Assessment reports>GTE>Threat Model>buy

Function: buy(address account, address token, address recipient, uint256 amountOutBase, uint256 maxAmountInQuote)

This function allows any caller or trusted operator to buy the specified amountOutBase amount of the LaunchToken. The maxAmountInQuote specifies the maximum amount of quote tokens that can be spent.

Inputs

  • account

    • Control: Full control.

    • Constraints: The caller should be the specified account itself or an approved operator by this account.

    • Impact: The account address on whose behalf the purchase is made.

  • token

    • Control: Full control.

    • Constraints: _launches contains data related to this token.

    • Impact: The address of the trusted LaunchToken, created using the launch function.

  • recipient

    • Control: Full control.

    • Constraints: Cannot be equal to the address of the Uniswap pool related to this LaunchToken and quote token.

    • Impact: The recipient of the purchased tokens.

  • amountOutBase

    • Control: Full control.

    • Constraints: The total amount of LaunchToken tokens bought cannot exceed the BONDING_SUPPLY limit.

    • Impact: Amount of the LaunchToken to be bought.

  • maxAmountInQuote

    • Control: Full control.

    • Constraints: The resulting amountInQuoteActual should be less than or equal to the maxAmountInQuote.

    • Impact: The maximum quote-tokens amount that can be spent.

Branches and code coverage

Intended branches

  • amountOutBaseActual is less than BONDING_SUPPLY.

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

  • The remaining tokens are successfully swapped using the Uniswap pool.

  • If the swap using the Uniswap pool fails, the remaining tokens are transferred to the caller.

Negative behavior

  • The token status is not active, because it does not exist.

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

  • The maxAmountInQuote is less than amountInQuoteActual.

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.

  • bondingCurve.buy(token, amountOutBaseActual)

    • What is controllable? token and amountOutBaseActual.

    • 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; otherwise, the resulting amount can be more expensive than expected but not more than maxAmountInQuote.

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

  • SafeTransferLib.safeTransfer(token, recipient, amountOutBaseActual)

    • What is controllable? recipient and amountOutBaseActual.

    • 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(data.quote), 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(uniV2Router), 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(data.quote), address(uniV2Router), 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.uniV2Router.addLiquidity(token, address(this.quote), tokensToLock, data.quoteBoughtByCurve, tokensToLock, data.quoteBoughtByCurve, 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. But since before that the skim function has been called, this is not the case.

  • this._swapRemaining(d) -> SafeTransferLib.safeTransferFrom(address(data.quote), msg.sender, address(this), data.quoteAmount)

    • 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._swapRemaining(d) -> SafeTransferLib.safeApprove(address(this.quote), address(this.uniV2Router), data.quoteAmount)

    • 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._swapRemaining(d) -> this.uniV2Router.swapTokensForExactTokens(data.baseAmount, data.quoteAmount, path, data.recipient, block.timestamp + 1)

    • What is controllable? data.recipient.

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

    • What happens if it reverts, reenters or does other unusual control flow? This function can revert if amountInMax is less than the resulting input amount.

  • this._swapRemaining(d) -> SafeTransferLib.safeApprove(address(data.quote), address(uniV2Router), 0)

    • 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. Reset the current approve to 0.

  • this._swapRemaining(d) -> SafeTransferLib.safeTransfer(address(data.quote), msg.sender, data.quoteAmount)

    • 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 ↑