Skip to content

Commit

Permalink
Rollover vault (#112)
Browse files Browse the repository at this point in the history
* added helper to compute redeemable tranche balances

* Rollover vault logic

bug fixes

bug fixes

Apply suggestions from code review

Co-authored-by: nms-7 <57442379+nms-7@users.noreply.github.com>

removing extra getTrancheData call

* code review updates

* Apply suggestions from code review

Co-authored-by: Brandon Iles <brandon@fragments.org>

* code review updates

* fixed perp initialization

* Added todo

* Apply suggestions from code review

Co-authored-by: Brandon Iles <brandon@fragments.org>

* code review feedback

* code review comments

* rollover comments

* Apply suggestions from code review

Co-authored-by: Brandon Iles <brandon@fragments.org>

* code review comments

* reduced allowance to the amount to be transferred

---------

Co-authored-by: Brandon Iles <brandon@fragments.org>
  • Loading branch information
aalavandhan and brandoniles authored Apr 10, 2023
1 parent 4ce5e1d commit 4e49b37
Show file tree
Hide file tree
Showing 5 changed files with 542 additions and 168 deletions.
2 changes: 2 additions & 0 deletions spot-contracts/contracts/PerpetualTranche.sol
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ contract PerpetualTranche is
) public initializer {
__ERC20_init(name, symbol);
__Ownable_init();
__Pausable_init();
__ReentrancyGuard_init();
_decimals = IERC20MetadataUpgradeable(address(collateral_)).decimals();

// NOTE: `_reserveAt(0)` always points to the underling collateral token
Expand Down
42 changes: 29 additions & 13 deletions spot-contracts/contracts/_utils/BondHelpers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.18;

import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol";
import { MathUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";

import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { IBondController } from "../_interfaces/buttonwood/IBondController.sol";
Expand Down Expand Up @@ -66,6 +67,9 @@ library TrancheHelpers {
*
*/
library BondHelpers {
using SafeCastUpgradeable for uint256;
using MathUpgradeable for uint256;

// Replicating value used here:
// https://github.com/buttonwood-protocol/tranche/blob/main/contracts/BondController.sol
uint256 private constant TRANCHE_RATIO_GRANULARITY = 1000;
Expand All @@ -92,7 +96,7 @@ library BondHelpers {
/// @return The tranche data.
function getTrancheData(IBondController b) internal view returns (TrancheData memory) {
TrancheData memory td;
td.trancheCount = SafeCastUpgradeable.toUint8(b.trancheCount());
td.trancheCount = b.trancheCount().toUint8();
td.tranches = new ITranche[](td.trancheCount);
td.trancheRatios = new uint256[](td.trancheCount);
// Max tranches per bond < 2**8 - 1
Expand Down Expand Up @@ -191,27 +195,39 @@ library BondHelpers {
return (td, collateralBalances, trancheSupplies);
}

/// @notice Given a bond, retrieves the collateral redeemable for
/// each tranche held by the given address.
/// @notice For a given bond and user address, computes the maximum number of each of the bond's tranches
/// the user is able to redeem before the bond's maturity. These tranche amounts necessarily match the bond's tranche ratios.
/// @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;
TrancheData memory td = getTrancheData(b);
uint256[] memory redeemableAmts = new uint256[](td.trancheCount);

// Calculate how many underlying assets could be redeemed from each tranche balance,
// assuming other tranches are not an issue, and record the smallest amount.
uint256 minUnderlyingOut = type(uint256).max;
uint8 i;
for (i = 0; i < td.trancheCount; i++) {
uint256 d = td.tranches[i].balanceOf(u).mulDiv(TRANCHE_RATIO_GRANULARITY, td.trancheRatios[i]);
if (d < minUnderlyingOut) {
minUnderlyingOut = d;
}

(td, collateralBalances, trancheSupplies) = getTrancheCollateralizations(b);
// if one of the balances is zero, we return
if (minUnderlyingOut == 0) {
return (td, redeemableAmts);
}
}

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].mulDiv(minUnderlyingOut, TRANCHE_RATIO_GRANULARITY);
}

return (td, balances);
return (td, redeemableAmts);
}
}
16 changes: 8 additions & 8 deletions spot-contracts/contracts/test/BondHelpersTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
}
Loading

0 comments on commit 4e49b37

Please sign in to comment.