Platform: Code4rena
Start Date: 07/08/2023
Pot Size: $36,500 USDC
Total HM: 11
Participants: 125
Period: 3 days
Judge: alcueca
Total Solo HM: 4
Id: 274
League: ETH
Rank: 76/125
Findings: 1
Award: $9.82
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: RED-LOTUS-REACH
Also found by: 0x3b, 0x4non, 0xCiphky, 0xDING99YA, 0xDetermination, 0xE1, 0xG0P1, 0xStalin, 0xWaitress, 0xbrett8571, 0xhacksmithh, 0xkazim, 0xmuxyz, 0xweb3boy, 14si2o_Flint, AlexCzm, Alhakista, Bube, Bughunter101, Deekshith99, Eeyore, Giorgio, HChang26, InAllHonesty, JP_Courses, KmanOfficial, MatricksDeCoder, Mike_Bello90, MrPotatoMagic, Naubit, QiuhaoLi, RHaO-sec, Raihan, Rolezn, SUPERMAN_I4G, Shubham, Silverskrrrt, Strausses, T1MOH, Topmark, Tripathi, Watermelon, _eperezok, aakansha, auditsea, audityourcontracts, ayden, carlos__alegre, castle_chain, cducrest, ch0bu, d23e, deadrxsezzz, deth, devival, erebus, fatherOfBlocks, halden, hassan-truscova, hpsb, hunter_w3b, imkapadia, immeas, jat, kaden, kaveyjoe, klau5, koxuan, kutugu, ladboy233, lanrebayode77, leasowillow, lsaudit, markus_ether, matrix_0wl, merlin, nemveer, ni8mare, nonseodion, oakcobalt, owadez, p_crypt0, pipidu83, piyushshukla, popular00, ppetrov, rjs, sandy, sl1, supervrijdag, tay054, thekmj, wahedtalash77, windhustler, zhaojie
9.8204 USDC - $9.82
Description
The non-upgradeable standard version of OpenZeppelin's library, such as Ownable
, Pausable
, Address
, Context
, SafeERC20
, ERC1967Upgrade
etc, are inherited / used by both the proxy and the implementation contracts.
As a result, when attempting to use the upgrades plugin mentioned, the following errors are raised:
Error: Contract `FiatTokenV1` is not upgrade safe contracts/v1/FiatTokenV1.sol:58: Variable `totalSupply_` is assigned an initial value Move the assignment to the initializer https://zpl.in/upgrades/error-004 contracts/v1/Pausable.sol:49: Variable `paused` is assigned an initial value Move the assignment to the initializer https://zpl.in/upgrades/error-004 contracts/v1/Ownable.sol:28: Contract `Ownable` has a constructor Define an initializer instead https://zpl.in/upgrades/error-001 contracts/util/Address.sol:186: Use of delegatecall is not allowed https://zpl.in/upgrades/error-002
Having reviewed these errors, none had any adversarial impact:
totalSupply_
and paused
are explictly assigned the default values 0
and false
the implementation contracts utilises the internal _transferOwnership()
in the initializer, thus transferring ownership to newOwner
regardless of who the current owner is
Address's
delegatecall
is only used by the ERC1967Upgrade
contract. Comparing both the Address
and ERC1967Upgrade
contracts against their upgradeable counterparts show similar behaviour (differences are some refactoring done to shift the delegatecall into the ERC1967Upgrade
contract).
Nevertheless, it would be safer to use the upgradeable versions of the library contracts to avoid unexpected behaviour.
Where applicable, use the contracts from @openzeppelin/contracts-upgradeable
instead of @openzeppelin/contracts
.
4 import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
https://github.com/code-423n4/2023-08-verwa/tree/main/src/VotingEscrow.sol#L4
Low-level calls that are unnecessary for the system should be avoided whenever possible because low-level calls behave differently from a contract-type call. For example;
address.call(abi.encodeWithSelector("fancy(bytes32)", mybytes))`` does not verify that a target is actually a contract, while ContractInterface(address).fancy(mybytes) does.
Additionally, when calling out to functions declared view/pure, the solidity compiler would actually perform a staticcall providing additional security guarantees while a low-level call does not. Similarly, return values have to be decoded manually when performing low-level calls.
179 (bool success, ) = msg.sender.call{value: cantoToSend}("");
https://github.com/code-423n4/2023-08-verwa/tree/main/src/LendingLedger.sol#L179
346 (bool success, ) = msg.sender.call{value: amountToSend}("");
https://github.com/code-423n4/2023-08-verwa/tree/main/src/VotingEscrow.sol#L346
The condition may be wrong in these cases, as when block.timestamp is equal to the compared > or < variable these blocks will not be executed.
70 if (t > block.timestamp) break; 82 if (t > block.timestamp) time_sum = t; 96 if (t > block.timestamp) break; 108 if (t > block.timestamp) time_weight[_gauge_addr] = t; 263 if (old_slope.end > block.timestamp) {
https://github.com/code-423n4/2023-08-verwa/tree/main/src/GaugeController.sol#L70
Consider limiting the number of iterations in for-loops that make external calls.
193 for (uint256 i = _fromEpoch; i <= _toEpoch; i += WEEK) {
https://github.com/code-423n4/2023-08-verwa/tree/main/src/LendingLedger.sol#L193
#0 - c4-judge
2023-08-22T13:33:30Z
alcueca marked the issue as grade-a