Olympus DAO contest - hansfriese's results

Version 3 of Olympus protocol, a decentralized floating currency.

General Information

Platform: Code4rena

Start Date: 25/08/2022

Pot Size: $75,000 USDC

Total HM: 35

Participants: 147

Period: 7 days

Judge: 0xean

Total Solo HM: 15

Id: 156

League: ETH

Olympus DAO

Findings Distribution

Researcher Performance

Rank: 20/147

Findings: 3

Award: $1,193.84

🌟 Selected for report: 2

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: hansfriese

Also found by: V_B, berndartmueller, csanuragjain, m9800, zzzitron

Labels

bug
duplicate
3 (High Risk)
sponsor confirmed

Awards

625.0708 DAI - $625.07

External Links

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Governance.sol#L216-L221 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Governance.sol#L302-L304

Vulnerability details

Impact

Currently, if users vote for the active proposal, the VOTES are transferred to the contract so that users can't vote or endorse other proposals while the voted proposal is active.

And the active proposal can be replaced only when the proposal is executed successfully or another proposal is activated after GRACE_PERIOD.

But activateProposal() requires at least 20% endorsements here, so it might be impossible to activate a new proposal forever if the current active proposal involves more than 80% of total votes.

Proof of Concept

The below scenario would be possible.

  1. Proposal 1 was submitted and activated successfully.
  2. Let's assume 81% of the total votes voted for this proposal. Yes = 47%, No = 34%
  3. This proposal can't be executed for this requirement because 47% - 34% = 13% < 33%.
  4. Currently the contract contains more than 81% of total votes and users have at most 19% in total.
  5. Also users can't reclaim their votes among 81% while Proposal 1 is active.
  6. So even if a user who has 1% votes submits a new proposal, it's impossible to activate because of this require().
  7. So it's impossible to delete Proposal 1 from an active proposal and there won't be other active proposal forever.

Tools Used

Solidity Visual Developer of VSCode

I think we should add one more constant like EXECUTION_EXPIRE = 2 weeks so that voters can reclaim their votes after this period even if the proposal is active.

I am not sure we can use the current GRACE_PERIOD for that purpose.

So reclaimVotes() should be modified like below.

function reclaimVotes(uint256 proposalId_) external { uint256 userVotes = userVotesForProposal[proposalId_][msg.sender]; if (userVotes == 0) { revert CannotReclaimZeroVotes(); } if (proposalId_ == activeProposal.proposalId) { if (block.timestamp < activeProposal.activationTimestamp + EXECUTION_EXPIRE) //+++++++++++++++++++++++++++++++++ { revert CannotReclaimTokensForActiveVote(); } } if (tokenClaimsForProposal[proposalId_][msg.sender] == true) { revert VotingTokensAlreadyReclaimed(); } tokenClaimsForProposal[proposalId_][msg.sender] = true; VOTES.transferFrom(address(this), msg.sender, userVotes); }

#0 - csanuragjain

2022-09-02T06:21:36Z

#1 - fullyallocated

2022-09-04T02:27:35Z

This is probably the best response for this issue.

#2 - 0xean

2022-09-19T14:58:47Z

using this as the primary issue.

Findings Information

🌟 Selected for report: hansfriese

Also found by: datapunk, itsmeSTYJ

Labels

bug
2 (Med Risk)
disagree with severity

Awards

514.4616 DAI - $514.46

External Links

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/RANGE.sol#L80 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/RANGE.sol#L244-L250 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/modules/RANGE.sol#L264 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Operator.sol#L134 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Operator.sol#L518

Vulnerability details

Impact

Inconsistant parameter requirements between constructor and Set() functions in RANGE.sol and Operator.sol.

The contracts might work unexpectedly when the params are set improperly using constructor().

Proof of Concept

File: 2022-08-olympus\src\modules\RANGE.sol 242: function setSpreads(uint256 cushionSpread_, uint256 wallSpread_) external permissioned { 243: // Confirm spreads are within allowed values 244: if ( 245: wallSpread_ > 10000 || 246: wallSpread_ < 100 || 247: cushionSpread_ > 10000 || 248: cushionSpread_ < 100 || 249: cushionSpread_ > wallSpread_ 250: ) revert RANGE_InvalidParams(); 251: 252: // Set spreads 253: _range.wall.spread = wallSpread_; 254: _range.cushion.spread = cushionSpread_; 255: 256: emit SpreadsChanged(wallSpread_, cushionSpread_); 257: }
File: 2022-08-olympus\src\modules\RANGE.sol 263: function setThresholdFactor(uint256 thresholdFactor_) external permissioned { 264: if (thresholdFactor_ > 10000 || thresholdFactor_ < 100) revert RANGE_InvalidParams(); 265: thresholdFactor = thresholdFactor_; 266: 267: emit ThresholdFactorChanged(thresholdFactor_); 268: } 269:
File: 2022-08-olympus\src\policies\Operator.sol 516: function setCushionFactor(uint32 cushionFactor_) external onlyRole("operator_policy") { 517: /// Confirm factor is within allowed values 518: if (cushionFactor_ > 10000 || cushionFactor_ < 100) revert Operator_InvalidParams(); 519: 520: /// Set factor 521: _config.cushionFactor = cushionFactor_; 522: 523: emit CushionFactorChanged(cushionFactor_); 524: } 525:

Tools Used

Solidity Visual Developer of VSCode

Recommend adding same validation for the parameters between constructor() and Set() functions.

#0 - Oighty

2022-09-07T00:46:33Z

Agree that the constructor should validate these parameters, but it is only an issue if configured improperly.

#1 - 0xean

2022-09-19T14:17:59Z

while I am typically weary of marking input validations as medium severity, I do think in this case its warranted as it directly leads to malfunctions at the protocol level and it seems that the sponsors thought it important enough to add the checks elsewhere. Hard call, but will award it at medium sev.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter