Function: exitToToken(address, IOrigamiInvestment.ExitQuoteData quoteData, address recipient)
The function can be called only from the lovToken contract. Allows investor to exit from the reserve token.
Inputs
quoteData.investmentTokenAmount
Constraints: Is not validated here — all checks performed by the lovToken contract.
Impact: lovTokens will be burned from the manager account.
quoteData.toToken
Constraints: There is verification that
toToken
can be equal to thedepositAsset
or_reserveToken
; otherwise, the transaction will revert.Impact: The
recipient
will receive these tokens in return —toToken
should be an accepted ERC-20 token.
quoteData.maxSlippageBps
Constraints: Is not used and is not validated.
Impact: The maximum allowed slippage of the
expectedToTokenAmount
.
quoteData.deadline
Constraints: Is not used and is not validated.
Impact: N/A.
quoteData.expectedToTokenAmount
Constraints: Is not used and is not validated.
Impact: N/A.
quoteData.minToTokenAmount
Constraints: There is a check that
toTokenAmount
is not less thanquoteData.minToTokenAmount
.Impact: The minimum amount of
toToken
to receive.
quoteData.underlyingInvestmentQuoteData
Constraints: Is not used and is not validated.
Impact: N/A.
recipient
Constraints: Cannot be zero address.
Impact: The receiver of the
toToken
.
Branches and code coverage
Intended branches
exitToToken
was successfully completed as expected.
Negative behavior
Caller is not an approved lovToken contract.
The
toTokenAmount
is less thanminToTokenAmount
.toToken
is not supported.recipient
is zero address.The pause state for exit is true
Function call analysis
this.populateCache() -> this.liabilities() -> this.lendingClerk.borrowerDebt(address(this))
What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? The value is used to calculate the debt converted to shares, which in turn is used for A/L ratio calculation.
What happens if it reverts, reenters or does other unusual control flow? The function returns the current debt of this manager contract. The balance of debt tokens can be changed only over
borrow/repay
function or by the minter of debt tokens, who can transfer debt tokens between accounts.
this.populateCache() -> this.liabilities() -> this._reserveToken.previewWithdraw(debtInDepositAsset)
What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns debt amount converted to the shares. The value is used for
cache.liabilities
.What happens if it reverts, reenters or does other unusual control flow? N/A.
this.populateCache() -> this.lovToken.totalSupply()
What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns full number of minted lovTokens. The value is used for
cache.totalSupply
.What happens if it reverts, reenters or does other unusual control flow? N/A.
this._assetToLiabilityRatio(cache) -> OrigamiMath.mulDiv(cache.assets, OrigamiAbstractLovTokenManager.PRECISION, cache.liabilities, Rounding.ROUND_DOWN)
What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns current L/A ratio, which is calculated using total reserves balance
cache.assets
, which is equal toreservesBalance()
, and debt shares, which is equal to thecache.liabilities
.What happens if it reverts, reenters or does other unusual control flow? N/A.
BasisPointFraction.getRemainder(this.exitFeeRate, toBurnAmount)
What is controllable?
toBurnAmount
.If the return value is controllable, how is it used and how can it go wrong? Returns the number of tokens minus the exit fee.
What happens if it reverts, reenters or does other unusual control flow? Can revert if
exitFeeRate
is more thanBASIS_POINTS_DIVISOR
.
this._sharesToReserves(cache, reservesAmount) -> OrigamiMath.mulDiv(shares, this._userRedeemableReserves(cache), cache.totalSupply, Rounding.ROUND_DOWN)
What is controllable?
reservesAmount
==shares
.If the return value is controllable, how is it used and how can it go wrong? N/A.
What happens if it reverts, reenters or does other unusual control flow? In case
cache.totalSupply
is not zero, the reserved amount will be calculated as follows:shares.mulDiv(_userRedeemableReserves(cache), cache.totalSupply, OrigamiMath.Rounding.ROUND_DOWN);
.
this._sharesToReserves(cache, reservesAmount) -> this._userRedeemableReserves(cache)
What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Can return zero; if redeemable reserves are not available (
cache.assets
is less than liabilities with buffer), then the_sharesToReserves
function result also will be equal to zero.What happens if it reverts, reenters or does other unusual control flow? N/A.
this._redeemFromReserves(reservesAmount, quoteData.toToken, recipient) -> OrigamiLovTokenErc4626Manager._redeemFromReserves
What is controllable?
quoteData.toToken
andrecipient
.If the return value is controllable, how is it used and how can it go wrong? Returns the amount of redeemed tokens.
What happens if it reverts, reenters or does other unusual control flow? The function will revert if
toToken
is neitherdepositAsset
or_reserveToken
. If equal to_reserveToken
,reservesAmount
of_reserveToken
will be transferred to therecipient
. Otherwise, thereservesAmount
amount of tokens will be redeemed from the_reserveToken
contract, thereservesAmount
reserve tokens will be burned, and assets tokens will transferred to therecipient
.