Skip to content

Commit ba5431a

Browse files
Purely superficial change - reordering functions, tweaking comments, etc: zero behavioral impact. (Pushing it now to make the diffs of a big upcoming behavioral change easier to follow...)
1 parent cf6b67a commit ba5431a

File tree

4 files changed

+71
-63
lines changed

4 files changed

+71
-63
lines changed

contracts/IUSM.sol

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ abstract contract IUSM {
1515
function latestPrice() public virtual view returns (uint price, uint updateTime);
1616
function latestOraclePrice() public virtual view returns (uint price, uint updateTime);
1717
function ethPool() public virtual view returns (uint pool);
18+
function usmTotalSupply() public virtual view returns (uint supply); // Is there a way to scrap this and just use ERC20(Permit)'s totalSupply()?
19+
function fumTotalSupply() public virtual view returns (uint supply);
20+
function buySellAdjustment() public virtual view returns (uint adjustment);
1821
function ethBuffer(uint ethUsdPrice, uint ethInPool, uint usmSupply, WadMath.Round upOrDown) public virtual pure returns (int buffer);
1922
function debtRatio(uint ethUsdPrice, uint ethInPool, uint usmSupply) public virtual pure returns (uint ratio);
2023
function ethToUsm(uint ethUsdPrice, uint ethAmount, WadMath.Round upOrDown) public virtual pure returns (uint usmOut);
2124
function usmToEth(uint ethUsdPrice, uint usmAmount, WadMath.Round upOrDown) public virtual pure returns (uint ethOut);
22-
function usmTotalSupply() public virtual view returns (uint supply); // Is there a way to scrap this and just use ERC20(Permit)'s totalSupply()?
23-
function fumTotalSupply() public virtual view returns (uint supply);
2425
function usmPrice(Side side, uint ethUsdPrice, uint debtRatio_) public virtual view returns (uint price);
2526
function fumPrice(Side side, uint ethUsdPrice, uint ethInPool, uint usmSupply, uint fumSupply, uint adjustment) public virtual view returns (uint price);
26-
function buySellAdjustment() public virtual view returns (uint adjustment);
2727
}

contracts/USM.sol

+61-53
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
5858
fum = new FUM(this, optedOut_);
5959
}
6060

61-
/** PUBLIC AND EXTERNAL TRANSACTIONAL FUNCTIONS **/
61+
// ____________________ External transactional functions ____________________
6262

6363
/**
6464
* @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 {
126126
ethOut = _defundFum(from, to, fumToBurn, minEthOut);
127127
}
128128

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+
129140
function refreshPrice() public virtual override returns (uint price, uint updateTime) {
130141
uint adjustment;
131142
bool priceChanged;
@@ -136,14 +147,7 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
136147
}
137148
}
138149

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 ____________________
147151

148152
/**
149153
* @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 {
159163
return true;
160164
}
161165

162-
/** INTERNAL TRANSACTIONAL FUNCTIONS */
166+
// ____________________ Internal helper transactional functions (for functions above) ____________________
163167

164168
function _mintUsm(address to, uint minUsmOut) internal returns (uint usmOut)
165169
{
@@ -338,12 +342,14 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
338342
emit BuySellAdjustmentChanged(previous, newAdjustment);
339343
}
340344

341-
/** PUBLIC VIEW FUNCTIONS **/
345+
// ____________________ Public Oracle view functions ____________________
342346

343347
function latestPrice() public virtual override(IUSM, Oracle) view returns (uint price, uint updateTime) {
344348
(price, updateTime) = (storedPrice.value, storedPrice.timestamp);
345349
}
346350

