Olympus DAO contest - 0x52'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: 2/147

Findings: 3

Award: $3,865.13

🌟 Selected for report: 2

πŸš€ Solo Findings: 2

Findings Information

🌟 Selected for report: 0x52

Labels

bug
2 (Med Risk)
disagree with severity

Awards

1905.4132 DAI - $1,905.41

External Links

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol#L195-L268

Vulnerability details

Impact

Loss of treasury funds

Proof of Concept

https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/RANGE.sol#L133-L139

if (capacity_ < _range.high.threshold && _range.high.active) { // Set wall to inactive _range.high.active = false; _range.high.lastActive = uint48(block.timestamp); emit WallDown(true, block.timestamp, capacity_); }

_range.high.lastActive and _range.low.lastActive are only updated in RANGE.sol when _range.x.capacity < _range.x.threshold and the _range.x.active == true. After this is tripped, _range.x.active will be set to false, meaning that _range.x.lastActive will not be updated again until the wall is regenerated and capacity is restored.

https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol#L209-L214

if ( uint48(block.timestamp) >= RANGE.lastActive(true) + uint48(config_.regenWait) && _status.high.count >= config_.regenThreshold ) { _regenerate(true); }

If 1) the price were to sustain outside of the range (high volatility for volatile asset, black swan for stable) for longer than config_.regenWait and 2) config_regenThreshold satisfies the following equation:

config_.regenThreshold <= _config.regenObserve - config_.regenWait / frequency

then status.high.count could be greater than config.regenThreshold. This would trigger more funds to be deployed even though the price never came back inside the wall price.

In this scenario the wall price would be far from the true price of the asset leading to loss of treasury funds as it buys/sell at prices well above/below market price.

Tools Used

A check should be added to verify that the price is within the wall price before regenerating. Alternatively, config_.regenTheshold could be set to satisfy the following equation:

config_.regenThreshold > _config.regenObserve - config_.regenWait / frequency

This would eliminate the risk as status.high.count >= config.regenThreshold could never be true for a sustained period where current price is greater than the wall price.

#0 - Oighty

2022-09-02T19:37:24Z

This is valid. Our intended parameterization of the system would not be subject to this vulnerability, but it would be an issue if the system was incorrectly parameterized. Because it is an edge case, I'm not sure it is a high risk bug though.

#1 - Oighty

2022-09-02T19:40:26Z

Another potential fix is resetting the count to 0 and the observations array to new bool[](regenObserve) to clear out positive values from when a wall goes down. This could be done in the _updateCapacity() function by checking if the new capacity is under the threshold.

#2 - 0xean

2022-09-20T13:29:03Z

Going to downgrade to M as the external dependency is a configuration that is not planned to be used by the sponsor.

Findings Information

🌟 Selected for report: 0x52

Labels

bug
2 (Med Risk)
disagree with severity

Awards

1905.4132 DAI - $1,905.41

External Links

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/policies/Operator.sol#L363-L469

Vulnerability details

Impact

Incorrect initial bond market price

Proof of Concept

uint256 initialPrice = range.wall.high.price.mulDiv(bondScale, oracleScale); uint256 initialPrice = invWallPrice.mulDiv(bondScale, oracleScale);

In the above lines the initial prices are set to the wall price rather than the current price as indicated in documentation

Tools Used

Initial price should be updated to open bond market at current price rather than wall price

#0 - Oighty

2022-09-02T15:59:39Z

This is more of a design decision than a bug. However, we did make this change in the code prior to the audit (it didn't get reflected in the repo). @ind-igo not sure how you want to handle.

#1 - 0xean

2022-09-19T23:45:34Z

Going to award as M assuming no additional input from sponsor on the topic.

#2 - Oighty

2022-09-20T16:38:29Z

It does deviate from the spec so I guess that's appropriate. The system actually would work as-is, but would be less responsive to price movements into the cushions since the bond market would have to decay (which requires waiting) to reach the current market price vs. instantly providing a buy/sell at the current price.

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/b5e139d732eb4c07102f149fb9426d356af617aa/src/modules/RANGE.sol#L158-L178

Vulnerability details

Impact

Increased systematic risk to the treasury and near guaranteed loss

Proof of Concept

The Range-Bound Stability system is designed to increase OHM stability against a reserve asset by providing an upper and lower liquidity band to resist sudden changes. In the white paper it suggests that the treasury may implement RBS against a volatile asset such as ETH. Given the relative volatility of ETH and that bounds are set by a moving average. It is highly likely that the market price of ETH will frequently enter or move outside of the RBS bounds. In this case, the RBS is not functioning as intended because it is effectively trying to absorb the volatility of the reserve asset rather than the volatility of OHM. Arbitrageur will close the price gap at the expense of treasury funds, since the treasury will either be buying for too much or selling for too little. Given the relative difference in liquidity the RBS will be easily overpowered by market forces

During a black swan event ( i.e. UST collapse) that affects a treasury asset, the RBS will increase exposure to that asset. This puts a greater amount of treasury assets at risk and increases the losses of the treasury.

Tools Used

RBS assets should be chosen very carefully. It should never be a volatile asset and stablecoins should be highly trusted and battle-tested.

#0 - 0xLienid

2022-09-06T14:57:37Z

This is more of a policy issue than an inherent contract security issue, and as mentioned is an already known concern vector with the system. Definitely not medium risk given all of that, but technically true. Thoughts on severity if any @ind-igo?

#1 - ind-igo

2022-09-07T05:00:55Z

Agreed, this is policy issue, although good observation. It is however out of scope for this contest.

#2 - 0xean

2022-09-19T14:06:11Z

Going to downgrade to QA

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