Skip to content

Commit

Permalink
Merge pull request #770 from reserve-protocol/polish-backing-overview
Browse files Browse the repository at this point in the history
FacadeRead.backingOverview nits
  • Loading branch information
tbrent authored Apr 11, 2023
2 parents ae516a4 + 24e1778 commit 0f81ee3
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 24 deletions.
41 changes: 28 additions & 13 deletions contracts/facade/FacadeRead.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,35 @@ contract FacadeRead is IFacadeRead {
uint256 supply = rToken.totalSupply();
if (supply == 0) return (0, 0);

// {BU}
uint192 basketsNeeded = rToken.basketsNeeded();

// {BU}
BasketRange memory buRange = basketRange(rToken, basketsNeeded);
uint192 basketsNeeded = rToken.basketsNeeded(); // {BU}
uint192 uoaNeeded; // {UoA}
uint192 uoaHeldInBaskets; // {UoA}
{
(address[] memory basketERC20s, uint256[] memory quantities) = rToken
.main()
.basketHandler()
.quote(basketsNeeded, FLOOR);

IAssetRegistry reg = rToken.main().assetRegistry();
IBackingManager bm = rToken.main().backingManager();
for (uint256 i = 0; i < basketERC20s.length; i++) {
IAsset asset = reg.toAsset(IERC20(basketERC20s[i]));

// {UoA/tok}
(uint192 low, ) = asset.price();

// {tok}
uint192 needed = shiftl_toFix(quantities[i], -int8(asset.erc20Decimals()));

// {UoA} = {UoA} + {tok}
uoaNeeded += needed.mul(low);

// {UoA} = {UoA} + {tok} * {UoA/tok}
uoaHeldInBaskets += fixMin(needed, asset.bal(address(bm))).mul(low);
}

// {1} = {UoA} / {UoA}
backing = buRange.bottom.div(basketsNeeded);
backing = uoaHeldInBaskets.div(uoaNeeded);
}

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

// {UoA/BU}
(uint192 buPriceLow, ) = rToken.main().basketHandler().price();

// {UoA} = {BU} * {UoA/BU}
uint192 uoaNeeded = basketsNeeded.mul(buPriceLow);

// {1} = {UoA} / {UoA}
overCollateralization = rsrUoA.div(uoaNeeded);
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/addresses/mainnet-2.1.0/1-tmp-deployments.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"facadeMonitor": "0xF3458200eDe2C5A592757dc0BA9A915e9CCA77C6",
"cvxMiningLib": "0xA6B8934a82874788043A75d50ca74a18732DC660",
"rsrAsset": "0x9cd0F8387672fEaaf7C269b62c34C53590d7e948",
"facadeRead": "0x15f06B2907594905D820a4AB3631f4b097a0bE07",
"facadeRead": "0xf535Cab96457558eE3eeAF1402fCA6441E832f08",
"facadeWrite": "0x1656D8aAd7Ee892582B9D5c2E9992d9f94ff3629",
"facadeAct": "0x933c5DBdA80f03C102C560e9ed0c29812998fA78"
}
45 changes: 35 additions & 10 deletions test/FacadeRead.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ describe('FacadeRead contract', () => {
let [backing, overCollateralization] = await facade.callStatic.backingOverview(rToken.address)

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

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

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

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

expect(backing).to.be.closeTo(fp('1'), 10)
expect(overCollateralization).to.be.closeTo(fp('1'), 10)
expect(backing).to.equal(fp('1'))
expect(overCollateralization).to.equal(fp('1'))

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

it('Should return backingOverview backing correctly when undercollateralized', async () => {
const backingManager = await main.backingManager()
await usdc.burn(backingManager, (await usdc.balanceOf(backingManager)).div(2))
await basketHandler.refreshBasket()
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
rToken.address
)

// Check values - Fully collateralized and no over-collateralization
expect(backing).to.equal(fp('0.875'))
expect(overCollateralization).to.equal(0)
})

it('Should return backingOverview backing correctly when an asset price is 0', async () => {
await setOraclePrice(tokenAsset.address, bn(0))
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
rToken.address
)

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

it('Should return backingOverview backing correctly when basket collateral is UNPRICED', async () => {
await setOraclePrice(tokenAsset.address, MAX_UINT256.div(2).sub(1))
await basketHandler.refreshBasket()
const [backing, overCollateralization] = await facade.callStatic.backingOverview(
rToken.address
)

// Check values - Fully collateralized and no over-collateralization
expect(backing).to.equal(fp('1')) // since price is unknown for uoaHeldInBaskets
expect(overCollateralization).to.equal(0)
})

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

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

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

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

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

// Check values - Fully collateralized and no over-collateralization
expect(backing2).to.be.closeTo(fp('1'), 10)
expect(backing2).to.equal(fp('1'))
expect(overCollateralization2).to.equal(0)
})

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

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

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

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

Expand Down

0 comments on commit 0f81ee3

Please sign in to comment.