Skip to content

Commit 329f006

Browse files
committed
docs(oracle): document upscaled price bound constants
Align PRICE_ORACLE.md with MINIMUM_PRICE_UPSCALED, MAX_CURRENT_PRICE_UPSCALED, and _clampPriceUpscaled().
1 parent be8cea6 commit 329f006

1 file changed

Lines changed: 29 additions & 19 deletions

File tree

docs/PRICE_ORACLE.md

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,8 @@ Manually sets the price (for initialization or emergency).
6969

7070
**Logic**:
7171
```solidity
72-
currentPriceUpScaled = _price << 10 // upscale by 2^10
73-
if (currentPriceUpScaled < minimumPriceUpscaled) {
74-
currentPriceUpScaled = minimumPriceUpscaled
75-
}
72+
_currentPriceUpScaled = uint64(_price) << 10 // upscale by 2^10
73+
currentPriceUpScaled = _clampPriceUpscaled(_currentPriceUpScaled)
7674
// Update PostageStamp
7775
PostageStamp.setPrice(currentPrice())
7876
emit PriceUpdate(currentPrice())
@@ -94,7 +92,7 @@ Automatically adjusts price based on redundancy (called by Redistribution).
9492
2. Cap redundancy at `targetRedundancy + maxConsideredExtraRedundancy`
9593
3. Apply change rate based on redundancy - target
9694
4. Apply maximum penalty for skipped rounds
97-
5. Enforce minimum price
95+
5. Clamp price to `[MINIMUM_PRICE_UPSCALED, MAX_CURRENT_PRICE_UPSCALED]`
9896
6. Update PostageStamp
9997
7. Emit event
10098

@@ -124,7 +122,10 @@ Pauses or unpauses price adjustments.
124122
Returns the current price (downscaled by 2^10).
125123

126124
#### minimumPrice()
127-
Returns the minimum price floor.
125+
Returns the minimum price floor (compile-time constant derived from `MINIMUM_PRICE_UPSCALED`).
126+
127+
#### MINIMUM_PRICE_UPSCALED() / MAX_CURRENT_PRICE_UPSCALED()
128+
Public constant getters for the upscaled price bounds used by `_clampPriceUpscaled()`.
128129

129130
#### currentRound()
130131
Returns the current round number: `block.number / 152`
@@ -134,7 +135,8 @@ Returns the current round number: `block.number / 152`
134135
```solidity
135136
uint16 targetRedundancy = 4; // Target chunks per node
136137
uint16 maxConsideredExtraRedundancy = 4; // Cap on extra redundancy
137-
uint32 minimumPriceUpscaled = 24000 << 10; // ~23.44 (downscaled)
138+
uint64 constant MINIMUM_PRICE_UPSCALED = 24000 << 10; // ~24000 (downscaled)
139+
uint64 constant MAX_CURRENT_PRICE_UPSCALED = uint64(type(uint32).max) << 10;
138140
uint32 priceBase = 1048576; // Base for change rate (2^20)
139141
```
140142

@@ -186,16 +188,24 @@ newPrice = (1049417 * 1000000) / 1048576 = 1000800
186188
// Increase of ~0.08%
187189
```
188190

189-
### Minimum Price Enforcement
191+
### Price Bounds Enforcement
192+
193+
Prices are clamped via `_clampPriceUpscaled()` after every manual or automatic update:
190194

191-
Prices are bounded from below:
192195
```solidity
193-
if (currentPriceUpScaled < minimumPriceUpscaled) {
194-
currentPriceUpScaled = minimumPriceUpscaled
196+
function _clampPriceUpscaled(uint64 priceUpScaled) private pure returns (uint64) {
197+
if (priceUpScaled < MINIMUM_PRICE_UPSCALED) {
198+
priceUpScaled = MINIMUM_PRICE_UPSCALED;
199+
}
200+
if (priceUpScaled > MAX_CURRENT_PRICE_UPSCALED) {
201+
priceUpScaled = MAX_CURRENT_PRICE_UPSCALED;
202+
}
203+
return priceUpScaled;
195204
}
196205
```
197206

198-
This prevents prices from becoming too low and disincentivizing storage.
207+
- **Minimum floor** prevents prices from becoming too low and disincentivizing storage.
208+
- **Maximum ceiling** ensures `(currentPriceUpScaled >> 10)` fits in `uint32`, so `currentPrice()` cannot silently truncate and under-report relative to the stored upscaled value.
199209

200210
## Integration with Other Contracts
201211

@@ -264,10 +274,11 @@ error UnexpectedZero(); // Redundancy must be > 0
264274
## Security Considerations
265275

266276
1. Minimum price floor prevents race-to-bottom pricing
267-
2. Maximum extra redundancy cap prevents excessive price increases
268-
3. One adjustment per round prevents manipulation
269-
4. Pausable for emergency stops
270-
5. Failed PostageStamp updates don't prevent oracle updates
277+
2. Maximum upscaled price cap keeps `currentPrice()` consistent with stored state
278+
3. Maximum extra redundancy cap prevents excessive price increases
279+
4. One adjustment per round prevents manipulation
280+
5. Pausable for emergency stops
281+
6. Failed PostageStamp updates don't prevent oracle updates
271282

272283
## Pause Mechanism
273284

@@ -300,9 +311,8 @@ function adjustPrice(redundancy):
300311
for each skipped round:
301312
newPrice = (changeRate[0] * newPrice) / priceBase
302313
303-
// Enforce minimum
304-
if (newPrice < minimumPriceUpscaled):
305-
newPrice = minimumPriceUpscaled
314+
// Clamp to upscaled bounds
315+
newPrice = _clampPriceUpscaled(newPrice)
306316
307317
currentPriceUpScaled = newPrice
308318
lastAdjustedRound = currentRoundNum

0 commit comments

Comments
 (0)