From 535309da93559129cfc0021091224fd0b7fd78bc Mon Sep 17 00:00:00 2001 From: nithin Date: Thu, 12 Jan 2023 22:22:36 +0530 Subject: [PATCH] added helper to compute redeemable tranche balances --- .../contracts/_utils/BondHelpers.sol | 32 ++-- .../contracts/test/BondHelpersTester.sol | 16 +- spot-contracts/test/_utils/BondHelpers.ts | 148 +----------------- 3 files changed, 28 insertions(+), 168 deletions(-) diff --git a/spot-contracts/contracts/_utils/BondHelpers.sol b/spot-contracts/contracts/_utils/BondHelpers.sol index 0e8656f8..c71769d6 100644 --- a/spot-contracts/contracts/_utils/BondHelpers.sol +++ b/spot-contracts/contracts/_utils/BondHelpers.sol @@ -191,27 +191,33 @@ library BondHelpers { return (td, collateralBalances, trancheSupplies); } - /// @notice Given a bond, retrieves the collateral redeemable for - /// each tranche held by the given address. + /// @notice Given a bond and a user address computes the tranche amounts proportional to the tranche ratios, + // that can be redeemed for the collateral before maturity. /// @param b The address of the bond contract. /// @param u The address to check balance for. - /// @return The tranche data and an array of collateral balances. - function getTrancheCollateralBalances(IBondController b, address u) + /// @return The tranche data and an array of tranche token balances. + function computeRedeemableTrancheAmounts(IBondController b, address u) internal view returns (TrancheData memory, uint256[] memory) { - TrancheData memory td; - uint256[] memory collateralBalances; - uint256[] memory trancheSupplies; - - (td, collateralBalances, trancheSupplies) = getTrancheCollateralizations(b); + TrancheData memory td = getTrancheData(b); + uint256[] memory redeemableAmts = new uint256[](td.trancheCount); + + // We calculate the minimum value of {trancheBal/trancheRatio} across tranches + uint256 min = type(uint256).max; + uint8 i; + for (i = 0; i < td.trancheCount && min != 0; i++) { + uint256 d = (td.tranches[i].balanceOf(u) * TRANCHE_RATIO_GRANULARITY) / td.trancheRatios[i]; + if (d < min) { + min = d; + } + } - uint256[] memory balances = new uint256[](td.trancheCount); - for (uint8 i = 0; i < td.trancheCount; i++) { - balances[i] = (td.tranches[i].balanceOf(u) * collateralBalances[i]) / trancheSupplies[i]; + for (i = 0; i < td.trancheCount; i++) { + redeemableAmts[i] = (td.trancheRatios[i] * min) / TRANCHE_RATIO_GRANULARITY; } - return (td, balances); + return (td, redeemableAmts); } } diff --git a/spot-contracts/contracts/test/BondHelpersTester.sol b/spot-contracts/contracts/test/BondHelpersTester.sol index 5e3220b4..e02af7b5 100644 --- a/spot-contracts/contracts/test/BondHelpersTester.sol +++ b/spot-contracts/contracts/test/BondHelpersTester.sol @@ -33,14 +33,6 @@ contract BondHelpersTester { return b.previewDeposit(collateralAmount); } - function getTrancheCollateralBalances(IBondController b, address u) - public - view - returns (TrancheData memory, uint256[] memory) - { - return b.getTrancheCollateralBalances(u); - } - function getTrancheCollateralizations(IBondController b) public view @@ -57,4 +49,12 @@ contract BondHelpersTester { TrancheData memory td = b.getTrancheData(); return td.getTrancheIndex(t); } + + function computeRedeemableTrancheAmounts(IBondController b, address u) + public + view + returns (TrancheData memory td, uint256[] memory) + { + return b.computeRedeemableTrancheAmounts(u); + } } diff --git a/spot-contracts/test/_utils/BondHelpers.ts b/spot-contracts/test/_utils/BondHelpers.ts index 90d0d557..988dfbcd 100644 --- a/spot-contracts/test/_utils/BondHelpers.ts +++ b/spot-contracts/test/_utils/BondHelpers.ts @@ -11,7 +11,6 @@ import { rebase, depositIntoBond, getTrancheBalances, - getTranches, } from "../helpers"; let bondFactory: Contract, @@ -20,18 +19,13 @@ let bondFactory: Contract, bondHelpers: Contract, accounts: Signer[], deployer: Signer, - deployerAddress: string, - user: Signer, - userAddress: string; + deployerAddress: string; async function setupContracts() { accounts = await ethers.getSigners(); deployer = accounts[0]; deployerAddress = await deployer.getAddress(); - user = accounts[1]; - userAddress = await user.getAddress(); - bondFactory = await setupBondFactory(); ({ collateralToken, rebaseOracle } = await setupCollateralToken("Bitcoin", "BTC")); @@ -425,144 +419,4 @@ describe("BondHelpers", function () { }); }); }); - - describe("#getTrancheCollateralBalances", function () { - let bond: Contract, bondLength: number; - beforeEach(async function () { - bondLength = 86400; - bond = await createBondWithFactory(bondFactory, collateralToken, [200, 300, 500], bondLength); - await depositIntoBond(bond, toFixedPtAmt("1000"), deployer); - const tranches = await getTranches(bond); - await tranches[0].transfer(userAddress, toFixedPtAmt("50")); - await tranches[1].transfer(userAddress, toFixedPtAmt("50")); - await tranches[2].transfer(userAddress, toFixedPtAmt("50")); - }); - - describe("when bond not mature", function () { - describe("when no change in supply", function () { - it("should calculate the balances", async function () { - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("150")); - expect(b[1][1]).to.eq(toFixedPtAmt("250")); - expect(b[1][2]).to.eq(toFixedPtAmt("450")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("50")); - expect(c[1][1]).to.eq(toFixedPtAmt("50")); - expect(c[1][2]).to.eq(toFixedPtAmt("50")); - }); - }); - - describe("when supply increases above z threshold", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, 0.1); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("150")); - expect(b[1][1]).to.eq(toFixedPtAmt("250")); - expect(b[1][2]).to.eq(toFixedPtAmt("540")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("50")); - expect(c[1][1]).to.eq(toFixedPtAmt("50")); - expect(c[1][2]).to.eq(toFixedPtAmt("60")); - }); - }); - - describe("when supply decreases below z threshold", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, -0.1); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("150")); - expect(b[1][1]).to.eq(toFixedPtAmt("250")); - expect(b[1][2]).to.eq(toFixedPtAmt("360")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("50")); - expect(c[1][1]).to.eq(toFixedPtAmt("50")); - expect(c[1][2]).to.eq(toFixedPtAmt("40")); - }); - }); - - describe("when supply decreases below b threshold", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, -0.6); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("150")); - expect(b[1][1]).to.eq(toFixedPtAmt("166.666666666666666666")); - expect(b[1][2]).to.eq(toFixedPtAmt("0")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("50")); - expect(c[1][1]).to.eq(toFixedPtAmt("33.333333333333333333")); - expect(c[1][2]).to.eq(toFixedPtAmt("0")); - }); - }); - - describe("when supply decreases below a threshold", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, -0.85); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("112.5")); - expect(b[1][1]).to.eq(toFixedPtAmt("0")); - expect(b[1][2]).to.eq(toFixedPtAmt("0")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("37.5")); - expect(c[1][1]).to.eq(toFixedPtAmt("0")); - expect(c[1][2]).to.eq(toFixedPtAmt("0")); - }); - }); - }); - - describe("when bond is mature", function () { - beforeEach(async function () { - await TimeHelpers.increaseTime(bondLength); - await bond.mature(); // NOTE: Any rebase after maturity goes directly to the tranches - }); - - describe("when no change in supply", function () { - it("should calculate the balances", async function () { - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("150")); - expect(b[1][1]).to.eq(toFixedPtAmt("250")); - expect(b[1][2]).to.eq(toFixedPtAmt("450")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("50")); - expect(c[1][1]).to.eq(toFixedPtAmt("50")); - expect(c[1][2]).to.eq(toFixedPtAmt("50")); - }); - }); - - describe("when supply increases", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, 0.1); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("165")); - expect(b[1][1]).to.eq(toFixedPtAmt("275")); - expect(b[1][2]).to.eq(toFixedPtAmt("495")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("55")); - expect(c[1][1]).to.eq(toFixedPtAmt("55")); - expect(c[1][2]).to.eq(toFixedPtAmt("55")); - }); - }); - - describe("when supply decreases", function () { - it("should calculate the balances", async function () { - await rebase(collateralToken, rebaseOracle, -0.1); - const b = await bondHelpers.getTrancheCollateralBalances(bond.address, deployerAddress); - expect(b[1][0]).to.eq(toFixedPtAmt("135")); - expect(b[1][1]).to.eq(toFixedPtAmt("225")); - expect(b[1][2]).to.eq(toFixedPtAmt("405")); - - const c = await bondHelpers.getTrancheCollateralBalances(bond.address, userAddress); - expect(c[1][0]).to.eq(toFixedPtAmt("45")); - expect(c[1][1]).to.eq(toFixedPtAmt("45")); - expect(c[1][2]).to.eq(toFixedPtAmt("45")); - }); - }); - }); - }); });