Entrypoints
Each form below maps directly to a contract entrypoint. Filling it in and clicking Call constructs a typed-argv DSOL call. Your wallet shows an approval modal before broadcasting; nothing fires without your explicit click.
createDutch @direct
createEnglish @direct
acceptCommit @direct
acceptReveal @direct
submitBid @direct
settleEnglish @direct
Public state
loading…
Contract source Verified
// Auction — Phase D of silent-iron-keystone v4.
//
// Supports both Dutch (price decay; first-to-accept wins) and English
// (sealed-bid; highest revealed wins) modes. Mode is stored at
// auction creation; mode-specific entrypoints separate the flows.
//
// Privacy: bidder identity is one-time stealth (CryptoNote default).
// English auction bids are commit-reveal. Dutch auction acceptance
// uses a 3-block commit-reveal window to prevent mempool front-running
// (see plan §AUDIT F-04).
dark contract Auction {
// mode: 1=Dutch, 2=English
public mapping(bytes => uint8) auctionMode;
public mapping(bytes => bytes) auctionTokenId;
public mapping(bytes => uint64) auctionTotalSupply;
public mapping(bytes => uint64) auctionStartBlock;
public mapping(bytes => uint64) auctionEndBlock;
public mapping(bytes => uint64) auctionStartPrice; // Dutch only
public mapping(bytes => uint64) auctionEndPrice; // Dutch only
public mapping(bytes => bool) auctionSettled;
public mapping(bytes => bool) acceptedNullifiers;
public mapping(bytes => bytes) acceptedCommit; // accept_commit_id → commit blob
public mapping(bytes => uint64) acceptedCommitBlock;
@direct
entry createDutch(bytes auction_id, bytes tokenId, uint64 totalSupply, uint64 startPrice, uint64 endPrice, uint64 startBlock, uint64 endBlock) {
require(auctionMode[auction_id] == 0, "AUC_DUPLICATE");
require(totalSupply > 0, "AUC_ZERO_SUPPLY");
require(startPrice > endPrice, "AUC_DUTCH_INVERTED");
require(endBlock > startBlock, "AUC_END_BEFORE_START");
require(startBlock >= block.number, "AUC_START_IN_PAST");
auctionMode[auction_id] = 1;
auctionTokenId[auction_id] = tokenId;
auctionTotalSupply[auction_id] = totalSupply;
auctionStartBlock[auction_id] = startBlock;
auctionEndBlock[auction_id] = endBlock;
auctionStartPrice[auction_id] = startPrice;
auctionEndPrice[auction_id] = endPrice;
auctionSettled[auction_id] = false;
}
@direct
entry createEnglish(bytes auction_id, bytes tokenId, uint64 totalSupply, uint64 startBlock, uint64 endBlock) {
require(auctionMode[auction_id] == 0, "AUC_DUPLICATE");
require(totalSupply > 0, "AUC_ZERO_SUPPLY");
require(endBlock > startBlock, "AUC_END_BEFORE_START");
require(startBlock >= block.number, "AUC_START_IN_PAST");
auctionMode[auction_id] = 2;
auctionTokenId[auction_id] = tokenId;
auctionTotalSupply[auction_id] = totalSupply;
auctionStartBlock[auction_id] = startBlock;
auctionEndBlock[auction_id] = endBlock;
auctionSettled[auction_id] = false;
}
// Dutch — commit-then-reveal within 3 blocks.
@direct
entry acceptCommit(bytes auction_id, bytes accept_commit_id, bytes commitment) {
require(auctionMode[auction_id] == 1, "AUC_NOT_DUTCH");
require(auctionStartBlock[auction_id] <= block.number, "AUC_NOT_STARTED");
require(block.number < auctionEndBlock[auction_id], "AUC_ENDED");
require(!auctionSettled[auction_id], "AUC_SETTLED");
require(acceptedCommitBlock[accept_commit_id] == 0, "AUC_COMMIT_DUPLICATE");
acceptedCommit[accept_commit_id] = commitment;
acceptedCommitBlock[accept_commit_id] = block.number;
}
@direct
entry acceptReveal(bytes auction_id, bytes accept_commit_id, uint64 quantity, bytes nullifier) {
require(auctionMode[auction_id] == 1, "AUC_NOT_DUTCH");
require(acceptedCommitBlock[accept_commit_id] != 0, "AUC_COMMIT_NOT_FOUND");
require(block.number <= acceptedCommitBlock[accept_commit_id] + 3, "AUC_REVEAL_STALE");
require(!acceptedNullifiers[nullifier], "AUC_REPLAY");
require(quantity > 0, "AUC_ZERO_QUANTITY");
require(quantity <= auctionTotalSupply[auction_id], "AUC_OVER_SUPPLY");
acceptedNullifiers[nullifier] = true;
auctionTotalSupply[auction_id] = auctionTotalSupply[auction_id] - quantity;
syscall(TOKEN_TRANSFER_EMIT_V1, ctx.txHash);
}
// English — sealed bid then reveal after end block.
@direct
entry submitBid(bytes auction_id, bytes bid_id, bytes commitment) {
require(auctionMode[auction_id] == 2, "AUC_NOT_ENGLISH");
require(block.number < auctionEndBlock[auction_id], "AUC_BID_PAST_END");
require(acceptedCommit[bid_id] == "", "AUC_BID_DUPLICATE");
acceptedCommit[bid_id] = commitment;
acceptedCommitBlock[bid_id] = block.number;
}
// Operator settles English auction. Caller proves they hold the
// winning bid's opening; contract verifies nullifier freshness.
@direct
entry settleEnglish(bytes auction_id, bytes bid_id, bytes nullifier, uint64 quantity) {
require(auctionMode[auction_id] == 2, "AUC_NOT_ENGLISH");
require(block.number >= auctionEndBlock[auction_id], "AUC_BEFORE_END");
require(!auctionSettled[auction_id], "AUC_ALREADY_SETTLED");
require(!acceptedNullifiers[nullifier], "AUC_REPLAY");
require(quantity > 0, "AUC_ZERO_QUANTITY");
require(quantity <= auctionTotalSupply[auction_id], "AUC_OVER_SUPPLY");
auctionSettled[auction_id] = true;
acceptedNullifiers[nullifier] = true;
syscall(TOKEN_TRANSFER_EMIT_V1, ctx.txHash);
}
}
Download .dsol