Assessment reports>Origami Finance>Threat Model>investWithToken

Function: investWithToken(InvestQuoteData quoteData)

Allows users to invest reserveToken or approved ERC-20 tokens. If the global variable allowAll is true, the msg.sender is not validated. Otherwise, if the address is not a contract, the allowedAccounts should contain the msg.sender address. In exchange, msg.sender will receive the Origami investment tokens.

Inputs

  • quoteData.fromToken

    • Constraints: It can be reserveToken or approved ERC-20 token to invest to reserveToken contract.

    • Impact: If quoteData.fromToken == reserveToken, then reserveToken is enough to just transfer fromTokenAmount to this contract from msg.sender. Otherwise, fromToken will be transferred to this contract, and after that, invested to the reserveToken contract.

  • quoteData.fromTokenAmount

    • Constraints: Cannot be equal to zero.

    • Impact: The amount of tokens to invest.

  • quoteData.underlyingInvestmentQuoteData

    • Constraints: N/A.

    • Impact: Extra quote parameters that will be provided to the reserveToken.investWithToken() function for investing fromToken tokens to the reserveToken contract.

Branches and code coverage

Negative behavior

  • Non-whitelisted caller

  • quoteData.fromToken is not an approved token address.

  • The caller does not own enough fromToken tokens.

  • investmentAmount is less than quoteData.minInvestmentAmount.

  • quoteData.fromToken and quoteData.underlyingInvestmentQuoteData.fromToken are different.

  • quoteData.fromTokenAmount is less than quoteData.underlyingInvestmentQuoteData.fromTokenAmount.

Function call analysis

  • SafeERC20.safeTransferFrom(IERC20(this.reserveToken), msg.sender, address(this), reservesAmount)

    • What is controllable? reservesAmount.

    • If the return value is controllable, how is it used and how can it go wrong? No return value.

    • What happens if it reverts, reenters or does other unusual control flow? Can revert if msg.sender does not have enough reserveToken to transfer. The function investWithToken has non-reentrant modifier.

  • SafeERC20.safeTransferFrom(IERC20(quoteData.fromToken), msg.sender, address(this), quoteData.fromTokenAmount)

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

    • If the return value is controllable, how is it used and how can it go wrong? No return value.

    • What happens if it reverts, reenters or does other unusual control flow? Can revert if msg.sender does not have enough fromToken to transfer. The function investWithToken has non-reentrant modifier.

  • IOrigamiInvestment(this.reserveToken).investWithToken(underlyingQuoteData)

    • What is controllable? underlyingQuoteData.

    • If the return value is controllable, how is it used and how can it go wrong? Return amount of received tokens in exchange of invested tokens.

    • What happens if it reverts, reenters or does other unusual control flow? Can revert if quoteData.underlyingInvestmentQuoteData.fromToken is not an approved token address. Also revert if quoteData.underlyingInvestmentQuoteData.fromTokenAmount is more than quoteData.fromTokenAmount.

  • this._issueSharesFromReserves(reservesAmount, msg.sender, quoteData.minInvestmentAmount)

    • What is controllable? reservesAmount and quoteData.minInvestmentAmount.

    • If the return value is controllable, how is it used and how can it go wrong? Return the minted shares amount — in case it is less than minSharesAmount, the function will revert.

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

Zellic © 2025Back to top ↑