Skip to main content

Create Auction

This guide will provide steps for creating an auction in the Axis system through direct integration with the contracts. It will break the components into different steps, to ease understanding. This particular guide will use the EncryptedMarginalPrice auction module.

Setup

First, we define a variable for the AuctionHouse. The address used here is a testnet address. However, the current addresses for both testnet and production deployments can be obtained from the Contract Addresses page.

// Define the deployed AuctionHouse
IAuctionHouse auctionHouse = IAuctionHouse(_auctionHouse);

Note that the address used for the AuctionHouse corresponds to the auction type used. An Atomic auction type would use the AtomicAuctionHouse, and a Batch auction type would use the BatchAuctionHouse. However, for the purposes of auction creation, the IAuctionHouse interface can be used.

The next step is to set up the tokens that will be used in the auction. In this example, mock ERC20 contracts are deployed to make minting simple.

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

Inputs

In this section, we prepare the inputs to the auction create function.

Routing Parameters

The routing parameters are used by the AuctionHouse contract to define the configuration related to the auction format, tokens, curator, callbacks and derivative. These parameters are kept separate from the auction parameters, which are used by the auction module defined in the auctionType property.

// Define the auction routing parameters
IAuctionHouse.RoutingParams memory routingParams = IAuctionHouse.RoutingParams({
auctionType: toKeycode("EMPA"),
baseToken: address(baseToken),
quoteToken: address(quoteToken),
curator: address(0), // Optional
referrerFee: 0, // Optional
callbacks: ICallback(address(0)), // Optional
callbackData: abi.encode(""), // Optional
derivativeType: toKeycode(""), // Optional
derivativeParams: abi.encode(""), // Optional
wrapDerivative: false
});

The code above configures an auction with the following:

  • Auction format is EncryptedMarginalPrice (using the Keycode of the module, EMPA)
  • Uses the base and quote tokens that were deployed earlier in this guide
  • No curator is defined
  • No callback contract is defined
  • No derivative is defined

Auction Parameters

Auction parameters are used by the respective auction module to configure the auction lot.

There are 4 standard configuration parameters across all auction modules:

// Define the auction parameters
uint48 start = uint48(block.timestamp + 1 days);
uint48 duration = uint48(3 days);
bool capacityInQuote = false;
uint256 capacity = 10e18;

This would result in an auction with the following features:

  • Commencing one day after the block in which the auction is created
  • The auction will last for 3 days
  • Has a capacity of 10 base tokens

Auction Module Parameters

Each auction module will likely have implementation-specific parameters that are used. The EncryptedMarginalPrice auction module takes parameters that are defined in the struct IEncryptedMarginalPrice.AuctionDataParams.

One of these parameters is the public key for the auction, which is used to encrypt bids. In this example script, the user sets the AUCTION_PRIVATE_KEY environment variable to be an integer value representing the auction's private key. The script reads that environment variable and generates a public key using the ECIES library.

note

The auction private key should only be handled in an off-chain script, otherwise third-parties would be able to decrypt any submitted bids.

// Calculate the auction public key
Point memory auctionPublicKey = ECIES.calcPubKey(
Point(1, 2),
vm.envUint("AUCTION_PRIVATE_KEY")
);

Next, we assemble the parameters for the EncryptedMarginalPrice auction module:

// Define the auction module parameters
IEncryptedMarginalPrice.AuctionDataParams memory empParams = IEncryptedMarginalPrice
.AuctionDataParams({
minPrice: 1e18, // 1 quote token per base token
minFillPercent: 10_000, // 10%
minBidSize: 1e18, // 1 quote token
publicKey: auctionPublicKey
});

This defines an EncryptedMarginalPrice auction with the following features:

  • Bids must have a minimum price of 1 quote token per base token in order to be considered for settlement
  • 10% of the capacity (defined in the Auction Parameters section) must be filled in order for the auction to settle
  • Each bid must have an amount in of at least 1 quote token in order to be accepted

Combining Auction Parameters

We then combine the standard auction parameters with the module-specific parameters:

IAuction.AuctionParams memory auctionParams = IAuction.AuctionParams({
start: start,
duration: duration,
capacityInQuote: capacityInQuote,
capacity: capacity,
implParams: abi.encode(empParams)
});

The implParams property of the struct encodes the module-specific parameters. This enables auction modules to specify different configuration options without being bound to a specific structure.

Token Funding

As the configured auction is a batch auction, the AuctionHouse will pre-fund the auction at the time of creation. For this reason, we need to ensure that the seller has the required balance of base tokens (the capacity). The seller also needs to approve spending of the tokens by the AuctionHouse.

// Mint base tokens to the seller
baseToken.mint(_SELLER, capacity);

// The AuctionHouse will pull base tokens from the seller upon auction creation,
// so approve the auction capacity
vm.prank(_SELLER);
baseToken.approve(address(auctionHouse), capacity);

Contract Call

The Axis frontend links additional auction information (such as a title, icons and description) to the auction using an IPFS hash, which is passed into the AuctionHouse and emitted in an event. It is not required for this example, so we define it as an empty string.

// Define the IPFS hash for additional information
string memory ipfsHash = "";

Lastly, we create the auction. The caller of the contract is considered the seller, so we use vm.prank to assume the role of the seller in the example script.

// Create the auction
vm.prank(_SELLER);
uint96 lotId = auctionHouse.auction(routingParams, auctionParams, ipfsHash);
console2.log("Created auction with lot ID:", lotId);

Source Code

The source code for the guide is located in the create-auction.s.sol file.