Elysia Tranche Pool

Spec

  • TranchePool

    • Users cannot withdraw & redeem in the live status.
  • Roles

    • Protocol Admin has a DEFAULT_ADMIN_ROLE of contracts
    • Each contract has a manager
  • Pausable

    • These functions are possible when portfolio is not paused
      • Portfolio: start, closeSenior, closeEquity, addLoan, fundLoan, repayLoan, repayDefaultedLoan, markLoanAsDefaulted.
      • TranchePool: deposit, mint, withdraw, redeem

Dev Notes

  • It is only periphery contracts where users interact that inherit Context.
  • An equity tranche always lies in tranches[0] to find the equity tranche easily regardless of the number of tranches.

Test

forge test

# coverage report
forge coverage

Naming conventions

To distinguish between the function name in the test name and the actual use of the function, we uses Pascal case for the function name in the test name.

function test_Foo() public {
  foo();
}

Deploy

# 1. create .env
cp .env.example .env

# 2. Fill out .env

# 3. Deploy
source .env
yarn hardhat deploy --network bsc_testnet
yarn hardhat etherscan-verify --network bsc_testnet --api-key $BSCSCAN_API_KEY

Openzeppelin defender

BSC Testnet https://defender.openzeppelin.com/#/autotask/6f72f14e-83d6-4716-a4aa-0204f9d2c613

yarn defender-autotask update-code 6f72f14e-83d6-4716-a4aa-0204f9d2c613 ./autotask/update-exchange-rate

BSC

yarn defender-autotask update-code 70413fb3-d05d-46f3-8730-9dae58e86639 ./autotask/update-exchange-rate

Upgrade Portfolio contract

# 1. Validate upgrade
yarn hardhat run scripts/validate-upgrade-startPortfolio.ts --network bsc_testnet
# 2. Comment out skip option in `deploy/07-UpgradeablePortfolio.ts`
# 3. Execute upgrade
yarn hardhat deploy --network bsc_testnet --tags Portfolio

Static analysis

mythx

pip install mythx-cli
export MYTHX_API_KEY=
mythx analyze

Solither

pip3 install slither-analyzer

slither .
# or
slither . > output.txt 2>&1

Docs

forge doc

Manuals

Deposit

yarn hardhat deposit --network bsc_testnet --amount 70000000000000000000000 --tranche senior

Start portfolio

yarn hardhat portfolio:start --network bsc_testnet

Repay a loan

1. uint256 debtAmountInUSD = fixedInterestBulletLoans.expectedRepayAmount(loanId)
2. usdt.approve(address(portfolio), debtAmountInUSD)
3. portfolio.repayLoan(loanId)

Addresses

BSC Mainnet

  • Exchange rate Autotask: https://defender.openzeppelin.com/#/autotask/70413fb3-d05d-46f3-8730-9dae58e86639

BSC Testnet

ContractsAddress
ProtocolConfig0x96607B297Ef79935912d5c0711A371a8Bc663E2c
CurrencyConverter0x9DEDdABdA5Df821906A8e2b80FC820825d7AB022
DepositController0xe6F2e4009a9633230975Bf2923563E50c91824d0
WithdrawController0xcd91E5F86E221A43Ed568A2EEe11Ec33f846f05B
FixedInterestBulletLoans0x4B1B1BC012f63B08bbFeA11fF37f003d1006f12a
OrderController0x6099256Ed184b976C13f5b9778EBE262d542aA2C
Portfolio0xDbdd1a9868db25300b6a0EDF4a43D7bBf5D85113
EquityTranche0x3d645f1dFf6107BFFB4913EdEc7e914aEF7D6715
SeniorTranche0x0505aC8DBca0d198a2CA0edd99EEe496717fF419
  • Exchange rate autotask: https://defender.openzeppelin.com/#/autotask/6f72f14e-83d6-4716-a4aa-0204f9d2c613/edit-settings

Status Live

ContractsAddress
FixedInterestBulletLoans0xA804bfccc7d57999856c7Ae58F70ce6A3D3E75e9
OrderController0x264b6c52DfDeaB92196C725b024fa2e110f20204
Portfolio0x06eC9F7341Cf7cda72ff8F1Ecbf353B70d94792B
EquityTranche0xaFCBb0451E0a00676B762DaA9885b248F3E1CD48
SeniorTranche0x16678a4B5Ba8722C8230E881D81096947165dbe8

Contents

ICurrencyConverter

Git Source

Functions

setExchangeRate

set the exchange rate between WON and USD

the caller is contract keeper

function setExchangeRate(uint256 _exchangeRate) external;

getExchangeRate

get the exchange rate between WON and USD

function getExchangeRate() external returns (uint256, uint256);

convertFromUSD

constructor guarantees 18 = won decimals >= usd decimals

function convertFromUSD(uint256 usdAmount) external view returns (uint256 wonAmount);

Parameters

NameTypeDescription
usdAmountuint256the amount of USD received

Returns

NameTypeDescription
wonAmountuint256the amount of WON to give

convertToUSD

constructor guarantees 18 = won decimals >= usd decimals

function convertToUSD(uint256 wonAmount) external view returns (uint256 usdAmount);

Parameters

NameTypeDescription
wonAmountuint256the amount of WON received

Returns

NameTypeDescription
usdAmountuint256the amount of USD to give

Errors

InvalidTargetDecimals

error InvalidTargetDecimals();

IDepositController

Git Source

Functions

onDeposit

Handle deposit of assets and distribute shares and fees accordingly

function onDeposit(address sender, uint256 assets, address receiver) external returns (uint256 shares, uint256 fees);

Parameters

NameTypeDescription
senderaddressThe address of the sender depositing assets
assetsuint256The amount of assets being deposited
receiveraddressThe address receiving the shares

Returns

NameTypeDescription
sharesuint256The amount of shares minted for the deposit
feesuint256The amount of fees collected during the deposit

onMint

Handle minting of shares and distribute assets and fees accordingly

function onMint(address sender, uint256 shares, address receiver) external returns (uint256 assets, uint256 fees);

Parameters

NameTypeDescription
senderaddressThe address of the sender minting shares
sharesuint256The amount of shares being minted
receiveraddressThe address receiving the assets

Returns

NameTypeDescription
assetsuint256The amount of assets corresponding to the minted shares
feesuint256The amount of fees collected during the minting

previewDeposit

Preview the number of shares that will be minted for a given amount of assets