351+
// ____________________ Public informational view functions ____________________
352+
347353
function latestOraclePrice() public virtual override view returns (uint price, uint updateTime) {
348354
(price, updateTime) = oracle.latestPrice();
349355
}
@@ -356,6 +362,28 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
356362
pool = address(this).balance;
357363
}
358364

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+
359387
/**
360388
* @notice Calculate the amount of ETH in the buffer.
361389
* @return buffer ETH buffer
@@ -397,14 +425,6 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
397425
ethOut = usmAmount.wadDiv(ethUsdPrice, upOrDown);
398426
}
399427

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-
408428
/**
409429
* @notice Calculate the *marginal* price of USM (in ETH terms) - that is, of the next unit, before the price start sliding.
410430
* @return price USM price in ETH terms
@@ -448,6 +468,28 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
448468
}
449469
}
450470

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+
451493
/**
452494
* @notice How much USM a minter currently gets back for ethIn ETH, accounting for adjustment and sliding prices.
453495
* @param ethIn The amount of ETH passed to mint()
@@ -557,38 +599,4 @@ contract USM is IUSM, Oracle, ERC20WithOptOut, Delegable {
557599
// Using this ending ETH mid price lowerBoundEthUsdPrice1, we can calc the actual average FUM sell price of the defund:
558600
avgFumSellPrice = fumPrice(IUSM.Side.Sell, lowerBoundEthUsdPrice1, ethQty0, usmQty0, fumQty0, adjustment0);
559601
}
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-
}
594602
}

contracts/USMView.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ contract USMView {
1515
usm = usm_;
1616
}
1717

18-
/** EXTERNAL VIEW FUNCTIONS */
18+
// ____________________ External informational view functions ____________________
1919

2020
/**
2121
* @notice Calculate the amount of ETH in the buffer.

test/03_USM.test.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ contract('USM', (accounts) => {
9191
return new BN(BigInt(Math.round(parseFloat(x) * WAD)))
9292
}
9393

94-
/* ____________________ Deployment ____________________ */
94+
// ____________________ Deployment ____________________
9595

9696
describe("mints and burns a static amount", () => {
9797
let oracle, usm, fum, usmView, ethPerFund, ethPerMint, bitOfEth, snapshot, snapshotId
@@ -149,7 +149,7 @@ contract('USM', (accounts) => {
149149
})
150150
})
151151

152-
/* ____________________ Minting and burning ____________________ */
152+
// ____________________ Minting and burning ____________________
153153

154154
describe("minting and burning", () => {
155155
let MAX_DEBT_RATIO
@@ -226,7 +226,7 @@ contract('USM', (accounts) => {
226226
usmSellPrice0 = await usmView.usmPrice(sides.SELL)
227227
})
228228

229-
/* ____________________ Minting FUM (aka fund()) ____________________ */
229+
// ____________________ Minting FUM (aka fund()) ____________________
230230

231231
it("calculates log/exp correctly", async () => {
232232
const w = await WadMath.new()
@@ -413,7 +413,7 @@ contract('USM', (accounts) => {
413413
totalFumSupply.should.be.bignumber.gt(totalFumSupply0)
414414
})
415415

416-
/* ____________________ Minting USM (aka mint()), at sliding price ____________________ */
416+
// ____________________ Minting USM (aka mint()), at sliding price ____________________
417417

418418
describe("with USM minted at sliding price", () => {
419419
let ethPoolM, priceM, debtRatioM, user2FumBalanceM, totalFumSupplyM, buySellAdjM, fumBuyPriceM,
@@ -530,7 +530,7 @@ contract('USM', (accounts) => {
530530
shouldEqualApprox(totalUsmSupply, targetTotalUsmSupply)
531531
})
532532

533-
/* ____________________ Burning FUM (aka defund()) ____________________ */
533+
// ____________________ Burning FUM (aka defund()) ____________________
534534

535535
it("allows burning FUM", async () => {
536536
const fumToBurn = user2FumBalance0.div(TWO) // defund 50% of the user's FUM
@@ -698,7 +698,7 @@ contract('USM', (accounts) => {
698698
await expectRevert(usm.defund(user2, user1, oneFum, 0, { from: user2 }), "Debt ratio > max")
699699
})
700700

701-
/* ____________________ Burning USM (aka burn()) ____________________ */
701+
// ____________________ Burning USM (aka burn()) ____________________
702702

703703
it("allows burning USM", async () => {
704704
const usmToBurn = user1UsmBalance0.div(TWO) // defund 50% of the user's USM

0 commit comments

Comments
 (0)