Skip to content

Commit 0f81ee3

Browse files
authored
Merge pull request #770 from reserve-protocol/polish-backing-overview
FacadeRead.backingOverview nits
2 parents ae516a4 + 24e1778 commit 0f81ee3

File tree

3 files changed

+64
-24
lines changed

3 files changed

+64
-24
lines changed

contracts/facade/FacadeRead.sol

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,35 @@ contract FacadeRead is IFacadeRead {
253253
uint256 supply = rToken.totalSupply();
254254
if (supply == 0) return (0, 0);
255255

256-
// {BU}
257-
uint192 basketsNeeded = rToken.basketsNeeded();
258-
259-
// {BU}
260-
BasketRange memory buRange = basketRange(rToken, basketsNeeded);
256+
uint192 basketsNeeded = rToken.basketsNeeded(); // {BU}
257+
uint192 uoaNeeded; // {UoA}
258+
uint192 uoaHeldInBaskets; // {UoA}
259+
{
260+
(address[] memory basketERC20s, uint256[] memory quantities) = rToken
261+
.main()
262+
.basketHandler()
263+
.quote(basketsNeeded, FLOOR);
264+
265+
IAssetRegistry reg = rToken.main().assetRegistry();
266+
IBackingManager bm = rToken.main().backingManager();
267+
for (uint256 i = 0; i < basketERC20s.length; i++) {
268+
IAsset asset = reg.toAsset(IERC20(basketERC20s[i]));
269+
270+
// {UoA/tok}
271+
(uint192 low, ) = asset.price();
272+
273+
// {tok}
274+
uint192 needed = shiftl_toFix(quantities[i], -int8(asset.erc20Decimals()));
275+
276+
// {UoA} = {UoA} + {tok}
277+
uoaNeeded += needed.mul(low);
278+
279+
// {UoA} = {UoA} + {tok} * {UoA/tok}
280+
uoaHeldInBaskets += fixMin(needed, asset.bal(address(bm))).mul(low);
281+
}
261282

262-
// {1} = {UoA} / {UoA}
263-
backing = buRange.bottom.div(basketsNeeded);
283+
backing = uoaHeldInBaskets.div(uoaNeeded);
284+
}
264285

265286
// Compute overCollateralization
266287
IAsset rsrAsset = rToken.main().assetRegistry().toAsset(rToken.main().rsr());
@@ -275,12 +296,6 @@ contract FacadeRead is IFacadeRead {
275296
// {UoA} = {tok} * {UoA/tok}
276297
uint192 rsrUoA = rsrBal.mul(lowPrice);
277298

278-
// {UoA/BU}
279-
(uint192 buPriceLow, ) = rToken.main().basketHandler().price();
280-
281-
// {UoA} = {BU} * {UoA/BU}
282-
uint192 uoaNeeded = basketsNeeded.mul(buPriceLow);
283-
284299
// {1} = {UoA} / {UoA}
285300
overCollateralization = rsrUoA.div(uoaNeeded);
286301
}

scripts/addresses/mainnet-2.1.0/1-tmp-deployments.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"facadeMonitor": "0xF3458200eDe2C5A592757dc0BA9A915e9CCA77C6",
2727
"cvxMiningLib": "0xA6B8934a82874788043A75d50ca74a18732DC660",
2828
"rsrAsset": "0x9cd0F8387672fEaaf7C269b62c34C53590d7e948",
29-
"facadeRead": "0x15f06B2907594905D820a4AB3631f4b097a0bE07",
29+
"facadeRead": "0xf535Cab96457558eE3eeAF1402fCA6441E832f08",
3030
"facadeWrite": "0x1656D8aAd7Ee892582B9D5c2E9992d9f94ff3629",
3131
"facadeAct": "0x933c5DBdA80f03C102C560e9ed0c29812998fA78"
3232
}

