Platform: Code4rena
Start Date: 13/01/2022
Pot Size: $75,000 USDC
Total HM: 9
Participants: 27
Period: 7 days
Judge: leastwood
Total Solo HM: 5
Id: 73
League: ETH
Rank: 9/27
Findings: 2
Award: $1,750.00
🌟 Selected for report: 3
🚀 Solo Findings: 0
🌟 Selected for report: sirhashalot
Also found by: Dravee, Jujic, WatchPug, aga7hokakological, defsec, gzeon, p4st13r4, robee
0.0387 LPT - $1.43
3.9418 USDC - $3.94
sirhashalot
Strings are broken into 32 byte chunks for operations. Revert error strings over 32 bytes therefore consume extra gas than shorter strings, as documented publicly.
There are dozens of examples of this gas optimization opportunity in the project, but some examples of this issue include:
Reducing revert error strings to under 32 bytes decreases deployment time gas and runtime gas when the revert condition is met. Alternatively, use custom errors, introduced in Solidity 0.8.4: https://blog.soliditylang.org/2021/04/21/custom-errors/
#0 - yondonfu
2022-02-01T17:31:42Z
🌟 Selected for report: sirhashalot
0.8082 LPT - $29.97
82.4134 USDC - $82.41
sirhashalot
The ControlledGateway.sol contract specifies a custom "GOVERNOR_ROLE" value that is assigned to the _msgsender when the contract is deployed. There is no need to create a custom role when only one role is used in the contract. This custom "GOVERNOR_ROLE" could be replaced with the built-in "DEFAULT_ADMIN_ROLE" value, which is the approach in the contract L1/escrow/L1Escrow.sol.
The custom role is created on line 13 of ControlledGateway.sol
Remove the GOVERNOR_ROLE role in ControlledGateway.sol and use the built-in DEFAULT_ADMIN_ROLE role to save gas
#0 - yondonfu
2022-02-01T13:11:24Z
🌟 Selected for report: 0x0x0x
Also found by: sirhashalot
0.3637 LPT - $13.49
37.086 USDC - $37.09
sirhashalot
The currentBondingRate variable in the Minter.sol contract of the livepeer/protocol project is initialized to a value of 0. Since currentBondingRate is a uint256, the default value is zero per Solidity docs: https://docs.soliditylang.org/en/latest/control-structures.html#default-value
Setting a variable to the default value it already contains is unnecessary. Removing this line would save gas.
uint256 currentBondingRate = 0;
Modify the initialization of currentBondingRate to:
uint256 currentBondingRate;
#0 - kautukkundan
2022-02-01T19:12:41Z
duplicate: going in favor of #215
🌟 Selected for report: sirhashalot
11.3746 LPT - $421.77
1159.9028 USDC - $1,159.90
sirhashalot
Polls require the proposer to burn tokens, so they are a serious matter. However, the vote() function in Poll.sol of the primary Livepeer project has several flaws:
These flaws allow an attacker to have unlimited votes, deciding the winning result of the poll. Even if malicious activity is detected, the tokens for the poll have already been burned and are irretrievable.
The scope of this contest was defined below. Since this poll voting issue is from "those contracts", I considered it in scope.
The recommendation for wardens is to focus on the LIP-73 contracts - links to the protocol contracts are provided as well for background/reference, however, if there are any findings surfaced in those contracts during the contest those are certainly welcome as well.
The relevant code is:
modifier isActive() { require(block.number <= endBlock, "poll is over"); _; } /** * @dev Vote for the poll's proposal. * Reverts if the poll period is over. * @param _choiceID the ID of the option to vote for */ function vote(uint256 _choiceID) external isActive { emit Vote(msg.sender, _choiceID); }
This vote mechanism is very simple and lacks proper checks. Consider using a more robust and tested voting mechanism, such as OpenZeppelin's Governance contract or Compound's GovernorAlpha or GovernorBravo contracts. In order to make it easier to undo a poll that was attacked, consider depositing the tokens for the poll creation into a governance multisig wallet instead of burning them, to allow for easier recovery from poll manipulation.
#0 - yondonfu
2022-01-24T02:09:13Z
Severity: 1 (Low)
The tallying of votes is handled off-chain [1] and the indexer apply rules for which votes count and how much their weight is. We acknowledge that this could've been made clearer in the contest repo though so marking as 1 (Low).
[1] https://github.com/livepeer/LIPs/blob/master/LIPs/LIP-19.md
#1 - 0xleastwood
2022-01-29T11:13:10Z
I think the sponsor is correct here. Vote validation is done off-chain, but further documentation could be made here so marking as low
.