Platform: Code4rena
Start Date: 12/08/2022
Pot Size: $35,000 USDC
Total HM: 10
Participants: 126
Period: 3 days
Judge: Justin Goro
Total Solo HM: 3
Id: 154
League: ETH
Rank: 95/126
Findings: 1
Award: $29.89
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: oyc_109
Also found by: 0x1f8b, 0x52, 0xDjango, 0xLovesleep, 0xNazgul, 0xNineDec, 0xbepresent, 0xmatt, 0xsolstars, Aymen0909, Bahurum, Bnke0x0, CertoraInc, Chom, CodingNameKiki, DecorativePineapple, Deivitto, Dravee, ElKu, Funen, GalloDaSballo, IllIllI, JC, JohnSmith, Junnon, KIntern_NA, Lambda, LeoS, MiloTruck, Noah3o6, PaludoX0, RedOneN, Respx, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Sm4rty, TomJ, Vexjon, Waze, Yiko, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, auditor0517, bin2chen, bobirichman, brgltd, bulej93, byndooa, c3phas, cRat1st0s, cryptphi, csanuragjain, d3e4, defsec, delfin454000, djxploit, durianSausage, ellahi, erictee, exd0tpy, fatherOfBlocks, gogo, jonatascm, ladboy233, medikko, mics, natzuu, neumo, p_crypt0, paribus, pfapostol, rbserver, reassor, ret2basic, robee, rokinot, rvierdiiev, sach1r0, saneryee, seyni, sikorico, simon135, sseefried, wagmi, wastewa
29.8918 USDC - $29.89
https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/features/Blocklist.sol#L9 https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/features/Blocklist.sol#L5
Could lead to undesired behaviour when interacting with VotingEscrow.sol and specifically, with the 'checkBlocklist()' modifier.
Due to time constraints, I cannot test extent of the impact on this (and have rated a medium out of hesitance and to draw attention), but provided a list of affected areas below:
checkBlocklist() modifier: https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/VotingEscrow.sol#L126
Blocklist contract does not implement IBlocklist.sol as expected
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import { IVotingEscrow } from "../interfaces/IVotingEscrow.sol"; /// @title Blocklist Checker implementation. /// @notice Checks if an address is blocklisted /// @dev This is a basic implementation using a mapping for address => bool contract Blocklist { mapping(address => bool) private _blocklist; address public manager; address public ve; constructor(address _manager, address _ve) { manager = _manager; ve = _ve; }
VS code and conversing with @elnilz on discord to confirm that this is an oversight.
Add the import and the 'is' keyword as follows:
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.3; import { IVotingEscrow } from "../interfaces/IVotingEscrow.sol"; import {IBlocklist} from "../interfaces/IBlocklist.sol"; /// @title Blocklist Checker implementation. /// @notice Checks if an address is blocklisted /// @dev This is a basic implementation using a mapping for address => bool contract Blocklist is IBlocklist { mapping(address => bool) private _blocklist; address public manager; address public ve; constructor(address _manager, address _ve) { manager = _manager; ve = _ve; }
locked is set to locked[msg.sender] https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/VotingEscrow.sol#L499
oldUnlockTime is set to locked_.end https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/VotingEscrow.sol#L506
locked_.end is set to unlock_time (the function param) https://github.com/code-423n4/2022-08-fiatdao/blob/fece3bdb79ccacb501099c24b60312cd0b2e4bb2/contracts/VotingEscrow.sol#L507
IF delegatee is msg.sender and so long as oldUnlockTime is greater than block.timestamp (not expired):
LockedBalance oldLocked = copyLock(locked) old_locked.end=unlock_time
checkpoint(msg.sender, oldLocked, locked_)
Any logic using oldLock could be impacted by this bug, since the oldLock.end would be incorrect.
Owing to a lack of time to find a potential for loss of funds through this logic error in the current contract, however, with respect to the potential for knock-on effects of biases and slopes being calculated incorrectly for oldLock as a result of this bug, I have labelled it as a 'low/medium' severity bug.
Additionally, balanceOfAt() and totalSupplyAt() functions would be affected by this bug.
Any contracts interacting with VotingEscrow.sol, unaware of this bug but performing calculations or logic functions with a checkpoint, would also be incorrect as it stands.
Visual studio code and confirming with @elnilz, who kindly provided the spec (https://github.com/code-423n4/2022-08-fiatdao/blob/main/CheckpointMath.md#increaseunlocktime) to confirm this is indeed a bug.
Owner could be added to blocklist by calling updateBlocklist(owner) assuming the owner is not an EOA
Add a requirement that address being added to blocklist is not owner
require(addr != msg.sender, "owner would be blocked!")
The penalty recipient could be set to zero address, meaning that any penalties that ought to be received could be lost.
Create a default penalty recipient, which the owner can control.
Alternatively, add a:
require(addr != address(0), "Penalty would be lost")
such that the transaction fails and penalties don't get lost.