test/FacadeRead.test.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ describe('FacadeRead contract', () => {
211211
let [backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)
212212

213213
// Check values - Fully collateralized and no over-collateralization
214-
expect(backing).to.be.closeTo(fp('1'), 10)
214+
expect(backing).to.equal(fp('1'))
215215
expect(overCollateralization).to.equal(0)
216216

217217
// Mint some RSR
@@ -224,16 +224,16 @@ describe('FacadeRead contract', () => {
224224
;[backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)
225225

226226
// Check values - Fully collateralized and fully over-collateralized
227-
expect(backing).to.be.closeTo(fp('1'), 10)
227+
expect(backing).to.equal(fp('1'))
228228
expect(overCollateralization).to.be.closeTo(fp('0.5'), 10)
229229

230230
// Stake more RSR
231231
await rsr.connect(addr1).approve(stRSR.address, stakeAmount)
232232
await stRSR.connect(addr1).stake(stakeAmount)
233233
;[backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)
234234

235-
expect(backing).to.be.closeTo(fp('1'), 10)
236-
expect(overCollateralization).to.be.closeTo(fp('1'), 10)
235+
expect(backing).to.equal(fp('1'))
236+
expect(overCollateralization).to.equal(fp('1'))
237237

238238
// Redeem all RTokens
239239
await rToken.connect(addr1).redeem(issueAmount, await basketHandler.nonce())
@@ -246,14 +246,39 @@ describe('FacadeRead contract', () => {
246246
expect(overCollateralization).to.equal(0)
247247
})
248248

249+
it('Should return backingOverview backing correctly when undercollateralized', async () => {
250+
const backingManager = await main.backingManager()
251+
await usdc.burn(backingManager, (await usdc.balanceOf(backingManager)).div(2))
252+
await basketHandler.refreshBasket()
253+
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
254+
rToken.address
255+
)
256+
257+
// Check values - Fully collateralized and no over-collateralization
258+
expect(backing).to.equal(fp('0.875'))
259+
expect(overCollateralization).to.equal(0)
260+
})
261+
249262
it('Should return backingOverview backing correctly when an asset price is 0', async () => {
250263
await setOraclePrice(tokenAsset.address, bn(0))
251264
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
252265
rToken.address
253266
)
254267

255268
// Check values - Fully collateralized and no over-collateralization
256-
expect(backing).to.be.closeTo(fp('1'), 10)
269+
expect(backing).to.equal(fp('1'))
270+
expect(overCollateralization).to.equal(0)
271+
})
272+
273+
it('Should return backingOverview backing correctly when basket collateral is UNPRICED', async () => {
274+
await setOraclePrice(tokenAsset.address, MAX_UINT256.div(2).sub(1))
275+
await basketHandler.refreshBasket()
276+
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
277+
rToken.address
278+
)
279+
280+
// Check values - Fully collateralized and no over-collateralization
281+
expect(backing).to.equal(fp('1')) // since price is unknown for uoaHeldInBaskets
257282
expect(overCollateralization).to.equal(0)
258283
})
259284

@@ -265,7 +290,7 @@ describe('FacadeRead contract', () => {
265290
)
266291

267292
// Check values - Fully collateralized and no over-collateralization
268-
expect(backing).to.be.closeTo(fp('0'), 10)
293+
expect(backing).to.equal(fp('1'))
269294
expect(overCollateralization).to.equal(0)
270295
})
271296

@@ -283,7 +308,7 @@ describe('FacadeRead contract', () => {
283308
)
284309

285310
// Check values - Fully collateralized and no over-collateralization
286-
expect(backing).to.be.closeTo(fp('1'), 10)
311+
expect(backing).to.equal(fp('1'))
287312
expect(overCollateralization).to.equal(fp('0.5'))
288313

289314
// Set price to 0
@@ -294,7 +319,7 @@ describe('FacadeRead contract', () => {
294319
)
295320

296321
// Check values - Fully collateralized and no over-collateralization
297-
expect(backing2).to.be.closeTo(fp('1'), 10)
322+
expect(backing2).to.equal(fp('1'))
298323
expect(overCollateralization2).to.equal(0)
299324
})
300325

@@ -309,14 +334,14 @@ describe('FacadeRead contract', () => {
309334

310335
// Check values - Fully collateralized and with 50%-collateralization
311336
let [backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)
312-
expect(backing).to.be.closeTo(fp('1'), 10)
337+
expect(backing).to.equal(fp('1'))
313338
expect(overCollateralization).to.equal(fp('0.5'))
314339

315340
await setOraclePrice(rsrAsset.address, MAX_UINT256.div(2).sub(1))
316341
;[backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)
317342

318343
// Check values - Fully collateralized and no over-collateralization
319-
expect(backing).to.be.closeTo(fp('1'), 10)
344+
expect(backing).to.equal(fp('1'))
320345
expect(overCollateralization).to.equal(0)
321346
})
322347

0 commit comments

Comments
 (0)