This guide explains how to participate in auctions on pod. In these auctions bidders submit bids within a duration when the auction is active, and then anyone can query for the set of valid bids.
An auction contract is deployed that accepts bids only during a certain time duration. Bidders submit their bids, and then anyone can query for the set of accepted bids.
Prerequisites
Before participating in auctions, ensure you have:
Required tools
A funded wallet on pod devnet
Rust Pod SDK installed. How to build the pod provider can be seen in the section
Auction Mechanism
The Pod Auction is an optimistic, single-shot, first-price auction. It is optimistic because it assumes participants behave honestly by default, and only resorts to dispute resolution when misbehavior occurs.
Protocol Overview
• Single-shot: Participants submit bids once without revisions.
• First-price: Highest bid wins the auction.
• Decentralized: No trusted third-party auctioneer. Pod network replicas act as validators.
Auction Phases
1. Bidding Phase:
Bidders submit bids to Pod replicas within a specific timeframe (auction start to auction finish).
Valid bids are signed by pod validators if submitted within this timeframe.
2. Optimistic Outcome:
• Once the bidding phase concludes (after the deadline is reached), bidders read Pod to locally identify the winner.
• The bidder observing themselves as the winner optimistically announces this outcome with sufficient signatures (2f+1) to an on-chain consumer.
3. Optimistic Dispute Resolution (only if needed):
• If a bidder wrongly claims victory, other bidders can dispute the outcome by submitting evidence of a higher bid.
• The smart contract consumer verifies signatures and settles disputes transparently.
4. No-Show Handling:
• If no bidder announces victory, bidders submit their local winning bids, and the consumer selects the highest valid bid.
Solidity
The auction contract implements a time-based bidding system where participants can submit bids during an active auction period. Here's the complete contract code:
contract Auction {
// Event emitted when a bid is submitted
event BidSubmitted(
uint256 indexed auction_id,
address indexed bidder,
uint256 indexed deadline,
uint256 value
);
/**
* @notice Submit a bid for an auction
* @param auction_id The ID of the auction
* @param deadline The deadline for the auction
* @param value The bid value
* @param data Additional data for the bid
*/
function submitBid(
uint256 auction_id,
uint256 deadline,
uint256 value,
bytes calldata data
) public {
// Check that the auction deadline hasn't passed
require(block.timestamp <= deadline, "Auction deadline passed");
// Emit the bid submission event
emit BidSubmitted(auction_id, msg.sender, deadline, value);
}
}
The contract features:
Checking that the auction was sent before the deadline.
Events for tracking bid submissions
Auction Contract on pod
The auction contract on pod is pre-deployed and ready to use. The implementation on the SDK side using the sol! macro looks as follows:
The contract is deployed to the address 0x217F5658c6ecC27D439922263AD9Bb8e992e0373 on pod network.
Participating in the auction
use eyre::Result;
use pod_sdk::{PodProviderBuilder, PrivateKeySigner};
use alloy::transports::http::Http;
use alloy_primitives::{Address, U256, H256};
use alloy_network::EthereumWallet;
use alloy_signer::k256::ecdsa::SigningKey;
use pod_core::contracts::auction::Auction;
use alloy_rpc_types_eth::{BlockNumber, Filter, ValueOrArray};
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<()> {
let rpc_url = "https://rpc.pod.network";
let private_key = "your-private-key-hex";
let auction_contract: Address = "auction-contract-address".parse()?;
let signer = PrivateKeySigner::from_signing_key(SigningKey::from_slice(&hex::decode(private_key)?)?);
let wallet = EthereumWallet::new(signer);
let provider = PodProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_http(Http::new(rpc_url)?)
.await?;
let auction = Auction::new(auction_contract, &provider);
let auction_id = U256::from(42);
let deadline = U256::from(9999999999u64);
let value = U256::from(100000);
let data = b"Hello from Pod!".to_vec();
let pending_tx = auction.submit_bid(auction_id, deadline, value, data).send().await?;
println!("Submitted bid, tx hash: {:?}", pending_tx.hash());
let receipt = pending_tx.get_receipt().await?;
println!("Bid confirmed, receipt: {:?}", receipt);
provider.wait_past_perfect_time(deadline.as_u64()).await?;
println!("Auction deadline passed. Bid is now final.");
let bid_submitted_sig = Auction::events::BidSubmitted::SIGNATURE_HASH;
let auction_id_topic = H256::from_uint(&auction_id);
let filter = Filter::new()
.address(auction_contract)
.topic0(ValueOrArray::Value(bid_submitted_sig))
.topic1(ValueOrArray::Value(auction_id_topic))
.from_block(BlockNumber::Earliest)
.to_block(BlockNumber::Latest);
let subscription = provider.subscribe_logs_pod(&filter).await?;
let mut log_stream = subscription.into_stream();
while let Some(log) = log_stream.next().await {
println!("Received log: {:?}", log);
let decoded = Auction::events::BidSubmitted::decode_log(&log)?;
println!("Decoded bid: {:?}", decoded);
}
Ok(())
}
Further reading
Read about about the .
Learn more about pod's and when working on timestamps with pod, pay attention to the .