Platform: Code4rena
Start Date: 23/06/2023
Pot Size: $60,500 USDC
Total HM: 31
Participants: 132
Period: 10 days
Judge: 0xean
Total Solo HM: 10
Id: 254
League: ETH
Rank: 19/132
Findings: 4
Award: $563.69
🌟 Selected for report: 3
🚀 Solo Findings: 0
104.6043 USDC - $104.60
As a result voting process is broken, as it won't execute proposals with most of forVotes
. But instead it will execute proposals with most of againstVotes
.
It returns whether number of votes with support = 1 is greater than with support = 0
function _voteSucceeded(uint256 proposalId) internal view override returns (bool){ return proposalData[proposalId].supportVotes[1] > proposalData[proposalId].supportVotes[0]; }
However support = 1 means againstVotes
, and support = 0 means forVotes
:
https://github.com/code-423n4/2023-06-lybra/blob/26915a826c90eeb829863ec3851c3c785800594b/contracts/lybra/governance/LybraGovernance.sol#L120-L122
function proposals(uint256 proposalId) external view returns (...) { ... forVotes = proposalData[proposalId].supportVotes[0]; againstVotes = proposalData[proposalId].supportVotes[1]; abstainVotes = proposalData[proposalId].supportVotes[2]; ... }
Manual Review
Swap 1 and 0:
function _voteSucceeded(uint256 proposalId) internal view override returns (bool){ return proposalData[proposalId].supportVotes[0] > proposalData[proposalId].supportVotes[1]; }
Governance
#0 - c4-pre-sort
2023-07-03T23:12:40Z
JeffCX marked the issue as primary issue
#1 - c4-sponsor
2023-07-14T10:07:06Z
LybraFinance marked the issue as sponsor confirmed
#2 - c4-judge
2023-07-26T01:38:17Z
0xean marked the issue as satisfactory
#3 - c4-judge
2023-07-28T19:48:35Z
0xean marked the issue as selected for report
🌟 Selected for report: T1MOH
Also found by: Iurii3, LokiThe5th, josephdara, skyge, squeaky_cactus, yjrwkk, zambody
287.8659 USDC - $287.87
For some reason it is calculated as sum of againstVotes and abstainVotes instead of totalVotes on proposal. As the result, quorum will be reached only if >=1/3 of all votes are abstain or against, which doesn't make sense.
Number of votes with support = 1 and support = 2 is summed up
function _quorumReached(uint256 proposalId) internal view override returns (bool){ return proposalData[proposalId].supportVotes[1] + proposalData[proposalId].supportVotes[2] >= quorum(proposalSnapshot(proposalId)); }
However support = 1 means against votes, support = 2 means abstain votes: https://github.com/code-423n4/2023-06-lybra/blob/26915a826c90eeb829863ec3851c3c785800594b/contracts/lybra/governance/LybraGovernance.sol#L120-L122
function proposals(uint256 proposalId) external view returns (...) { ... forVotes = proposalData[proposalId].supportVotes[0]; againstVotes = proposalData[proposalId].supportVotes[1]; abstainVotes = proposalData[proposalId].supportVotes[2]; ... }
Manual review
Use totalVotes:
function _quorumReached(uint256 proposalId) internal view override returns (bool){ return proposalData[proposalId].totalVotes >= quorum(proposalSnapshot(proposalId)); }
Governance
#0 - c4-pre-sort
2023-07-04T02:23:22Z
JeffCX marked the issue as primary issue
#1 - c4-sponsor
2023-07-14T10:08:02Z
LybraFinance marked the issue as sponsor confirmed
#2 - c4-judge
2023-07-26T01:40:01Z
0xean marked the issue as satisfactory
#3 - c4-judge
2023-07-28T19:50:20Z
0xean marked the issue as selected for report
🌟 Selected for report: Musaka
Also found by: 0xhacksmithh, 0xnev, CrypticShepherd, LuchoLeonel1, T1MOH, bytes032, cccz, devival, josephdara, ktg, squeaky_cactus
29.0567 USDC - $29.06
3 blocks is too small for voting. It opens opportunity to manipulate voting in extreme market conditions for example.
function votingPeriod() public pure override returns (uint256){ return 3; } function CLOCK_MODE() public override view returns (string memory){ require(clock() == block.number, "Votes: broken clock mode"); return "mode=blocknumber&from=default"; }
Manual Review
Consider increasing voting period.
Governance
#0 - c4-pre-sort
2023-07-04T14:13:35Z
JeffCX marked the issue as duplicate of #268
#1 - c4-pre-sort
2023-07-11T21:27:17Z
JeffCX marked the issue as duplicate of #228
#2 - c4-pre-sort
2023-07-11T21:27:54Z
JeffCX marked the issue as duplicate of #268
#3 - c4-judge
2023-07-28T15:43:58Z
0xean marked the issue as satisfactory
142.156 USDC - $142.16
getBadCollateralRatio()
will revert because of underflow, if vaultBadCollateralRatio[pool]
and vaultSafeCollateralRatio[pool]
are set to 0 (i.e. using default ratios 150% and 130% accordingly).
It blocks liquidation flow.
1e19 is decremented from value vaultSafeCollateralRatio[pool]
function getBadCollateralRatio(address pool) external view returns(uint256) { if(vaultBadCollateralRatio[pool] == 0) return vaultSafeCollateralRatio[pool] - 1e19; return vaultBadCollateralRatio[pool]; }
However vaultSafeCollateralRatio[pool]
can be set to 0, which should mean 160%:
function getSafeCollateralRatio( address pool ) external view returns (uint256) { if (vaultSafeCollateralRatio[pool] == 0) return 160 * 1e18; return vaultSafeCollateralRatio[pool]; }
As the result incorrect accounting block liquidation when using default values.
Also I think this is similar issue, but different impact, therefore describe in this issue. BadCollateralRatio can't be set when SafeCollateralRatio is default, as newRatio must be less than 10%: https://github.com/code-423n4/2023-06-lybra/blob/5d70170f2c68dbd3f7b8c0c8fd6b0b2218784ea6/contracts/lybra/configuration/LybraConfigurator.sol#L127
function setBadCollateralRatio(address pool, uint256 newRatio) external onlyRole(DAO) { require(newRatio >= 130 * 1e18 && newRatio <= 150 * 1e18 && newRatio <= vaultSafeCollateralRatio[pool] + 1e19, "LNA"); ... }
Manual Review
Instead of internal accessing variables, use functions getSafeCollateralRatio()
and getBadCollateralRatio()
in all the occurences, because variables can be zero.
Invalid Validation
#0 - c4-pre-sort
2023-07-08T21:03:21Z
JeffCX marked the issue as duplicate of #926
#1 - c4-judge
2023-07-28T15:36:05Z
0xean marked the issue as satisfactory
#2 - c4-judge
2023-07-28T19:43:05Z
0xean changed the severity to 2 (Med Risk)
#3 - c4-judge
2023-07-28T19:56:07Z
0xean marked the issue as selected for report
#4 - c4-sponsor
2023-07-29T11:28:27Z
LybraFinance marked the issue as sponsor confirmed