-
Notifications
You must be signed in to change notification settings - Fork 4
Update docs to make auction lengths chain specific #221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f91ffd
f57fbef
8e1521d
17c2897
580b38d
6c35530
821e218
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,27 +42,85 @@ understand and comply with in order to successfully participate in auctions. | |
|
|
||
| | Name | Value | Description | | ||
| | ------------------------------------- | ----- | -------------------------------------------------------------------------------------------------- | | ||
| | AUCTION_LENGTH_SECONDS | 30 | How long an auction lasts. | | ||
| | OEV_AUCTIONS_MAJOR_VERSION | 1 | Increased when we release any breaking change relevant to OEV auctions. | | ||
| | COLLATERAL_REQUIREMENT_BUFFER_PERCENT | 5 | The additional percentage of the bidder's collateral to mitigate against price changes. | | ||
| | BID_PHASE_LENGTH_SECONDS | 25 | The length of the bid phase during which searchers can place their bids. | | ||
| | AWARD_PHASE_LENGTH_SECONDS | 5 | The length of the award phase during which Auctioneer attempts to resolve the auction. | | ||
| | REPORT_FULFILLMENT_PERIOD_SECONDS | 86400 | The fulfillment period, during which the auction winner is able to report payment for the OEV bid. | | ||
| | MINIMUM_BID_EXPIRING_SECONDS | 15 | The minimum expiring time for a bid to be considered eligible for award. | | ||
| | PLACED_BIDS_BLOCK_RANGE | 300 | The number of blocks queried for placed bids during award phase. | | ||
|
|
||
| ### Auction length | ||
|
|
||
| The auction length is chain dependent. | ||
|
|
||
| <!-- BEGIN:chain-auction-length-table --> | ||
|
|
||
| | Chain | Length (seconds) | | ||
| | --------------- | ---------------- | | ||
| | ApeChain | 30 | | ||
| | Arbitrum One | 15 | | ||
| | Avalanche | 30 | | ||
| | Base | 30 | | ||
| | Berachain | 30 | | ||
| | Bitlayer | 30 | | ||
| | Blast | 30 | | ||
| | BNB Smart Chain | 30 | | ||
| | BOB | 30 | | ||
| | Core | 30 | | ||
| | Ethereum | 30 | | ||
| | Fraxtal | 30 | | ||
| | Gnosis Chain | 30 | | ||
| | Ink | 30 | | ||
| | Katana | 30 | | ||
| | Kava | 30 | | ||
| | Linea | 30 | | ||
| | Lumia | 30 | | ||
| | Manta | 30 | | ||
| | Mantle | 30 | | ||
| | Merlin | 30 | | ||
| | Metal L2 | 30 | | ||
| | Metis | 30 | | ||
| | Mode | 30 | | ||
| | Moonbeam | 30 | | ||
| | Moonriver | 30 | | ||
| | opBNB | 30 | | ||
| | Optimism | 30 | | ||
| | Polygon | 30 | | ||
| | Polygon zkEVM | 30 | | ||
| | Ronin | 30 | | ||
| | Scroll | 30 | | ||
| | Sei | 30 | | ||
| | Soneium | 30 | | ||
| | Sonic | 30 | | ||
| | Taiko | 30 | | ||
| | Unichain | 30 | | ||
| | World Chain | 30 | | ||
| | X Layer | 30 | | ||
| | Zircuit | 30 | | ||
|
|
||
| <!-- END:chain-auction-length-table --> | ||
|
|
||
| ### Bid phase length | ||
|
|
||
| The length of the bid phase during which searchers can place their bids. The bid phase length is auction length dependent. | ||
|
|
||
| ```js | ||
| const bidPhaseLength = auctionLength - AWARD_PHASE_LENGTH_SECONDS; | ||
| ``` | ||
|
|
||
| ### Auction offset | ||
|
|
||
| Auctions repeat indefinitely and take a fixed amount of time. The first auction | ||
| starts at the UNIX timestamp 0 (midnight UTC on 1st of January 1970) plus an | ||
| offset based on the dApp ID. | ||
|
|
||
| ```solidity | ||
| uint256(keccak256(abi.encodePacked(uint256(dAppId)))) % AUCTION_LENGTH_SECONDS; | ||
| uint256(keccak256(abi.encodePacked(uint256(dappId)))) % auctionLength; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Yeah, the casing was incorrect. |
||
| ``` | ||
|
|
||
| ::: info ℹ️ Example | ||
|
|
||
| Say there is a dApp with ID `13` and `AUCTION_LENGTH_SECONDS=30` | ||
| Say there is a dApp with ID `13` and `auctionLength=30` | ||
|
|
||
| - When we encode and hash the dApp ID, we get | ||
| `0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5`. | ||
|
|
@@ -97,9 +155,7 @@ Let's break down the components of the bid topic: | |
| protocol specs, is denoted by this major version being incremented. Refer to | ||
| the current value of `OEV_AUCTIONS_MAJOR_VERSION` constant. | ||
| 2. `dappId` - The dApp ID for which the auction is being held. | ||
| 3. `auctionLength` - The length of the auction. This parameter must be set to | ||
| `AUCTION_LENGTH_SECONDS`. It is one of the most important parameters, so | ||
| we're explicitly including it in the bid topic to highlight its importance. | ||
| 3. `auctionLength` - The length of the auction in seconds. It is one of the most important parameters, so we're explicitly including it in the bid topic to highlight its importance. | ||
| 4. `signedDataTimestampCutoff` - The cutoff timestamp of the signed data. The auction winner is permitted to only use signed data with timestamps smaller than or equal to this. It is equal to the end of the bid phase of the | ||
| auction. | ||
|
|
||
|
|
@@ -108,10 +164,10 @@ Let's break down the components of the bid topic: | |
| Auctions repeat continuously and indefinitely. To calculate the | ||
| `signedDataTimestampCutoff` that is to be specified in the bid topic, one needs | ||
| to calculate the `startTimestamp` of the next auction. This depends on the auction | ||
| offset, `BID_PHASE_LENGTH_SECONDS` and the current time. | ||
| offset, `bidPhaseLength` and the current time. | ||
|
|
||
| For example, dApp with ID `13` has an auction offset of `17`. With | ||
| `AUCTION_LENGTH_SECONDS=30` and `BID_PHASE_LENGTH_SECONDS=25` this gives the | ||
| `auctionLength=30` and `bidPhaseLength=25` this gives the | ||
| following sequence of auctions: | ||
|
|
||
| | `startTimestamp` | `signedDataTimestampCutoff` | End of award phase | | ||
|
|
@@ -205,7 +261,7 @@ transaction. | |
| Each auction is split into two phases: | ||
|
|
||
| 1. Bid phase - During this phase, searchers are free to submit their bids. | ||
| This phase takes `BID_PHASE_LENGTH_SECONDS`. | ||
| This phase takes `bidPhaseLength`. | ||
| 2. Award phase - During this phase, Auctioneer determines and awards the winner. | ||
| Bids placed during this period are ignored. | ||
|
|
||
|
|
@@ -221,6 +277,7 @@ as soon as possible. The following happens under the hood: | |
| selected | ||
| 6. Prepare and submit the award for the auction winner on the OEV Network | ||
|
|
||
| Auctioneer may take longer than the allotted `AWARD_PHASE_LENGTH_SECONDS` to award the winner. | ||
| Under rare circumstances, when Auctioneer is unable to fetch the block or the | ||
| logs from the OEV Network, the auction will be aborted and no winner is chosen. | ||
| Similarly, if the auction award transaction fails, there will be no retry, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import path from 'node:path'; | ||
| import fs from 'node:fs'; | ||
| import { test, expect } from 'vitest'; | ||
| import { CHAINS } from '@api3/contracts'; | ||
| import { getChains } from '@api3/dapi-management'; | ||
|
|
||
| const supportedMainnets = getChains() | ||
| .filter((chain) => chain.stage === 'active') | ||
| .map((chain) => CHAINS.find((api3Chain) => api3Chain.id === chain.id)!) | ||
| .filter((chain) => !chain.testnet) | ||
| .filter((chain) => chain.alias !== 'oev-network') | ||
| .map((chain) => chain.name) | ||
| .sort((a, b) => a.localeCompare(b)); | ||
|
|
||
| test('the auction length section lists all the supported chains', () => { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Yeah, I imagined something like this |
||
| const docPath = path.join( | ||
| process.cwd(), | ||
| 'docs', | ||
| 'oev-searchers', | ||
| 'in-depth', | ||
| 'oev-auctioneer.md' | ||
| ); | ||
| const content = fs.readFileSync(docPath, 'utf8'); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you make sure this errors out nicely in case the path doesn't exist (when we move the files arouind) |
||
|
|
||
| const chains = extractContentBetweenMarkers(content, 'chain-auction-length-table') | ||
| .split('\n') | ||
| .filter(Boolean) // Get rid of blank lines | ||
| .slice(2) // Get rid of the header rows | ||
| .map((row) => row.split('|')[1].trim()); | ||
|
|
||
| expect(chains).toStrictEqual(supportedMainnets); | ||
| }); | ||
|
|
||
| function extractContentBetweenMarkers(content: string, key: string) { | ||
| const beginMarker = `<!-- BEGIN:${key} -->`; | ||
| const endMarker = `<!-- END:${key} -->`; | ||
| const beginIndex = content.indexOf(beginMarker); | ||
| const endIndex = content.indexOf(endMarker); | ||
| if (beginIndex === -1 || endIndex === -1) { | ||
| throw new Error(`Could not find markers "${beginMarker}" and "${endMarker}"`); | ||
| } | ||
| return content.slice(beginIndex + beginMarker.length, endIndex).trim(); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.