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.investmentTokenAmountConstraints: Is not validated here — all checks performed by the lovToken contract.
Impact: lovTokens will be burned from the manager account.
quoteData.toTokenConstraints: There is verification that
toTokencan be equal to thedepositAssetor_reserveToken; otherwise, the transaction will revert.Impact: The
recipientwill receive these tokens in return —toTokenshould be an accepted ERC-20 token.
quoteData.maxSlippageBpsConstraints: Is not used and is not validated.
Impact: The maximum allowed slippage of the
expectedToTokenAmount.
quoteData.deadlineConstraints: Is not used and is not validated.
Impact: N/A.
quoteData.expectedToTokenAmountConstraints: Is not used and is not validated.
Impact: N/A.
quoteData.minToTokenAmountConstraints: There is a check that
toTokenAmountis not less thanquoteData.minToTokenAmount.Impact: The minimum amount of
toTokento receive.
quoteData.underlyingInvestmentQuoteDataConstraints: Is not used and is not validated.
Impact: N/A.
recipientConstraints: Cannot be zero address.
Impact: The receiver of the
toToken.
Branches and code coverage
Intended branches
exitToTokenwas successfully completed as expected.
Negative behavior
Caller is not an approved lovToken contract.
The
toTokenAmountis less thanminToTokenAmount.toTokenis not supported.recipientis 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/repayfunction 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
exitFeeRateis 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.totalSupplyis 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.assetsis less than liabilities with buffer), then the_sharesToReservesfunction 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._redeemFromReservesWhat is controllable?
quoteData.toTokenandrecipient.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
toTokenis neitherdepositAssetor_reserveToken. If equal to_reserveToken,reservesAmountof_reserveTokenwill be transferred to therecipient. Otherwise, thereservesAmountamount of tokens will be redeemed from the_reserveTokencontract, thereservesAmountreserve tokens will be burned, and assets tokens will transferred to therecipient.