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
Rank: 2/147
Findings: 3
Award: $3,865.13
π Selected for report: 2
π Solo Findings: 2
π Selected for report: 0x52
1905.4132 DAI - $1,905.41
Loss of treasury funds
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.
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.
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.
π Selected for report: 0x52
1905.4132 DAI - $1,905.41
Incorrect initial bond market price
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
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.
π Selected for report: zzzitron
Also found by: 0x040, 0x1f8b, 0x52, 0x85102, 0xDjango, 0xNazgul, 0xNineDec, 0xSky, 0xSmartContract, 0xkatana, 8olidity, Aymen0909, Bahurum, BipinSah, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chandr, Chom, CodingNameKiki, Deivitto, DimSon, Diraco, ElKu, EthLedger, Funen, GalloDaSballo, Guardian, IllIllI, JansenC, Jeiwan, Lambda, LeoS, Margaret, MasterCookie, PPrieditis, PaludoX0, Picodes, PwnPatrol, RaymondFam, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StevenL, The_GUILD, TomJ, Tomo, Trust, Waze, __141345__, ajtra, ak1, apostle0x01, aviggiano, bin2chen, bobirichman, brgltd, c3phas, cRat1st0s, carlitox477, cccz, ch13fd357r0y3r, cloudjunky, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, devtooligan, dipp, djxploit, durianSausage, eierina, enckrish, erictee, fatherOfBlocks, gogo, grGred, hansfriese, hyh, ignacio, indijanc, itsmeSTYJ, ladboy233, lukris02, martin, medikko, mics, natzuu, ne0n, nxrblsrpr, okkothejawa, oyc_109, p_crypt0, pfapostol, prasantgupta52, rajatbeladiya, rbserver, reassor, ret2basic, robee, rokinot, rvierdiiev, shenwilly, sikorico, sorrynotsorry, tnevler, tonisives, w0Lfrum, yixxas
54.3128 DAI - $54.31
Increased systematic risk to the treasury and near guaranteed loss
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.
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