function previewDeposit(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to be deposited

Returns

NameTypeDescription
sharesuint256The estimated number of shares to be minted

previewMint

Preview the total amount of assets (including fees) for a given number of shares

function previewMint(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to be minted

Returns

NameTypeDescription
assetsuint256The estimated total amount of assets (including fees) for the given shares

maxDeposit

Calculate the maximum deposit amount based on the given ceiling

function maxDeposit(address receiver, uint256 ceiling) external view returns (uint256 assets);

Parameters

NameTypeDescription
receiveraddressThe address receiving the shares
ceilinguint256The maximum allowed total assets

Returns

NameTypeDescription
assetsuint256The maximum deposit amount under the given ceiling

maxMint

Calculate the maximum number of shares that can be minted based on the given ceiling

function maxMint(address receiver, uint256 ceiling) external view returns (uint256 shares);

Parameters

NameTypeDescription
receiveraddressThe address receiving the assets
ceilinguint256The maximum allowed total assets

Returns

NameTypeDescription
sharesuint256The maximum number of shares that can be minted under the given ceiling

setDepositFeeRate

Set the deposit fee rate

function setDepositFeeRate(uint256 _depositFeeRate) external;

Parameters

NameTypeDescription
_depositFeeRateuint256The new deposit fee rate

FixedInterestBulletLoanStatus

Git Source

enum FixedInterestBulletLoanStatus {
    Created,
    Started,
    Repaid,
    Canceled,
    Defaulted
}

IFixedInterestBulletLoans

Git Source

Inherits: IAccessControl

Functions

issueLoan

Issue a new loan with the specified parameters

function issueLoan(IssueLoanInputs calldata loanInputs) external returns (uint256);

Parameters

NameTypeDescription
loanInputsIssueLoanInputsThe input parameters for the new loan

Returns

NameTypeDescription
<none>uint256The ID of the newly created loan

startLoan

Start a loan with the specified ID

The loan must be in the Created status and the caller must be the portfolio contract

function startLoan(uint256 loanId) external returns (uint256 principal);

Parameters

NameTypeDescription
loanIduint256The ID of the loan to start

Returns

NameTypeDescription
principaluint256The borrowed principal amount of the loan in USD

loanData

Retrieve loan data for a specific loan ID

function loanData(uint256 loanId) external view returns (LoanMetadata memory);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>LoanMetadataThe loan metadata as a LoanMetadata struct

repayLoan

Repay a loan with the specified ID and amount

The loan must be in the Started status and the caller must be the portfolio contract

function repayLoan(uint256 loanId, uint256 usdAmount) external;

Parameters

NameTypeDescription
loanIduint256The ID of the loan to repay
usdAmountuint256The amount to repay in USD

repayDefaultedLoan

Repay a defaulted loan with the specified ID and amount

The loan must be in the Defaulted status and the caller must be the portfolio contract

function repayDefaultedLoan(uint256 loanId, uint256 usdAmount) external;

Parameters

NameTypeDescription
loanIduint256The ID of the defaulted loan to repay
usdAmountuint256The amount to repay in USD

cancelLoan

Cancel a loan with the specified ID

The loan must be in the Created status and the caller must be the portfolio contract

function cancelLoan(uint256 loanId) external;

Parameters

NameTypeDescription
loanIduint256The ID of the loan to cancel

markLoanAsDefaulted

Mark a loan as defaulted with the specified ID

The loan must be in the Started status and the caller must be the portfolio contract

function markLoanAsDefaulted(uint256 loanId) external;

Parameters

NameTypeDescription
loanIduint256The ID of the loan to mark as defaulted

getRecipient

Get the recipient address of a loan with the specified ID

function getRecipient(uint256 loanId) external view returns (address);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>addressThe recipient address

getStatus

Get the status of a loan with the specified ID

function getStatus(uint256 loanId) external view returns (FixedInterestBulletLoanStatus);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>FixedInterestBulletLoanStatusThe loan status as a FixedInterestBulletLoanStatus enum value

isOverdue

Check if a loan with the specified ID is overdue

function isOverdue(uint256 loanId) external view returns (bool);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>boolA boolean value indicating if the loan is overdue

getLoansLength

Get the total number of loans

function getLoansLength() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total number of loans

currentUsdValue

Calculate the loan value at the current timestamp

function currentUsdValue(uint256 loanId) external view returns (uint256);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>uint256loan value. It remains the same after loan.endDate

expectedUsdRepayAmount

Calculate the amount to repay. It is the same regardless of the repaying time.

function expectedUsdRepayAmount(uint256 loanId) external view returns (uint256);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>uint256repayment amount

setPortfolio

Set the portfolio contract

The caller must have the manager role

function setPortfolio(IPortfolio _portfolio) external;

Parameters

NameTypeDescription
_portfolioIPortfolioThe address of the portfolio contract

setCurrencyConverter

Set the currency converter contract

The caller must have the manager role

function setCurrencyConverter(ICurrencyConverter _currencyConverter) external;

Parameters

NameTypeDescription
_currencyConverterICurrencyConverterThe address of the currency converter contract

Events

Created

Emitted when a new loan is created

event Created(uint256 indexed loanId);

Started

Emitted when a loan is started

event Started(uint256 indexed loanId);

Repaid

Emitted when a loan is repaid

event Repaid(uint256 indexed loanId, uint256 amount);

RepayDefaulted

Emitted when a defaulted loan is repaid

event RepayDefaulted(uint256 indexed loanId, uint256 amount);

Defaulted

Emitted when a loan is marked as defaulted

event Defaulted(uint256 indexed loanId);

Canceled

Emitted when a loan is canceled

event Canceled(uint256 indexed loanId);

LoanStatusChanged

Emitted when a loan status is changed

event LoanStatusChanged(uint256 indexed loanId, FixedInterestBulletLoanStatus newStatus);

Errors

NotPortfolio

error NotPortfolio();

PortfolioAlreadySet

error PortfolioAlreadySet();

NotSuitableLoanStatus

error NotSuitableLoanStatus();

NotEqualRepayAmount

error NotEqualRepayAmount();

Structs

LoanMetadata

struct LoanMetadata {
    uint256 krwPrincipal;
    uint256 usdPrincipal;
    uint256 usdRepaid;
    uint256 interestRate;
    address recipient;
    address collateral;
    uint256 collateralId;
    uint256 startDate;
    uint256 duration;
    FixedInterestBulletLoanStatus status;
    IERC20 asset;
}

IssueLoanInputs

struct IssueLoanInputs {
    uint256 krwPrincipal;
    uint256 interestRate;
    address recipient;
    address collateral;
    uint256 collateralId;
    uint256 duration;
    IERC20 asset;
}

AddLoanParams

Git Source

struct AddLoanParams {
    address recipient;
    uint256 krwPrincipal;
    uint256 interestRate;
    address collateral;
    uint256 collateralId;
    uint256 duration;
}

ILoansManager

Git Source

Functions

issuedLoanIds

function issuedLoanIds(uint256 loanId) external view returns (bool);

Parameters

NameTypeDescription
loanIduint256Loan id

Returns

NameTypeDescription
<none>boolWhether a loan with the given loanId was issued by this contract

fixedInterestBulletLoans

function fixedInterestBulletLoans() external view returns (IFixedInterestBulletLoans);

Returns

NameTypeDescription
<none>IFixedInterestBulletLoansFixedInterestBulletLoans contract

Events

LoanAdded

Emitted when a loan is added

event LoanAdded(uint256 indexed loanId);

LoanFunded

Emitted when a loan is funded

event LoanFunded(uint256 indexed loanId);

LoanRepaid

Emitted when a loan is repaid

event LoanRepaid(uint256 indexed loanId, uint256 amount);

LoanCanceled

Emitted when a loan is canceled

event LoanCanceled(uint256 indexed loanId);

LoanDefaulted

Emitted when a loan is defaulted

event LoanDefaulted(uint256 indexed loanId);

ActiveLoanRemoved

Emitted when a active loan is removed

event ActiveLoanRemoved(uint256 indexed loanId, FixedInterestBulletLoanStatus indexed status);

Errors

InvalidLoanId

Thrown when loanId is not valid or doesn't exist in the issuedLoanIds mapping

error InvalidLoanId();

InSufficientFund

Thrown when there are insufficient funds in the contract to fund a loan

error InSufficientFund();

InvalidRecipient

Thrown when the recipient address is invalid

error InvalidRecipient();

OrderType

Git Source

enum OrderType {
    NONE,
    DEPOSIT,
    WITHDRAW
}

Order

Git Source

struct Order {
    uint256 id;
    uint256 amount;
    uint256 prev;
    uint256 next;
    uint256 createdAt;
    address user;
    OrderType orderType;
}

IOrderController

Git Source

Functions

deposit

Allows a user to deposit tokens and create a DEPOSIT order. It doesn't gurantee deposit

The order can be executed if there's a matching withdrawal request. The caller should approve tokens prior to calling this function.

function deposit(uint256 tokenAmount, uint256 iterationLimit) external;

Parameters

NameTypeDescription
tokenAmountuint256The amount of tokens to deposit.
iterationLimituint256The maximum number of orders to process in a single call.

withdraw

Allows a user to withdraw tranches and create a WITHDRAW order.

The order can be executed if there's a matching deposit request. The caller should approve tranches prior to calling this function.

function withdraw(uint256 trancheAmount, uint256 iterationLimit) external;

Parameters

NameTypeDescription
trancheAmountuint256The amount of tranches to withdraw.
iterationLimituint256The maximum number of orders to process in a single call.

cancelOrder

Allows a user to cancel their pending order.

This can be called by the user who placed the order only.

function cancelOrder() external;

cancelDustOrder

Allows any users to cancel dust order.

function cancelDustOrder(uint256 orderId) external;

Parameters

NameTypeDescription
orderIduint256The order id to cancel.

expectedTokenAmount

Calculate the expected token amount for a given tranche amount.

function expectedTokenAmount(uint256 trancheAmount) external view returns (uint256);

Parameters

NameTypeDescription
trancheAmountuint256The amount of tranches to convert.

Returns

NameTypeDescription
<none>uint256The expected token amount.

expectedTrancheAmount

Calculate the expected tranche amount for a given token amount.

function expectedTrancheAmount(uint256 tokenAmount) external view returns (uint256);

Parameters

NameTypeDescription
tokenAmountuint256The amount of tokens to convert.

Returns

NameTypeDescription
<none>uint256The expected tranche amount.

currentOrderType

Return the type of the current order in the linked list of orders

function currentOrderType() external view returns (OrderType);

getValidOrderCount

Return the count of valid orders and the current order type.

function getValidOrderCount() external view returns (uint256 count, OrderType orderType);

Returns

NameTypeDescription
countuint256The count of valid orders.
orderTypeOrderTypeThe type of the current order.

getValidOrders

Return the valid orders and the current order type.

function getValidOrders() external view returns (Order[] memory, OrderType);

Returns

NameTypeDescription
<none>Order[]orders The valid orders.
<none>OrderTypeorderType The type of the order.

getOrderCount

Return the count of all orders.

function getOrderCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The count of all orders.

getOrders

Return all orders.

function getOrders() external view returns (Order[] memory);

Returns

NameTypeDescription
<none>Order[]The orders.

getUserOrder

Return the order of the given user.

function getUserOrder(address user) external view returns (Order memory);

Parameters

NameTypeDescription
useraddressThe user address.

Returns

NameTypeDescription
<none>OrderThe order.

dust

Return the min amount of an order.

function dust() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The minimum value.

Events

DustUpdated

event DustUpdated(uint256 newDust);

Errors

InvalidAmount

error InvalidAmount();

InvalidOrderType

error InvalidOrderType();

InvalidOrderId

error InvalidOrderId();

InsufficientBalance

error InsufficientBalance();

InsufficientAllowance

error InsufficientAllowance();

PortfolioClosed

error PortfolioClosed();

IPausable

Git Source

Functions

paused

function paused() external returns (bool);

Status

Git Source

enum Status {
    Preparation,
    Live,
    Stopped,
    SeniorClosed,
    EquityClosed
}

TrancheData

Git Source

struct TrancheData {
    uint256 initialAssets;
    uint128 targetApr;
    uint128 minSubordinateRatio;
}

TrancheInitData

Git Source

struct TrancheInitData {
    ITranchePool tranche;
    uint128 targetApr;
    uint128 minSubordinateRatio;
}

IPortfolio

Git Source

Functions

tranches

Returns the address of the tranche pool contract

function tranches(uint256 index) external view returns (ITranchePool);

status

Returns current portfolio status

function status() external view returns (Status);

startTimestamp

Returns the timestamp when the portfolio started

function startTimestamp() external view returns (uint40);

calculateWaterfall

calculate each tranche values based only on the current assets.

It does not take account of loans value.

function calculateWaterfall() external view returns (uint256[] memory);

Returns

NameTypeDescription
<none>uint256[]Array of current tranche values

calculateWaterfallForTranche

function calculateWaterfallForTranche(uint256 waterfallIndex) external view returns (uint256);

calculateWaterfallWithLoans

calculate each tranche values given the (current assets + loans value).

function calculateWaterfallWithLoans() external view returns (uint256[] memory);

calculateWaterfallWithLoansForTranche

function calculateWaterfallWithLoansForTranche(uint256 waterfallIndex) external view returns (uint256);

loansValue

calculate the total value of all active loans in the contract.

function loansValue() external view returns (uint256);

getTokenBalance

get token balance of this contract

function getTokenBalance() external view returns (uint256);

getAssumedCurrentValues

get assumed current values

function getAssumedCurrentValues()
    external
    view
    returns (uint256 equityValue, uint256 fixedRatePoolValue, uint256 overdueValue);

Returns

NameTypeDescription
equityValueuint256The value of equity tranche
fixedRatePoolValueuint256The value of fixed rate pool tranches
overdueValueuint256The value of overdue loans

start

Starts the portfolio to issue loans.

  • changes the state to Live
  • gathers assets to the portfolio from every tranche.*
function start() external;

closeSenior

Allow the senior tranche to withdraw.

  • changes the state to SeniorClosed
  • Distribute the remaining assets to the senior tranche.*
function closeSenior() external;

closeEquity

Allow the equity tranche to withdraw.

  • changes the state to EquityClosed
  • Distribute the remaining assets to the equity tranche.*
function closeEquity() external;

addLoan

Create loan

function addLoan(AddLoanParams calldata params) external returns (uint256 loanId);

Parameters

NameTypeDescription
paramsAddLoanParamsLoan params

fundLoan

Fund the loan

function fundLoan(uint256 loanId) external returns (uint256 principal);

Parameters

NameTypeDescription
loanIduint256Loan id

repayLoan

Repay the loan

function repayLoan(uint256 loanId) external returns (uint256 amount);

Parameters

NameTypeDescription
loanIduint256Loan id

repayDefaultedLoan

Repay the loan

function repayDefaultedLoan(uint256 loanId, uint256 amount) external;

Parameters

NameTypeDescription
loanIduint256Loan id
amountuint256amount

cancelLoan

Cancel the loan

function cancelLoan(uint256 loanId) external;

Parameters

NameTypeDescription
loanIduint256Loan id

markLoanAsDefaulted

Cancel the loan

function markLoanAsDefaulted(uint256 loanId) external;

Parameters

NameTypeDescription
loanIduint256Loan id

increaseTokenBalance

Increase the current token balance of the portfolio

This function is used to track the token balance of the portfolio. Only the tranche pool contract can call

function increaseTokenBalance(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256Amount to increase

Events

PortfolioStatusChanged

event PortfolioStatusChanged(Status status);

Errors

NotTranche

error NotTranche();

NotGovernance

error NotGovernance();

NotManagerOrCollateralOwner

error NotManagerOrCollateralOwner();

EquityAprNotZero

error EquityAprNotZero();

ActiveLoansExist

error ActiveLoansExist();

AlreadyStarted

error AlreadyStarted();

NotReadyToCloseSenior

error NotReadyToCloseSenior();

NotFullyFunded

error NotFullyFunded();

NotReadyToCloseEquity

error NotReadyToCloseEquity();

AddLoanNotAllowed

error AddLoanNotAllowed();

FundLoanNotAllowed

error FundLoanNotAllowed();

RepayLoanNotAllowed

error RepayLoanNotAllowed();

RepayDefaultedLoanNotAllowed

error RepayDefaultedLoanNotAllowed();

StopPortfolioWithInvalidStatus

error StopPortfolioWithInvalidStatus();

StopPortfolioWithInvalidValues

error StopPortfolioWithInvalidValues();

RestartPortfolioWithInvalidStatus

error RestartPortfolioWithInvalidStatus();

RestartPortfolioWithInvalidValues

error RestartPortfolioWithInvalidValues();

RestartPortfolioOverDuration

error RestartPortfolioOverDuration();

DepositInvalidStatus

error DepositInvalidStatus();

IProtocolConfig

Git Source

Functions

protocolAdmin

function protocolAdmin() external view returns (address);

pauser

function pauser() external view returns (address);

Events

ProtocolAdminChanged

event ProtocolAdminChanged(address protocolAdmin);

PauserChanged

event PauserChanged(address pauser);

Errors

NotProtocolAdmin

error NotProtocolAdmin();

ITranchePool

Git Source

Inherits: IERC4626Upgradeable

Functions

portfolio

the associated portfolio for this tranche pool

function portfolio() external view returns (IPortfolio portfolio);

Returns

NameTypeDescription
portfolioIPortfolioThe associated portfolio

ceiling

the ceiling for this tranche pool

function ceiling() external view returns (uint256 ceiling);

Returns

NameTypeDescription
ceilinguint256The ceiling value

availableLiquidity

available liquidity tracked by the token balance tracker

function availableLiquidity() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The available liquidity

waterfallIndex

the waterfall index for this tranche pool. 0 is equity and 1 is senior

function waterfallIndex() external view returns (uint256 waterfallIndex);

Returns

NameTypeDescription
waterfallIndexuint256The waterfall index

convertToSharesCeil

Converts a given amount of assets to shares (rounded up)

function convertToSharesCeil(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to convert

Returns

NameTypeDescription
sharesuint256The equivalent amount of shares

convertToAssetsCeil

Converts a given amount of shares to assets (rounded up)

function convertToAssetsCeil(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to convert

Returns

NameTypeDescription
assetsuint256The equivalent amount of assets

setPortfolio

Sets the portfolio for this tranche pool

function setPortfolio(IPortfolio _portfolio) external;

Parameters

NameTypeDescription
_portfolioIPortfolioThe new portfolio to set

setDepositController

Sets the deposit controller for this tranche pool

function setDepositController(IDepositController newController) external;

Parameters

NameTypeDescription
newControllerIDepositControllerThe new deposit controller to set

setWithdrawController

Sets the withdraw controller for this tranche pool

function setWithdrawController(IWithdrawController newController) external;

Parameters

NameTypeDescription
newControllerIWithdrawControllerThe new withdraw controller to set

setCeiling

Sets the ceiling for this tranche pool

function setCeiling(uint256 newCeiling) external;

Parameters

NameTypeDescription
newCeilinguint256The new ceiling to set

onPortfolioStart

Called when the portfolio starts

function onPortfolioStart() external returns (uint256);

Returns

NameTypeDescription
<none>uint256The balance of the tranche pool

increaseTokenBalance

Increases the token balance of the tranche pool by the given amount

function increaseTokenBalance(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256The amount to increase the token balance by

Events

DepositControllerChanged

event DepositControllerChanged(IDepositController indexed controller);

DepositFeePaid

event DepositFeePaid(address indexed receiver, uint256 fee);

WithdrawControllerChanged

event WithdrawControllerChanged(IWithdrawController indexed controller);

WithdrawFeePaid

event WithdrawFeePaid(address indexed receiver, uint256 fee);

CeilingChanged

event CeilingChanged(uint256 newCeiling);

Errors

PortfolioAlreadySet

error PortfolioAlreadySet();

NotPortfolio

error NotPortfolio();

PortfolioPaused

error PortfolioPaused();

MaxDepositExceeded

error MaxDepositExceeded();

MaxMintExceeded

error MaxMintExceeded();

MaxWithdrawExceeded

error MaxWithdrawExceeded();

MaxRedeemExceeded

error MaxRedeemExceeded();

InsufficientAllowance

error InsufficientAllowance();

IWithdrawController

Git Source

This contract manages the withdrawal and redemption fees for users in the tranches.

The contract calculates fees, handles withdrawal, and allows setting of withdrawal fee rates.

Functions

withdrawFeeRate

function withdrawFeeRate() external view returns (uint256);

maxWithdraw

A user cannot withdraw in the live status.

function maxWithdraw(address owner) external view returns (uint256 assets);

Returns

NameTypeDescription
assetsuint256The max amount of assets that the user can withdraw.

maxRedeem

A user cannot redeem in the live status.

function maxRedeem(address owner) external view returns (uint256 shares);

Returns

NameTypeDescription
sharesuint256The max amount of shares that the user can burn to withdraw assets.

previewWithdraw

Preview the amount of shares to burn to withdraw the given amount of assets.

It always rounds up the result. e.g. 3/4 -> 1.

function previewWithdraw(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to withdraw.

Returns

NameTypeDescription
sharesuint256The amount of shares to burn.

previewRedeem

Preview the amount of assets to receive after burning the given amount of shares.

function previewRedeem(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to burn.

Returns

NameTypeDescription
assetsuint256The amount of assets to receive.

onWithdraw

Executes the withdrawal process, returning the amount of shares to burn and fees.

The sender and owner parameters are not used in this implementation.

function onWithdraw(
    address sender,
    uint256 assets,
    address receiver,
    address owner
)
    external
    returns (uint256 shares, uint256 fees);

Parameters

NameTypeDescription
senderaddress
assetsuint256The amount of assets to withdraw.
receiveraddressThe address that will receive the assets.
owneraddressThe address of the owner of the assets.

Returns

NameTypeDescription
sharesuint256The amount of shares to burn.
feesuint256The amount of fees to be paid.

onRedeem

function onRedeem(
    address sender,
    uint256 shares,
    address receiver,
    address owner
)
    external
    returns (uint256 assets, uint256 fees);

setWithdrawFeeRate

function setWithdrawFeeRate(uint256 _withdrawFeeRate) external;

Contents

MathUtils

Git Source

State Variables

BASIS_PRECISON

uint256 constant BASIS_PRECISON = 10_000;

SECONDS_PER_YEAR

Ignoring leap years

uint256 internal constant SECONDS_PER_YEAR = 365 days;

Functions

calculateLinearInterest

function calculateLinearInterest(
    uint256 principal,
    uint256 rate,
    uint256 startTimestamp,
    uint256 endTimestamp
)
    internal
    view
    returns (uint256);

Contents

FaucetToken

Git Source

Inherits: ERC20

Functions

constructor

Constructor that gives msg.sender all of existing tokens.

constructor() ERC20("FaucetToken", "FAU");

fallback

fallback() external;

mint

function mint(address to, uint256 value) public returns (bool);

TestFixedInterestBulletLoans

Git Source

Inherits: FixedInterestBulletLoans

Functions

constructor

constructor(
    string memory name_,
    string memory symbol_,
    IProtocolConfig _protocolConfig,
    ICurrencyConverter _currencyConverter,
    address manager
)
    FixedInterestBulletLoans(name_, symbol_, _protocolConfig, _currencyConverter, manager);

mockSetStatus

function mockSetStatus(uint256 loanId, FixedInterestBulletLoanStatus _status) external;

TestLoansManager

Git Source

Inherits: LoansManager, UUPSUpgradeable

Functions

initialize

function initialize(IFixedInterestBulletLoans _fixedInterestBulletLoans, IERC20 _asset) public initializer;

_authorizeUpgrade

function _authorizeUpgrade(address) internal override;

addLoan

function addLoan(AddLoanParams calldata params) external returns (uint256 loanId);

fundLoan

function fundLoan(uint256 loanId) external returns (uint256 principal);

repayLoan

function repayLoan(uint256 loanId) external returns (uint256 amount);

repayDefaultedLoan

function repayDefaultedLoan(uint256 loanId, uint256 amount) external;

cancelLoan

function cancelLoan(uint256 loanId) external;

markLoanAsDefaulted

function markLoanAsDefaulted(uint256 loanId) external;

tryToExcludeLoan

function tryToExcludeLoan(uint256 loanId) external;

increaseTokenBalance

function increaseTokenBalance(uint256 amount) external;

getCountOfActiveLoans

function getCountOfActiveLoans() external view returns (uint256);

TestOrderController

Git Source

Inherits: OrderController

State Variables

isExpectedTokenAndTrancheAmountMocked

bool public isExpectedTokenAndTrancheAmountMocked;

isPortfolioStatusMocked

bool public isPortfolioStatusMocked;

mockedPortfolioStatus

Status public mockedPortfolioStatus;

Functions

constructor

constructor(
    ITranchePool tranche_,
    IProtocolConfig protocolConfig_,
    IPortfolio portfolio_,
    uint256 dust_,
    address manager_
)
    OrderController(tranche_, protocolConfig_, portfolio_, dust_, manager_);

executeDepositOrder

function executeDepositOrder(uint256 amount, address user) external;

executeWithdrawOrder

function executeWithdrawOrder(uint256 amount, address user) external;

validateInputs

function validateInputs(address user, uint256 amount, OrderType orderType) external view;

setToken

function setToken(IERC20 token_) external;

setTranche

function setTranche(ITranchePool tranche_) external;

createOrder

function createOrder(address user, uint256 amount, OrderType orderType) external;

mockExpectedTokenAndTrancheAmount

function mockExpectedTokenAndTrancheAmount(bool isMocked) external;

mockPortfolioStatus

function mockPortfolioStatus(Status status, bool isMocked) external;

expectedTokenAmount

function expectedTokenAmount(uint256 trancheAmount) public view override returns (uint256);

expectedTrancheAmount

function expectedTrancheAmount(uint256 tokenAmount) public view override returns (uint256);

expectedTokenAmountCeil

function expectedTokenAmountCeil(uint256 trancheAmount) internal view override returns (uint256);

expectedTrancheAmountCeil

function expectedTrancheAmountCeil(uint256 tokenAmount) internal view override returns (uint256);

getOrderCount

function getOrderCount(OrderType orderType) public view returns (uint256);

getOrders

function getOrders(OrderType orderType) public view returns (Order[] memory);

TestPortfolio

Git Source

Inherits: Portfolio, TestTokenBalanceTracker

Functions

mockSetStatus

function mockSetStatus(Status _status) external;

calculateWaterfall

function calculateWaterfall(uint256 assetsLeft) external view returns (uint256[] memory);

TestTokenBalanceTracker

Git Source

Inherits: TokenBalanceTrackerUpgradeable

Functions

mockIncreaseTokenBalance

function mockIncreaseTokenBalance(uint256 _amount) external;

mockDecreaseTokenBalance

function mockDecreaseTokenBalance(uint256 _amount) external;

TestTranchePool

Git Source

Inherits: TranchePool, TestTokenBalanceTracker

Base

Git Source

Inherits: AccessControl, Pausable

State Variables

PAUSER_ROLE

bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a;

MANAGER_ROLE

bytes32 public constant MANAGER_ROLE = 0x241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08;

Functions

constructor

constructor(address _admin, address _pauser);

pause

function pause() external onlyRole(PAUSER_ROLE);

unpause

function unpause() external onlyRole(PAUSER_ROLE);

_grantManagerRole

function _grantManagerRole(address _manager) internal;

_requireManagerRole

function _requireManagerRole() internal view;

Errors

NotManager

error NotManager();

CurrencyConverter

Git Source

Inherits: Base, ICurrencyConverter

This smart contract is responsible for converting between different currencies in a financial ecosystem. It allows for the conversion of USD to another currency (e.g., won) and vice versa, using a specified exchange rate. The main functions include setting the exchange rate, retrieving the current exchange rate and its last update timestamp, converting a specified amount from USD to the target currency, and converting a specified amount from the target currency to USD. This contract works in conjunction with other financial contracts to facilitate currency conversions in a portfolio.

Use decimal 18 for won.

State Variables

WON_DECIMALS

uint256 constant WON_DECIMALS = 18;

EXCHANGE_RATE_DECIMALS

uint256 constant EXCHANGE_RATE_DECIMALS = 2;

usd

IERC20Metadata public usd;

exchangeRate

uint256 public exchangeRate;

updatedTs

uint256 public updatedTs;

Functions

constructor

constructor(
    IProtocolConfig _protocolConfig,
    IERC20Metadata _usd,
    address _manager,
    uint256 _exchangeRate
)
    Base(_protocolConfig.protocolAdmin(), _protocolConfig.pauser());

setExchangeRate

set the exchange rate between WON and USD

the caller is contract keeper

function setExchangeRate(uint256 _exchangeRate) external;

getExchangeRate

get the exchange rate between WON and USD

function getExchangeRate() external view returns (uint256, uint256);

convertFromUSD

constructor guarantees 18 = won decimals >= usd decimals

function convertFromUSD(uint256 usdAmount) external view returns (uint256 wonAmount);

Parameters

NameTypeDescription
usdAmountuint256the amount of USD received

Returns

NameTypeDescription
wonAmountuint256the amount of WON to give

convertToUSD

constructor guarantees 18 = won decimals >= usd decimals

function convertToUSD(uint256 wonAmount) external view returns (uint256 usdAmount);

Parameters

NameTypeDescription
wonAmountuint256the amount of WON received

Returns

NameTypeDescription
usdAmountuint256the amount of USD to give

_setExchangeRate

function _setExchangeRate(uint256 _exchangeRate) internal;

DepositController

Git Source

Inherits: Base, IDepositController

This smart contract is responsible for managing the deposit process of a tranche pool in a portfolio. It handles the distribution of shares and fees when depositing assets and minting shares. The main functions include calculating the number of shares for a given deposit amount, estimating the total assets for a given number of shares, determining the maximum deposit amount and maximum mintable shares based on a given ceiling, and setting the deposit fee rate. This contract works in conjunction with the TranchePool contract to manage deposits and maintain the portfolio.

State Variables

depositFeeRate

uint256 public depositFeeRate;

BASIS_PRECISION

uint256 constant BASIS_PRECISION = 10_000;

Functions

constructor

constructor(
    IProtocolConfig _protocolConfig,
    address _manager,
    uint256 _depositFeeRate
)
    Base(_protocolConfig.protocolAdmin(), _protocolConfig.pauser());

onDeposit

Handle deposit of assets and distribute shares and fees accordingly

function onDeposit(address, uint256 assets, address receiver) external returns (uint256 shares, uint256 fees);

Parameters

NameTypeDescription
<none>address
assetsuint256The amount of assets being deposited
receiveraddressThe address receiving the shares

Returns

NameTypeDescription
sharesuint256The amount of shares minted for the deposit
feesuint256The amount of fees collected during the deposit

onMint

Handle minting of shares and distribute assets and fees accordingly

function onMint(address, uint256 shares, address receiver) external returns (uint256 assets, uint256 fees);

Parameters

NameTypeDescription
<none>address
sharesuint256The amount of shares being minted
receiveraddressThe address receiving the assets

Returns

NameTypeDescription
assetsuint256The amount of assets corresponding to the minted shares
feesuint256The amount of fees collected during the minting

previewDeposit

Preview the number of shares that will be minted for a given amount of assets

function previewDeposit(uint256 assets) public view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to be deposited

Returns

NameTypeDescription
sharesuint256The estimated number of shares to be minted

previewMint

Preview the total amount of assets (including fees) for a given number of shares

function previewMint(uint256 shares) public view returns (uint256);

Parameters

NameTypeDescription
sharesuint256The amount of shares to be minted

Returns

NameTypeDescription
<none>uint256assets The estimated total amount of assets (including fees) for the given shares

maxDeposit

Calculate the maximum deposit amount based on the given ceiling

function maxDeposit(address, uint256 ceiling) public view returns (uint256);

Parameters

NameTypeDescription
<none>address
ceilinguint256The maximum allowed total assets

Returns

NameTypeDescription
<none>uint256assets The maximum deposit amount under the given ceiling

maxMint

Calculate the maximum number of shares that can be minted based on the given ceiling

function maxMint(address receiver, uint256 ceiling) external view returns (uint256);

Parameters

NameTypeDescription
receiveraddressThe address receiving the assets
ceilinguint256The maximum allowed total assets

Returns

NameTypeDescription
<none>uint256shares The maximum number of shares that can be minted under the given ceiling

setDepositFeeRate

Set the deposit fee rate

function setDepositFeeRate(uint256 _depositFeeRate) external;

Parameters

NameTypeDescription
_depositFeeRateuint256The new deposit fee rate

_calculateDepositFee

function _calculateDepositFee(uint256 assets) internal view returns (uint256);

_calculateMaxDeposit

function _calculateMaxDeposit(uint256 assets) internal view returns (uint256);

FixedInterestBulletLoans

Git Source

Inherits: Base, ERC721, IFixedInterestBulletLoans

State Variables

portfolio

IPortfolio public portfolio;

currencyConverter

ICurrencyConverter public currencyConverter;

loans

LoanMetadata[] internal loans;

Functions

onlyLoanStatus

modifier onlyLoanStatus(uint256 loanId, FixedInterestBulletLoanStatus _status);

constructor

constructor(
    string memory name_,
    string memory symbol_,
    IProtocolConfig _protocolConfig,
    ICurrencyConverter _currencyConverter,
    address _manager
)
    ERC721(name_, symbol_)
    Base(_protocolConfig.protocolAdmin(), _protocolConfig.pauser());

loanData

Retrieve loan data for a specific loan ID

function loanData(uint256 loanId) external view returns (LoanMetadata memory);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>LoanMetadataThe loan metadata as a LoanMetadata struct

getRecipient

Get the recipient address of a loan with the specified ID

function getRecipient(uint256 loanId) external view returns (address);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>addressThe recipient address

getStatus

Get the status of a loan with the specified ID

function getStatus(uint256 loanId) external view returns (FixedInterestBulletLoanStatus);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>FixedInterestBulletLoanStatusThe loan status as a FixedInterestBulletLoanStatus enum value

currentUsdValue

Calculate the loan value at the current timestamp

function currentUsdValue(uint256 loanId) public view override returns (uint256);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>uint256loan value. It remains the same after loan.endDate

expectedUsdRepayAmount

Calculate the amount to repay. It is the same regardless of the repaying time.

function expectedUsdRepayAmount(uint256 loanId) public view override returns (uint256);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>uint256repayment amount

setPortfolio

Set the portfolio contract

The caller must have the manager role

function setPortfolio(IPortfolio _portfolio) external;

Parameters

NameTypeDescription
_portfolioIPortfolioThe address of the portfolio contract

setCurrencyConverter

Set the currency converter contract

The caller must have the manager role

function setCurrencyConverter(ICurrencyConverter _currencyConverter) external;

Parameters

NameTypeDescription
_currencyConverterICurrencyConverterThe address of the currency converter contract

issueLoan

Issue a new loan with the specified parameters

function issueLoan(IssueLoanInputs calldata loanInputs) external override returns (uint256);

Parameters

NameTypeDescription
loanInputsIssueLoanInputsThe input parameters for the new loan

Returns

NameTypeDescription
<none>uint256The ID of the newly created loan

startLoan

Start a loan with the specified ID

The loan must be in the Created status and the caller must be the portfolio contract

function startLoan(uint256 loanId)
    external
    whenNotPaused
    onlyLoanStatus(loanId, FixedInterestBulletLoanStatus.Created)
    returns (uint256 principal);

Parameters

NameTypeDescription
loanIduint256The ID of the loan to start

Returns

NameTypeDescription
principaluint256The borrowed principal amount of the loan in USD

repayLoan

Repay a loan with the specified ID and amount

The loan must be in the Started status and the caller must be the portfolio contract

function repayLoan(
    uint256 loanId,
    uint256 usdAmount
)
    external
    whenNotPaused
    onlyLoanStatus(loanId, FixedInterestBulletLoanStatus.Started);

Parameters

NameTypeDescription
loanIduint256The ID of the loan to repay
usdAmountuint256The amount to repay in USD

repayDefaultedLoan

Repay a defaulted loan with the specified ID and amount

The loan must be in the Defaulted status and the caller must be the portfolio contract

function repayDefaultedLoan(
    uint256 loanId,
    uint256 usdAmount
)
    external
    whenNotPaused
    onlyLoanStatus(loanId, FixedInterestBulletLoanStatus.Defaulted);

Parameters

NameTypeDescription
loanIduint256The ID of the defaulted loan to repay
usdAmountuint256The amount to repay in USD

cancelLoan

Cancel a loan with the specified ID

The loan must be in the Created status and the caller must be the portfolio contract

function cancelLoan(uint256 loanId)
    external
    whenNotPaused
    onlyLoanStatus(loanId, FixedInterestBulletLoanStatus.Created);

Parameters

NameTypeDescription
loanIduint256The ID of the loan to cancel

markLoanAsDefaulted

Mark a loan as defaulted with the specified ID

The loan must be in the Started status and the caller must be the portfolio contract

function markLoanAsDefaulted(uint256 loanId)
    external
    whenNotPaused
    onlyLoanStatus(loanId, FixedInterestBulletLoanStatus.Started);

Parameters

NameTypeDescription
loanIduint256The ID of the loan to mark as defaulted

getLoansLength

Get the total number of loans

function getLoansLength() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256The total number of loans

isOverdue

Check if a loan with the specified ID is overdue

function isOverdue(uint256 loanId) external view returns (bool);

Parameters

NameTypeDescription
loanIduint256The ID of the loan

Returns

NameTypeDescription
<none>boolA boolean value indicating if the loan is overdue

supportsInterface

function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, ERC721) returns (bool);

_getUsdPrincipal

function _getUsdPrincipal(uint256 loanId) internal view returns (uint256);

_changeLoanStatus

function _changeLoanStatus(uint256 loanId, FixedInterestBulletLoanStatus _status) internal;

_requirePortfolio

function _requirePortfolio() internal view;

LoansManager

Git Source

Inherits: ILoansManager, IERC721Receiver, Initializable, TokenBalanceTrackerUpgradeable

State Variables

fixedInterestBulletLoans

IFixedInterestBulletLoans public fixedInterestBulletLoans;

asset

IERC20 public asset;

activeLoanIds

uint256[] public activeLoanIds;

issuedLoanIds

mapping(uint256 => bool) public issuedLoanIds;

__gap

uint256[50] private __gap;

Functions

__LoanManager_init

function __LoanManager_init(
    IFixedInterestBulletLoans _fixedInterestBulletLoans,
    IERC20 _asset
)
    internal
    onlyInitializing;

_transferAsset

function _transferAsset(address to, uint256 amount) internal;

_transferAssetFrom

function _transferAssetFrom(address from, address to, uint256 amount) internal;

_addLoan

function _addLoan(AddLoanParams calldata params) internal returns (uint256 loanId);

_fundLoan

function _fundLoan(uint256 loanId) internal returns (uint256 principal);

_repayLoan

function _repayLoan(uint256 loanId) internal returns (uint256 amount);

_repayDefaultedLoan

function _repayDefaultedLoan(uint256 loanId, uint256 usdAmount) internal;

_cancelLoan

function _cancelLoan(uint256 loanId) internal;

_markLoanAsDefaulted

function _markLoanAsDefaulted(uint256 loanId) internal;

_tryToExcludeLoan

function _tryToExcludeLoan(uint256 loanId) internal;

onERC721Received

function onERC721Received(
    address operator,
    address from,
    uint256 tokenId,
    bytes calldata data
)
    external
    override
    returns (bytes4);

_calculateOverdueValue

function _calculateOverdueValue() internal view returns (uint256 overdueValue);

OrderController

Git Source

Inherits: IOrderController, Base

The OrderController is for handling deposit and withdrawal orders.

State Variables

portfolio

IPortfolio public portfolio;

token

IERC20 public token;

tranche

ITranchePool public tranche;

dust

uint256 public dust;

NULL

uint256 public constant NULL = 0;
uint256 public constant HEAD = 0;

nextOrderId

uint256 internal nextOrderId = 1;

orders

mapping(uint256 => Order) internal orders;

Functions

constructor

constructor(
    ITranchePool tranche_,
    IProtocolConfig protocolConfig_,
    IPortfolio portfolio_,
    uint256 dust_,
    address manager_
)
    Base(protocolConfig_.protocolAdmin(), protocolConfig_.pauser());

deposit

Allows a user to deposit tokens and create a DEPOSIT order. It doesn't gurantee deposit

The order can be executed if there's a matching withdrawal request. The caller should approve tokens prior to calling this function.

function deposit(uint256 tokenAmount, uint256 iterationLimit) external whenNotPaused;

Parameters

NameTypeDescription
tokenAmountuint256The amount of tokens to deposit.
iterationLimituint256The maximum number of orders to process in a single call.

withdraw

Allows a user to withdraw tranches and create a WITHDRAW order.

The order can be executed if there's a matching deposit request. The caller should approve tranches prior to calling this function.

function withdraw(uint256 trancheAmount, uint256 iterationLimit) external whenNotPaused;

Parameters

NameTypeDescription
trancheAmountuint256The amount of tranches to withdraw.
iterationLimituint256The maximum number of orders to process in a single call.

cancelOrder

Allows a user to cancel their pending order.

This can be called by the user who placed the order only.

function cancelOrder() external;

cancelDustOrder

Allows any users to cancel dust order.

function cancelDustOrder(uint256 orderId) external;

Parameters

NameTypeDescription
orderIduint256The order id to cancel.

setDust

function setDust(uint256 _dust) external;

expectedTokenAmount

Calculate the expected token amount for a given tranche amount.

function expectedTokenAmount(uint256 trancheAmount) public view virtual returns (uint256);

Parameters

NameTypeDescription
trancheAmountuint256The amount of tranches to convert.

Returns

NameTypeDescription
<none>uint256The expected token amount.

expectedTrancheAmount

Calculate the expected tranche amount for a given token amount.

function expectedTrancheAmount(uint256 tokenAmount) public view virtual returns (uint256);

Parameters

NameTypeDescription
tokenAmountuint256The amount of tokens to convert.

Returns

NameTypeDescription
<none>uint256The expected tranche amount.

expectedTokenAmountCeil

function expectedTokenAmountCeil(uint256 trancheAmount) internal view virtual returns (uint256);

expectedTrancheAmountCeil

function expectedTrancheAmountCeil(uint256 tokenAmount) internal view virtual returns (uint256);

getUserOrder

Return the order of the given user.

function getUserOrder(address user) public view returns (Order memory);

Parameters

NameTypeDescription
useraddressThe user address.

Returns

NameTypeDescription
<none>OrderThe order.

getOrders

Return all orders.

function getOrders() public view returns (Order[] memory);

Returns

NameTypeDescription
<none>Order[]The orders.

getValidOrders

Return the valid orders and the current order type.

function getValidOrders() public view returns (Order[] memory, OrderType);

Returns

NameTypeDescription
<none>Order[]orders The valid orders.
<none>OrderTypeorderType The type of the order.

getOrderCount

Return the count of all orders.

function getOrderCount() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256The count of all orders.

getValidOrderCount

Return the count of valid orders and the current order type.

function getValidOrderCount() public view returns (uint256 count, OrderType orderType);

Returns

NameTypeDescription
countuint256The count of valid orders.
orderTypeOrderTypeThe type of the current order.

currentOrderType

Return the type of the current order in the linked list of orders

function currentOrderType() public view returns (OrderType);

_processWithdrawOrder

function _processWithdrawOrder(uint256 tokenAmount, uint256 iterationLimit) internal returns (uint256, uint256);

_processDepositOrder

function _processDepositOrder(uint256 trancheAmount, uint256 iterationLimit) internal returns (uint256, uint256);

_createOrder

function _createOrder(address user, uint256 amount, OrderType orderType) internal;

_removeOrder

function _removeOrder(uint256 orderId) internal;

_cancelOrder

function _cancelOrder(address user) internal;

_executeDepositOrder

function _executeDepositOrder(uint256 tokenAmount, address user) internal returns (uint256 trancheAmount);

_executeDepositOrder

function _executeDepositOrder(uint256 tokenAmount, uint256 trancheAmount, address user) internal;

_executeWithdrawOrder

function _executeWithdrawOrder(uint256 tokenAmount, uint256 trancheAmount, address user) internal;

_executeWithdrawOrder

function _executeWithdrawOrder(uint256 trancheAmount, address user) internal returns (uint256 tokenAmount);

_setToken

function _setToken(IERC20 _token) internal;

_setTranche

function _setTranche(ITranchePool _tranche) internal;

_setPortfolio

function _setPortfolio(IPortfolio _portfolio) internal;

_setDust

function _setDust(uint256 _dust) internal;

_validateOrder

check user token allowance for corresponding order type

function _validateOrder(Order memory order, OrderType orderType) internal view returns (bool);

_validateInputs

function _validateInputs(address user, uint256 amount, OrderType orderType) internal view;

_checkBalance

function _checkBalance(address user, uint256 amount, OrderType orderType) internal view returns (bool);

_checkAllowance

function _checkAllowance(address user, uint256 amount, OrderType orderType) internal view returns (bool);

_isStatus

function _isStatus(Status allowedStatus) internal view virtual returns (bool);

Portfolio

Git Source

Inherits: IPortfolio, UpgradeableBase, LoansManager

This smart contract represents a portfolio of loans that are managed by tranches. Each tranche can have different risk profiles and yields. The main functions are starting the portfolio, closing senior and equity tranches, and handling loans. It uses the LoansManager contract to manage loans and relies on TranchePool contracts for tranche management.

Min number of tranches is 2, first tranche is always equity.

State Variables

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = 0x71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1;

tranches

tranche[0] is always equity

ITranchePool[] public tranches;

tranchesData

TrancheData[] public tranchesData;

status

Status public status;

startTimestamp

uint40 public startTimestamp;

stoppedTimestamp

uint256 public stoppedTimestamp;

Functions

initialize

function initialize(
    address manager,
    address governance,
    IERC20 _asset,
    IProtocolConfig _protocolConfig,
    TrancheInitData[] memory tranchesInitData,
    IFixedInterestBulletLoans _fixedInterestBulletLoans
)
    public
    initializer;

Parameters

NameTypeDescription
manageraddress
governanceaddress
_assetIERC20
_protocolConfigIProtocolConfig
tranchesInitDataTrancheInitData[][{equityTrancheAddress, targetApr}, {seniorTrancheAddress, targetApr}]
_fixedInterestBulletLoansIFixedInterestBulletLoans

start

Starts the portfolio to issue loans.

  • changes the state to Live
  • gathers assets to the portfolio from every tranche.*
function start() external whenNotPaused;

closeSenior

Allow the senior tranche to withdraw.

  • changes the state to SeniorClosed
  • Distribute the remaining assets to the senior tranche.*
function closeSenior() external whenNotPaused;

closeEquity

Allow the equity tranche to withdraw.

  • changes the state to EquityClosed
  • Distribute the remaining assets to the equity tranche.*
function closeEquity() external whenNotPaused;

calculateWaterfall

calculate each tranche values based only on the current assets.

no fee

function calculateWaterfall() public view returns (uint256[] memory);

Returns

NameTypeDescription
<none>uint256[]Array of current tranche values

calculateWaterfallForTranche

no fee

function calculateWaterfallForTranche(uint256 waterfallIndex) external view returns (uint256);

calculateWaterfallWithLoansForTranche

no fee

function calculateWaterfallWithLoansForTranche(uint256 waterfallIndex) external view returns (uint256);

calculateWaterfallWithLoans

calculate each tranche values given the (current assets + loans value).

no fee

function calculateWaterfallWithLoans() public view returns (uint256[] memory);

loansValue

calculate the total value of all active loans in the contract.

function loansValue() public view returns (uint256);

getTokenBalance

get token balance of this contract

function getTokenBalance() external view returns (uint256);

_validateStart

function _validateStart() internal view;

_validateCloseSenior

function _validateCloseSenior() internal view;

_validateCloseEquity

validate portfolio

function _validateCloseEquity() internal view;

_distributeToTranches

function _distributeToTranches(uint256 lowestIndex) internal;

_calculateWaterfall

calculate each tranche values based only on the current assets and the status.

1. if the portfolio is in the preparation / equity closed stage, return the current assets of each tranche. 2. if the portfolio is in the live / paused stage, calculate based on the current assets in the portfolio and the loans value. 3. if the portfolio is in the senior closed stage, return the current assets of each tranche except for the equity tranche.

function _calculateWaterfall(uint256 assetsLeft) internal view returns (uint256[] memory);

_assumedTrancheValue

function _assumedTrancheValue(uint256 trancheIdx, uint256 timestamp) internal view returns (uint256);

_changePortfolioStatus

function _changePortfolioStatus(Status newStatus) internal;

addLoan

Create loan

function addLoan(AddLoanParams calldata params) external whenNotPaused returns (uint256);

Parameters

NameTypeDescription
paramsAddLoanParamsLoan params

fundLoan

Fund the loan

function fundLoan(uint256 loanId) external whenNotPaused returns (uint256 principal);

Parameters

NameTypeDescription
loanIduint256Loan id

repayLoan

Repay the loan

function repayLoan(uint256 loanId) external whenNotPaused returns (uint256 amount);

Parameters

NameTypeDescription
loanIduint256Loan id

repayDefaultedLoan

Repay the loan

function repayDefaultedLoan(uint256 loanId, uint256 amount) external whenNotPaused;

Parameters

NameTypeDescription
loanIduint256Loan id
amountuint256amount

cancelLoan

cancel the loan

function cancelLoan(uint256 loanId) external;

Parameters

NameTypeDescription
loanIduint256loan id

getAssumedCurrentValues

function getAssumedCurrentValues()
    public
    view
    returns (uint256 equityValue, uint256 fixedRatePoolValue, uint256 overdueValue);

stopPortfolio

stop the portfolio

function stopPortfolio() external;

restartPortfolio

restart the portfolio

function restartPortfolio() external;

checkPortfolioNeedStop

function checkPortfolioNeedStop(
    uint256 equityValue,
    uint256 fixedRatePoolValue,
    uint256 overdueValue
)
    public
    returns (bool);

checkPortfolioNeedRestart

function checkPortfolioNeedRestart(
    uint256 equityValue,
    uint256 fixedRatePoolValue,
    uint256 overdueValue
)
    public
    returns (bool);

markLoanAsDefaulted

Cancel the loan

function markLoanAsDefaulted(uint256 loanId) external whenNotPaused;

Parameters

NameTypeDescription
loanIduint256Loan id

increaseTokenBalance

function increaseTokenBalance(uint256 amount) external;

_requireManagerOrCollateralOwner

function _requireManagerOrCollateralOwner(address collateral, uint256 collateralId) internal view;

_requireTranchePool

function _requireTranchePool() internal view;

_requireGovernanceRole

function _requireGovernanceRole() internal view;

_grantGovernanceRole

function _grantGovernanceRole(address governance) internal;

ProtocolConfig

Git Source

Inherits: IProtocolConfig, Base

State Variables

protocolAdmin

address public protocolAdmin;

pauser

address public pauser;

Functions

constructor

constructor(address _protocolAdmin, address _pauser) Base(_msgSender(), _pauser);

setProtocolAdmin

function setProtocolAdmin(address _protocolAdmin) external onlyRole(DEFAULT_ADMIN_ROLE);

setPauser

function setPauser(address _pauser) external onlyRole(DEFAULT_ADMIN_ROLE);

TokenBalanceTrackerUpgradeable

Git Source

State Variables

_tokenBalance

uint256 private _tokenBalance;

__gap

This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps

uint256[49] private __gap;

Functions

_getTokenBalance

function _getTokenBalance() internal view returns (uint256);

_increaseTokenBalance

function _increaseTokenBalance(uint256 _amount) internal;

_decreaseTokenBalance

function _decreaseTokenBalance(uint256 _amount) internal;

Errors

InsufficientTokenBalance

error InsufficientTokenBalance();

TranchePool

Git Source

Inherits: ITranchePool, UpgradeableBase, ERC20Upgradeable, TokenBalanceTrackerUpgradeable

This smart contract represents a tranche pool in a portfolio of loans managed by tranches. Each tranche pool can have different risk profiles and yields within the portfolio. The main functions of this contract include setting the associated portfolio, deposit and withdraw controllers, ceiling for each tranche pool, and converting between assets and shares. It works in conjunction with the Portfolio contract and relies on external controllers for deposit and withdrawal management. This contract also implements the IERC4626 standard.

State Variables

portfolio

the associated portfolio for this tranche pool

IPortfolio public portfolio;

depositController

IDepositController public depositController;

withdrawController

IWithdrawController public withdrawController;

token

ERC20 token to deposit

IERC20 public token;

feeReceiver

address public feeReceiver;

ceiling

the ceiling for this tranche pool

uint256 public ceiling;

waterfallIndex

the waterfall index for this tranche pool. 0 is equity and 1 is senior

uint256 public waterfallIndex;

Functions

initialize

Use portfolio.paused() for pausable

function initialize(
    string memory _name,
    string memory _symbol,
    IProtocolConfig _protocolConfig,
    IDepositController _depositController,
    IWithdrawController _withdrawController,
    IERC20 _token,
    address manager,
    uint256 _ceiling,
    uint256 _waterfallIndex
)
    public
    initializer;

portfolioNotPaused

modifier portfolioNotPaused();

asset

function asset() external view returns (address assetTokenAddress);

totalAssets

function totalAssets() public view returns (uint256 totalManagedAssets);

availableLiquidity

function availableLiquidity() public view returns (uint256);

deposit

function deposit(uint256 assets, address receiver) external portfolioNotPaused returns (uint256);

convertToShares

function convertToShares(uint256 assets) external view returns (uint256 shares);

convertToSharesCeil

Converts a given amount of assets to shares (rounded up)

function convertToSharesCeil(uint256 assets) external view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to convert

Returns

NameTypeDescription
sharesuint256The equivalent amount of shares

convertToAssets

function convertToAssets(uint256 shares) external view returns (uint256 assets);

convertToAssetsCeil

Converts a given amount of shares to assets (rounded up)

function convertToAssetsCeil(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to convert

Returns

NameTypeDescription
assetsuint256The equivalent amount of assets

maxDeposit

function maxDeposit(address receiver) public view returns (uint256 maxAssets);

previewDeposit

function previewDeposit(uint256 assets) external view returns (uint256 shares);

maxMint

function maxMint(address receiver) public view returns (uint256 maxShares);

previewMint

function previewMint(uint256 shares) external view returns (uint256 assets);

mint

function mint(uint256 shares, address receiver) external portfolioNotPaused returns (uint256);

maxWithdraw

function maxWithdraw(address owner) public view returns (uint256 maxAssets);

previewWithdraw

function previewWithdraw(uint256 assets) external view returns (uint256 shares);

withdraw

function withdraw(uint256 assets, address receiver, address owner) external portfolioNotPaused returns (uint256);

maxRedeem

function maxRedeem(address owner) public view returns (uint256 maxShares);

previewRedeem

function previewRedeem(uint256 shares) external view returns (uint256 assets);

redeem

function redeem(uint256 shares, address receiver, address owner) external portfolioNotPaused returns (uint256);

setDepositController

Sets the deposit controller for this tranche pool

function setDepositController(IDepositController newController) external;

Parameters

NameTypeDescription
newControllerIDepositControllerThe new deposit controller to set

setWithdrawController

Sets the withdraw controller for this tranche pool

function setWithdrawController(IWithdrawController newController) external;

Parameters

NameTypeDescription
newControllerIWithdrawControllerThe new withdraw controller to set

setCeiling

Sets the ceiling for this tranche pool

function setCeiling(uint256 newCeiling) external;

Parameters

NameTypeDescription
newCeilinguint256The new ceiling to set

setPortfolio

Sets the portfolio for this tranche pool

function setPortfolio(IPortfolio _portfolio) external;

Parameters

NameTypeDescription
_portfolioIPortfolioThe new portfolio to set

onPortfolioStart

Called when the portfolio starts

function onPortfolioStart() external returns (uint256);

Returns

NameTypeDescription
<none>uint256The balance of the tranche pool

increaseTokenBalance

Increases the token balance of the tranche pool by the given amount

function increaseTokenBalance(uint256 amount) external;

Parameters

NameTypeDescription
amountuint256The amount to increase the token balance by

_payDepositFee

function _payDepositFee(uint256 fee) internal;

_payWithdrawFee

function _payWithdrawFee(uint256 fee) internal;

_transferAsset

function _transferAsset(address to, uint256 amount) internal;

_transferAssetFrom

function _transferAssetFrom(address from, address to, uint256 amount) internal;

_depositAssets

function _depositAssets(uint256 assets, uint256 shares, address receiver) internal;

_withdrawAssets

function _withdrawAssets(uint256 assets, uint256 shares, address receiver, address owner) internal;

_safeBurn

function _safeBurn(address owner, uint256 shares) internal;

_requirePortfolio

function _requirePortfolio() internal view;

UpgradeableBase

Git Source

Inherits: AccessControlUpgradeable, UUPSUpgradeable, PausableUpgradeable

State Variables

PAUSER_ROLE

bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a;

MANAGER_ROLE

bytes32 public constant MANAGER_ROLE = 0x241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08;

Functions

__UpgradeableBase_init

function __UpgradeableBase_init(address admin, address pauser) internal onlyInitializing;

_authorizeUpgrade

function _authorizeUpgrade(address) internal override onlyRole(DEFAULT_ADMIN_ROLE);

pause

function pause() external onlyRole(PAUSER_ROLE);

unpause

function unpause() external onlyRole(PAUSER_ROLE);

_grantManagerRole

function _grantManagerRole(address _manager) internal;

_requireManagerRole

function _requireManagerRole() internal view;

Errors

NotManager

error NotManager();

WithdrawController

Git Source

Inherits: Base, IWithdrawController

This smart contract is responsible for managing the withdrawal process of a tranche pool in a portfolio. It handles the calculation of withdrawal and redemption fees, as well as the withdrawal of assets and redemption of shares. The main functions include determining the maximum withdrawable assets and redeemable shares for a user, previewing the amount of shares to burn for a given asset withdrawal, estimating the amount of assets to receive after burning a given number of shares, and setting the withdrawal fee rate. This contract works in conjunction with the TranchePool contract to manage withdrawals and maintain the portfolio.

State Variables

withdrawFeeRate

uint256 public withdrawFeeRate;

BASIS_PRECISION

uint256 constant BASIS_PRECISION = 10_000;

Functions

constructor

constructor(
    IProtocolConfig _protocolConfig,
    address _manager,
    uint256 _withdrawFeeRate
)
    Base(_protocolConfig.protocolAdmin(), _protocolConfig.pauser());

onWithdraw

Executes the withdrawal process, returning the amount of shares to burn and fees.

The sender and owner parameters are not used in this implementation.

function onWithdraw(
    address,
    uint256 assets,
    address receiver,
    address
)
    external
    returns (uint256 shares, uint256 fees);

Parameters

NameTypeDescription
<none>address
assetsuint256The amount of assets to withdraw.
receiveraddressThe address that will receive the assets.
<none>address

Returns

NameTypeDescription
sharesuint256The amount of shares to burn.
feesuint256The amount of fees to be paid.

onRedeem

function onRedeem(
    address sender,
    uint256 shares,
    address receiver,
    address owner
)
    external
    returns (uint256 assets, uint256 fees);

maxWithdraw

A user cannot withdraw in the live status.

function maxWithdraw(address owner) external view returns (uint256 assets);

Returns

NameTypeDescription
assetsuint256The max amount of assets that the user can withdraw.

maxRedeem

A user cannot redeem in the live status.

function maxRedeem(address owner) external view returns (uint256);

Returns

NameTypeDescription
<none>uint256shares The max amount of shares that the user can burn to withdraw assets.

previewWithdraw

Preview the amount of shares to burn to withdraw the given amount of assets.

It always rounds up the result. e.g. 3/4 -> 1.

function previewWithdraw(uint256 assets) public view returns (uint256 shares);

Parameters

NameTypeDescription
assetsuint256The amount of assets to withdraw.

Returns

NameTypeDescription
sharesuint256The amount of shares to burn.

previewRedeem

Preview the amount of assets to receive after burning the given amount of shares.

function previewRedeem(uint256 shares) external view returns (uint256 assets);

Parameters

NameTypeDescription
sharesuint256The amount of shares to burn.

Returns

NameTypeDescription
assetsuint256The amount of assets to receive.

setWithdrawFeeRate

function setWithdrawFeeRate(uint256 _withdrawFeeRate) external;

_checkStatusToWithdraw

1. SeniorClosed: Tranches except for equity are allowed. 2. EquityClosed: All tranches are allowed.

function _checkStatusToWithdraw(Status status, uint256 waterfallIndex) internal view returns (bool);

_calculateWithdrawFee

function _calculateWithdrawFee(uint256 assets) internal view returns (uint256);