@@ -58,7 +58,7 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
58
58
fum = new FUM (this , optedOut_);
59
59
}
60
60
61
- /** PUBLIC AND EXTERNAL TRANSACTIONAL FUNCTIONS **/
61
+ // ____________________ External transactional functions ____________________
62
62
63
63
/**
64
64
* @notice Mint new USM, sending it to the given address, and only if the amount minted >= minUsmOut. The amount of ETH is
@@ -126,6 +126,17 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
126
126
ethOut = _defundFum (from, to, fumToBurn, minEthOut);
127
127
}
128
128
129
+ /**
130
+ * @notice If anyone sends ETH here, assume they intend it as a `mint`.
131
+ * If decimals 8 to 11 (included) of the amount of Ether received are `0000` then the next 7 will
132
+ * be parsed as the minimum Ether price accepted, with 2 digits before and 5 digits after the comma.
133
+ */
134
+ receive () external payable {
135
+ _mintUsm (msg .sender , MinOut.parseMinTokenOut (msg .value ));
136
+ }
137
+
138
+ // ____________________ Public transactional functions ____________________
139
+
129
140
function refreshPrice () public virtual override returns (uint price , uint updateTime ) {
130
141
uint adjustment;
131
142
bool priceChanged;
@@ -136,14 +147,7 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
136
147
}
137
148
}
138
149
139
- /**
140
- * @notice If anyone sends ETH here, assume they intend it as a `mint`.
141
- * If decimals 8 to 11 (included) of the amount of Ether received are `0000` then the next 7 will
142
- * be parsed as the minimum Ether price accepted, with 2 digits before and 5 digits after the comma.
143
- */
144
- receive () external payable {
145
- _mintUsm (msg .sender , MinOut.parseMinTokenOut (msg .value ));
146
- }
150
+ // ____________________ Internal ERC20 transactional functions ____________________
147
151
148
152
/**
149
153
* @notice If a user sends USM tokens directly to this contract (or to the FUM contract), assume they intend it as a `burn`.
@@ -159,7 +163,7 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
159
163
return true ;
160
164
}
161
165
162
- /** INTERNAL TRANSACTIONAL FUNCTIONS */
166
+ // ____________________ Internal helper transactional functions (for functions above) ____________________
163
167
164
168
function _mintUsm (address to , uint minUsmOut ) internal returns (uint usmOut )
165
169
{
@@ -338,12 +342,14 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
338
342
emit BuySellAdjustmentChanged (previous, newAdjustment);
339
343
}
340
344
341
- /** PUBLIC VIEW FUNCTIONS **/
345
+ // ____________________ Public Oracle view functions ____________________
342
346
343
347
function latestPrice () public virtual override (IUSM, Oracle) view returns (uint price , uint updateTime ) {
344
348
(price, updateTime) = (storedPrice.value, storedPrice.timestamp);
345
349
}
346
350
351
+ // ____________________ Public informational view functions ____________________
352
+
347
353
function latestOraclePrice () public virtual override view returns (uint price , uint updateTime ) {
348
354
(price, updateTime) = oracle.latestPrice ();
349
355
}
@@ -356,6 +362,28 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
356
362
pool = address (this ).balance;
357
363
}
358
364
365
+ function usmTotalSupply () public override view returns (uint supply ) {
366
+ supply = totalSupply ();
367
+ }
368
+
369
+ function fumTotalSupply () public override view returns (uint supply ) {
370
+ supply = fum.totalSupply ();
371
+ }
372
+
373
+ /**
374
+ * @notice The current min FUM buy price, equal to the stored value decayed by time since minFumBuyPriceTimestamp.
375
+ * @return mfbp The minFumBuyPrice, in ETH terms
376
+ */
377
+ function minFumBuyPrice () public view returns (uint mfbp ) {
378
+ if (storedMinFumBuyPrice.value != 0 ) {
379
+ uint numHalvings = (block .timestamp - storedMinFumBuyPrice.timestamp).wadDivDown (MIN_FUM_BUY_PRICE_HALF_LIFE);
380
+ uint decayFactor = numHalvings.wadHalfExp ();
381
+ mfbp = uint256 (storedMinFumBuyPrice.value).wadMulUp (decayFactor);
382
+ } // Otherwise just returns 0
383
+ }
384
+
385
+ // ____________________ Public helper pure functions (for functions above) ____________________
386
+
359
387
/**
360
388
* @notice Calculate the amount of ETH in the buffer.
361
389
* @return buffer ETH buffer
@@ -397,14 +425,6 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
397
425
ethOut = usmAmount.wadDiv (ethUsdPrice, upOrDown);
398
426
}
399
427
400
- function usmTotalSupply () public override view returns (uint supply ) {
401
- supply = totalSupply ();
402
- }
403
-
404
- function fumTotalSupply () public override view returns (uint supply ) {
405
- supply = fum.totalSupply ();
406
- }
407
-
408
428
/**
409
429
* @notice Calculate the *marginal* price of USM (in ETH terms) - that is, of the next unit, before the price start sliding.
410
430
* @return price USM price in ETH terms
@@ -448,6 +468,28 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
448
468
}
449
469
}
450
470
471
+ /**
472
+ * @notice The current buy/sell adjustment, equal to the stored value decayed by time since buySellAdjustmentTimestamp. This
473
+ * adjustment is intended as a measure of "how long-ETH recent user activity has been", so that we can slide price
474
+ * accordingly: if recent activity was mostly long-ETH (fund() and burn()), raise FUM buy price/reduce USM sell price; if
475
+ * recent activity was short-ETH (defund() and mint()), reduce FUM sell price/raise USM buy price. We use "it reduced debt
476
+ * ratio" as a rough proxy for "the operation was long-ETH".
477
+ *
478
+ * (There is one odd case: when debt ratio > 100%, a *short*-ETH mint() will actually reduce debt ratio. This does no real
479
+ * harm except to make fast-succession mint()s and fund()s in such > 100% cases a little more expensive than they would be.)
480
+ *
481
+ * @return adjustment The sliding-price buy/sell adjustment
482
+ */
483
+ function buySellAdjustment () public override view returns (uint adjustment ) {
484
+ uint numHalvings = (block .timestamp - storedBuySellAdjustment.timestamp).wadDivDown (BUY_SELL_ADJUSTMENT_HALF_LIFE);
485
+ uint decayFactor = numHalvings.wadHalfExp (10 );
486
+ // Here we use the idea that for any b and 0 <= p <= 1, we can crudely approximate b**p by 1 + (b-1)p = 1 + bp - p.
487
+ // Eg: 0.6**0.5 pulls 0.6 "about halfway" to 1 (0.8); 0.6**0.25 pulls 0.6 "about 3/4 of the way" to 1 (0.9).
488
+ // So b**p =~ b + (1-p)(1-b) = b + 1 - b - p + bp = 1 + bp - p.
489
+ // (Don't calculate it as 1 + (b-1)p because we're using uints, b-1 can be negative!)
490
+ adjustment = WAD + uint256 (storedBuySellAdjustment.value).wadMulDown (decayFactor) - decayFactor;
491
+ }
492
+
451
493
/**
452
494
* @notice How much USM a minter currently gets back for ethIn ETH, accounting for adjustment and sliding prices.
453
495
* @param ethIn The amount of ETH passed to mint()
@@ -557,38 +599,4 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
557
599
// Using this ending ETH mid price lowerBoundEthUsdPrice1, we can calc the actual average FUM sell price of the defund:
558
600
avgFumSellPrice = fumPrice (IUSM.Side.Sell, lowerBoundEthUsdPrice1, ethQty0, usmQty0, fumQty0, adjustment0);
559
601
}
560
-
561
- /**
562
- * @notice The current min FUM buy price, equal to the stored value decayed by time since minFumBuyPriceTimestamp.
563
- * @return mfbp The minFumBuyPrice, in ETH terms
564
- */
565
- function minFumBuyPrice () public view returns (uint mfbp ) {
566
- if (storedMinFumBuyPrice.value != 0 ) {
567
- uint numHalvings = (block .timestamp - storedMinFumBuyPrice.timestamp).wadDivDown (MIN_FUM_BUY_PRICE_HALF_LIFE);
568
- uint decayFactor = numHalvings.wadHalfExp ();
569
- mfbp = uint256 (storedMinFumBuyPrice.value).wadMulUp (decayFactor);
570
- } // Otherwise just returns 0
571
- }
572
-
573
- /**
574
- * @notice The current buy/sell adjustment, equal to the stored value decayed by time since buySellAdjustmentTimestamp. This
575
- * adjustment is intended as a measure of "how long-ETH recent user activity has been", so that we can slide price
576
- * accordingly: if recent activity was mostly long-ETH (fund() and burn()), raise FUM buy price/reduce USM sell price; if
577
- * recent activity was short-ETH (defund() and mint()), reduce FUM sell price/raise USM buy price. We use "it reduced debt
578
- * ratio" as a rough proxy for "the operation was long-ETH".
579
- *
580
- * (There is one odd case: when debt ratio > 100%, a *short*-ETH mint() will actually reduce debt ratio. This does no real
581
- * harm except to make fast-succession mint()s and fund()s in such > 100% cases a little more expensive than they would be.)
582
- *
583
- * @return adjustment The sliding-price buy/sell adjustment
584
- */
585
- function buySellAdjustment () public override view returns (uint adjustment ) {
586
- uint numHalvings = (block .timestamp - storedBuySellAdjustment.timestamp).wadDivDown (BUY_SELL_ADJUSTMENT_HALF_LIFE);
587
- uint decayFactor = numHalvings.wadHalfExp (10 );
588
- // Here we use the idea that for any b and 0 <= p <= 1, we can crudely approximate b**p by 1 + (b-1)p = 1 + bp - p.
589
- // Eg: 0.6**0.5 pulls 0.6 "about halfway" to 1 (0.8); 0.6**0.25 pulls 0.6 "about 3/4 of the way" to 1 (0.9).
590
- // So b**p =~ b + (1-p)(1-b) = b + 1 - b - p + bp = 1 + bp - p.
591
- // (Don't calculate it as 1 + (b-1)p because we're using uints, b-1 can be negative!)
592
- adjustment = WAD + uint256 (storedBuySellAdjustment.value).wadMulDown (decayFactor) - decayFactor;
593
- }
594
602
}
0 commit comments