Assessment reports>GTE>Threat Model>buy

Function: buy(address token, address recipient, uint256 amountOutBase, uint256 worstAmountInQuote)

This function allows buying amountOutBase tokens, but the amount of USDC to be spent is limited by worstAmountInQuote. After selling the BONDING_SUPPLY amount of LaunchToken, the remaining liquidity will be transferred to the Uniswap pool, and the current function will become unavailable for this token.

Inputs

  • token

    • Control: Full control.

    • Constraints: The status active of this token should be true, and launches should contain the token info.

    • Impact: The address of the LaunchToken to be bought.

  • recipient

    • Control: Full control.

    • Constraints: No constraints.

    • Impact: The address of the recipient of LaunchToken.

  • amountOutBase

    • Control: Full control.

    • Constraints: The total sold amount of LaunchToken cannot exceed BONDING_SUPPLY.

    • Impact: The desired amount of LaunchToken to be bought.

  • worstAmountInQuote

    • Control: Full control.

    • Constraints: No constraints.

    • Impact: The limited amount of USDC to be spent.

Branches and code coverage

Intended branches

  • amountOutBase is less than BONDING_SUPPLY.

  • amountOutBase is greater than BONDING_SUPPLY but has been successfully limited by BONDING_SUPPLY.

  • The remaining tokens were successfully swapped using the Uniswap pool

  • If the swap using the Uniswap pool failed, the remaining tokens were transferred to the caller.

Negative behavior

  • The token status is not active, because it doesn't exists

  • The token status is not active, because liquidity was transferred to the Uniswap pool.

  • worstAmountInQuote is less than amountInQuote.

Function call analysis

  • LaunchToken(token).unlock()

    • What is controllable? token.

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

    • What happens if it reverts, reenters or does other unusual control flow? This function unlocks the LaunchToken transferring.

  • data.bondingCurve.getAverageCostInY(token, this.baseToX(data.baseSoldFromCurve), this.baseToX(nextAmountSold))

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? The returned amountInQuote can be less or more than expected. If amountInQuote is less than expected, the user can buy tokens cheaper than expected; otherwise, the resulting amount can be more expensive than expected but not more than worstAmountInQuote.

    • What happens if it reverts, reenters or does other unusual control flow? It has a nonReentrant modifier.

  • SafeTransferLib.safeTransfer(token, recipient, amountOutBase)

    • What is controllable? recipient and amountOutBase.

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • SafeTransferLib.safeTransferFrom(address(this.quoteAsset), msg.sender, address(this), amountInQuote)

    • What is controllable? N/A.

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • SafeTransferLib.safeApprove(token, address(this.router), tokensToLock)

    • What is controllable? N/A.

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • SafeTransferLib.safeApprove(address(this.quoteAsset), address(this.router), data.quoteBoughtByCurve)

    • What is controllable? N/A.

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • this.router.addLiquidity(token, address(this.quoteAsset), tokensToLock, data.quoteBoughtByCurve, 0, 0, address(this), block.timestamp)

    • What is controllable? N/A.

    • If the return value is controllable, how is it used and how can it go wrong? Returned values are not used here.

    • What happens if it reverts, reenters or does other unusual control flow? If the pool already has liquidity, the initial price has already been determined. Therefore, only the portion of liquidity that matches the current rate will be added, rather than the full amount.

  • this._swapRemainingQuote(token, recipient, remainingQuote) -> SafeTransferLib.safeTransferFrom(address(this.quoteAsset), msg.sender, address(this), remainingQuote)

    • What is controllable? N/A

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • this._swapRemainingQuote(token, recipient, remainingQuote) -> SafeTransferLib.safeApprove(address(this.quoteAsset), address(this.router), remainingQuote)

    • What is controllable? N/A

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

  • this._swapRemainingQuote(token, recipient, remainingQuote) -> this.router.swapExactTokensForTokens(remainingQuote, 1, path, recipient, block.timestamp + 300)

    • What is controllable? recipient.

    • If the return value is controllable, how is it used and how can it go wrong? Returns the output amount of LaunchToken received as a result of the swap. This amount is added to the total LaunchToken received by the recipient.

    • What happens if it reverts, reenters or does other unusual control flow? this function can revert if amountOutMin is less than the resulting output amount, but since it is called with amountOutMin set to 1, it is unlikely to revert.

  • this._swapRemainingQuote(token, recipient, remainingQuote) -> SafeTransferLib.safeTransfer(address(this.quoteAsset), msg.sender, remainingQuote)

    • What is controllable? N/A.

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

    • What happens if it reverts, reenters or does other unusual control flow? There are no problems here.

Zellic © 2025Back to top ↑