Skip to main content

Purchase

This guide will provide steps for conducting a purchase on an atomic auction through direct integration with the contracts. This guide is designed to work with the FixedPriceSale auction format.

Setup

First, define the AtomicAuctionHouse that will be used. This should correspond to the same AtomicAuctionHouse in which the auction lot was created.

// Define the deployed AtomicAuctionHouse
IAtomicAuctionHouse auctionHouse = IAtomicAuctionHouse(_atomicAuctionHouse);

The quote token is also required:

// Define the tokens used in the auction
MockERC20 quoteToken = _getQuoteToken();

Inputs

We obtain from the LOT_ID environment variable the lot ID that identifies each auction lot. The lot ID is a uint96 number, so should be checked before being downcast.

// Obtain the lot from the environment variable
uint256 lotIdRaw = vm.envUint("LOT_ID");
if (lotIdRaw > type(uint96).max) {
revert("LOT_ID must be less than uint96 max");
}
uint96 lotId = uint96(lotIdRaw);

The lot ID is returned from the auction creation function. See the Create Auction Guide for more details.

Then we define the amount in and minimum amount out as variables:

// Prepare inputs
uint256 amount = 1e18;
uint256 minAmountOut = 2e18;
address recipient = address(0x10);

Next, we define the auction module-specific data. In the case of FixedPriceSale, it expects the minimum amount out to be passed in an abi-encoded form:

// Prepare parameters for the FixedPriceSale module
IFixedPriceSale.PurchaseParams memory fpsPurchaseParams =
IFixedPriceSale.PurchaseParams({minAmountOut: minAmountOut});

Permit2 approval can be optionally granted. For simplicity, this example will not use Permit2 approval. Instead, the buyer must approve the spending of tokens by the AtomicAuctionHouse.

// Prepare Permit2 approval (unused)
bytes memory permit2Data = abi.encode("");

Data can be passed to the onPurchase callback, which is unused in this example.

// Define callback data (unused)
bytes memory callbackData = abi.encode("");

The purchase parameters are then assembled.

// Prepare parameters
IAtomicAuctionHouse.PurchaseParams memory purchaseParams = IAtomicAuctionHouse
.PurchaseParams({
recipient: recipient, // Who should receive the purchased tokens
referrer: _REFERRER, // The referrer (e.g. frontend) for the buyer
lotId: lotId,
amount: amount, // The amount of quote tokens in
minAmountOut: minAmountOut, // The minimum amount of base tokens out, otherwise it will revert
auctionData: abi.encode(fpsPurchaseParams), // Auction module-specific data
permit2Data: permit2Data // Permit 2 approval (optional)
});

This would result in a purchase with the following characteristics:

  • 1 quote token would be provided by the buyer
  • The payout (in base tokens) would be a minimum of 2
  • The recipient would receive the payout instead of the _BUYER

Permit2

A purchase can optionally be performed using Permit2 approvals.

TODO

Token Funding

The AtomicAuctionHouse will attempt to transfer amount quantity of quote tokens from the buyer to itself. For this reason, we need to ensure that the buyer has the required balance.

// Mint the required quote tokens
quoteToken.mint(_BUYER, amount);

If Permit2 approval has not been given, the AtomicAuctionHouse needs to have spending approved:

// Approve spending of quote tokens
if (usePermit2_ == false) {
vm.prank(_BUYER);
quoteToken.approve(_atomicAuctionHouse, amount);
}

Contract Call

Lastly, we call the function to purchase. This must be performed as the buyer who possesses the quote tokens.

// Conduct the purchase
// The buyer must have enough quote tokens to complete the purchase
vm.prank(_BUYER);
uint256 payout = auctionHouse.purchase(purchaseParams, callbackData);
console2.log("Purchase completed. Payout:", payout);

It is worthwhile noting that the purchase may fail for the following reasons:

  • If the caller does not have amount quantity of quote tokens
  • If the caller has not approved the AtomicAuctionHouse to spend amount quantity of quote tokens
    • This can be provided through the traditional ERC20.approve() function
    • Alternatively, Permit2 Approval can be provided
  • The payout was less than minAmountOut

Source Code

The source code for the guide is located in the purchase.s.sol file.