Assessment reports>Origami Finance>Threat Model>investWithToken

Function: investWithToken(address account, IOrigamiInvestment.InvestQuoteData quoteData)

The function can be called only from the LovToken contract, but the LovToken:investWithToken, which triggers this function, can be called by any user. The global investmentsPaused should not be true.

Inputs

  • account

    • Constraints: If the global variable allowAll is true, the account is not validated. Otherwise, if the address is not a contract, the allowedAccounts should contain the account address.

    • Impact: The address of the caller of the LovToken:investWithToken function who initiated the invest process.

  • quoteData.fromToken

    • Constraints: The address is validated inside the _depositIntoReserves function. If fromToken is equal to the depositAsset, then depositAsset will be deposited to the _reserveToken. If fromToken is equal to the _reserveToken, then its tokens are already deposited for the _manager contract; otherwise, the function will revert.

    • Impact: The token that will be invested.

  • quoteData.fromTokenAmount

    • Constraints: Cannot be zero.

    • Impact: If fromToken == depositAsset, then fromTokenAmount tokens will be deposited to the _reserveToken contract using deposit(). If fromToken == _reserveToken and then fromTokenAmount, then tokens were already deposited.

  • quoteData.maxSlippageBps

    • Constraints: Is not used and is not validated.

    • Impact: The maximum allowed slippage of the expectedInvestmentAmount.

  • quoteData.deadline

    • Constraints: Is not used and is not validated.

    • Impact: The maximum deadline to execute the transaction.

  • quoteData.expectedInvestmentAmount

    • Constraints: Is not used and is not validated.

    • Impact: The expected amount of this lovToken token to receive in return.

  • quoteData.minInvestmentAmount

    • Constraints: There is a check that investmentAmount is not less than quoteData.minInvestmentAmount.

    • Impact: The minimum amount of lovToken to receive.

  • quoteData.underlyingInvestmentQuoteData

    • Constraints: Is not used and is not validated.

    • Impact: Extra quote parameters.

Branches and code coverage

Intended branches

  • investWithToken was successfully completed as expected.

Negative behavior

  • Caller is not approved lovToken contract.

  • The investmentAmount is less than minInvestmentAmount.

  • fromToken is not supported.

  • The pause state for invest is true

  • quoteData.fromTokenAmount is zero

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 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 to reservesBalance(), and debt shares, which is equal to the cache.liabilities.

    • What happens if it reverts, reenters or does other unusual control flow? N/A.

  • this._depositIntoReserves(quoteData.fromToken, quoteData.fromTokenAmount) -> OrigamiLovTokenErc4626Manager._depositIntoReserves

    • What is controllable? quoteData.fromToken and quoteData.fromTokenAmount.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the number invested reserves.

    • What happens if it reverts, reenters or does other unusual control flow? If fromToken == _reserveToken, the function will return quoteData.fromTokenAmount. If fromToken == depositAsset, the function will return the result of the _reserveToken.deposit() function; otherwise, this function will revert.

  • this._reservesToShares(cache, newReservesAmount)

    • What is controllable? newReservesAmount.

    • If the return value is controllable, how is it used and how can it go wrong? If cache.totalSupply == 0, the function will return newReservesAmount, so _reservesToShares will be 1:1.

    • What happens if it reverts, reenters or does other unusual control flow? Calculate the number of shares for the corresponding reserves, cache.totalSupply, and _redeemableReserves amounts.

Zellic © 2025Back to top ↑