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: 131/199
Findings: 1
Award: $22.60
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
SafeCast
library to prevent unexpected overflows when casting from uint256
In the contract Equity.sol
two function adjustTotalVotes
takes an argument roundingLoss
of type uint256
and a variable lostVotes
of type uint256
and downcast them to type uint192
. Furthermore the function adjustRecipientVoteAnchor
in the same contract sets two variables of type uint256
which are recipientVotes
and newbalance
and downcast them to type uint64
while performing some arithmetic to calculate the voteAnchor
. However, since totalVotesAtAnchor
should not exceed 68-bits and voteAnchor
should not exceed 64-bits it is still considered as best practice to use OpenZepplin's SafeCast
library to prevent any unexpected overflows from happening.
Function adjustTotalVotes
:
adjustRecipientVoteAnchor
:Consider using OpenZeppelin’s SafeCast library to prevent unexpected overflows when casting from uint256.
In the contract Ownable.sol
it was observed that the function transferOwnership
does not check transfer to address(0)
which effectively burn the ownership.
/** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { setOwner(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function setOwner(address newOwner) internal { address oldOwner = owner; owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); }
The function transferOwnership
above takes the address of newOwner
as an argument and is directly passed to the function setOwner
. However, there is no checks in both of these functions to ensure that the newOwner
is not address(0)
. This means that the owner can transfer the ownership to address(0)
which effectively burn the ownership.
It is recommended to implement a validation check to ensure that the ownership is not transferred to address(0)
.
Example:
function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0), "New owner cannot be zero address"); setOwner(newOwner); }
votes
in the contracts Equity.sol
The issue with the votes
function is that it has two functions with the same name, which causes a name conflict. The first votes
function takes only one argument, which is the sender's address and returns the number of votes for the sender. The second votes
function takes two arguments, one sender's address, and an array of helper addresses, and returns the total number of votes for both the sender and the helper addresses.
This is problematic because the two functions have the same name, but different input parameters, which can lead to confusion and potential errors when calling the function. When calling the function, it may not be clear which version of the votes function is being called, especially if the arguments are not explicitly stated. This could result in unexpected behavior and may cause errors in the contract.
To resolve this issue, one of the votes
functions should be renamed to avoid the naming conflict. For example, the first function could be renamed votesForSender
to clarify its purpose, while the second function could remain as votes
since it takes both the sender and the helper addresses as arguments. By doing this, the contract code becomes more explicit and easy to understand.
votes
in the contract Equity.sol
The issue could allow an attacker to bypass the canVoteFor
function, which verifies that the sender is allowed to vote for their helpers. This could lead to the attacker being able to manipulate the votes of other users in the contract and potentially gain control over the voting process.
An attacker could create a helper account and call the votes
function with the sender's address and the helper's address. If the helper account is not authorized to vote for the sender, the canVoteFor function should return false and the transaction should revert. However, due to the vulnerability in the votes
function, the attacker would be able to bypass this check and get the total number of votes for the sender and the helper.
The canVoteFor
function should be called before calculating the votes for the sender and their helpers. Additionally, the function should include checks to ensure that helpers are unique and not equal to the sender.
#0 - c4-judge
2023-05-16T03:24:12Z
hansfriese marked the issue as grade-b
#1 - hansfriese
2023-05-16T03:24:24Z
L4 is invalid