owned this note
owned this note
Published
Linked with GitHub
# Create2-Based Private Vickrey Auctions
Tl;dr. Each bidder sends to a different account that seems like an EoA from the perspective of the blockchain, but is actually a create2-generated address that is revealed at the end of the auction. When the reveal phase begins, people reveal their create2 salt and bid, and the auction contract can run the second price auction securely.
## Links
Live Demo on Goerli: https://vickrey.xyz / https://vcg.app [reveal has a minor bug rn, will be fixed end of week]
Slides: [Explanation of construction, best viewed with video instead](https://docs.google.com/presentation/d/1k9VUYWwi4LGSbRzpbTT5iulnp2qJmBCSTvoBs101yJs/edit#slide=id.g164037e31bc_0_46)
Video: [Presentation at EthBogota Finalist Stage](https://www.youtube.com/watch?v=WZbQO0esKzo&t=4215s)
Code: [Contracts](https://github.com/Philogy/create2-vickrey-contracts/), [Frontend](https://github.com/outdoteth/vickrey-auction-frontend)
Twitters: [@yush_g](https://twitter.com/yush_g), [@real_philogy](https://twitter.com/real_philogy), [@outdoteth](https://twitter.com/outdoteth), [@0xngmi](https://twitter.com/0xngmi)
## Technical Spec
### Create2 Smart Contract
- Create2 salt should be: `keccak256(bidder account address, actual bid, sub salt)`
- Note that the sender address is the auction contract
- This contract has one constructor, that checks if msg.sender is the auction contract, and if it is, it returns all the existing eth at the current balance to that account. Ideally it deploys no code.
### Auction Smart Contract
- Contains a callable function that stores the block of reveal end
- If block is more than 256 blocks in the past, store the oldest available block hash.
- Callers prove that their bid was created before reveal via merkle patricia trie against block's state root
- The constructor takes in the bytecode of the contract as an argument, the start block number, the bid-end block number (reveal will start the next block), and the last block number at the end of the reveal period, along with an NFT ID, and transfers the selected NFT out of the auctioneers wallet.
- Contains a function called `revealBid(bidderAddress: address, bidAmount: bytes256, subSalt: bytes256, ...<patricia trie proof args>)`, that calculates `salt = keccak256(bidderAddress, bidAmount, subSalt)`. It deploys the contract with the bytecode argument from the constructor, collects the eth, and sets a mapping from the address to the bid.
- It compares the bid to the currently stored top two bids, and progressively updates the top 2 bidders.
### Frontend
NFT Auction creation process:
* Approve the factory contract to transfer the NFT, then transfer the NFT to the factory contract. This deploys a new auction with default start and end times that can be overwritten if desired.
* In the future, they can just call one generalized auction contract that handles all of the auctions and takes in the auction id as an argument to the salt hash.
Bidding process:
* Frontend should generate addresses using create2 for where the bidder should send their eth, and request Metamask to send eth there
Reveal process:
* A button on the frontend turns available for anyone to call the reveal function, which stores the blockhash closest to the reveal block (ideally within 256 blocks, if more than 256 blocks then the oldest blockhash is added). This formally ends the bid period.
* Ideally, it pays back the caller the gas fee used, to avoid a tragedy of the commons. It can also be stored temporarily in a mapping, which will refund the reveal caller their gas once the winning bid is revealed.
* After bid period ends, the frontend checks if the bid period has formally ended (someone has called the reveal() function). If someone has, it enables functoinality for all bidders to send their salt to the auction contract and reveal the bid.
Auction finish process:
* At the end of the reveal period, anyone (usually the bid winner or the auction creator) will finish the auction. This will first check that we've passed the minimal number of blocks since reveal period start time. This will then will trigger the NFT to be sent to the winner, the price to be paid of the second place, and unlock the other bids to be returnable.
* Withdraw allows a loser address to withdraw their bid from the auction contract after reveal phase has ended.
Misc.
* Table to view all current auctions
* Auction metadata (how much time is left, creator, creation date etc.)
### Kudos
Credit to [@personae_labs](https://twitter.com/personae_labs), [@13yearoldvc](https://twitter.com/13yearoldvc), and [@notfellows](https://twitter.com/notfellows) for supporting and connecting us!