- Model an auction with three structs, two mappings and counters.
- Use a modifier with an argument to validate bid values.
- Receive Ether in a payable function and forward it with
transfer.
Synopsis
An e-auction lets bidders compete for an item online, but participants usually have to trust the auction house to record bids honestly and to declare the true highest bidder. In this project the bidding rules run in a smart contract, so every registration and bid is recorded on the blockchain and the winner is determined by public code.
The deploying account is the Auction Manager, who puts an item up for auction with a starting value. Other accounts register as bidders and place open, increasing bids – each bid must be higher than the current highest. When the manager declares the result, the last (highest) bid wins, and the winner pays the bid amount in Ether through the contract to the manager.
Contract Architecture
| Part | Details |
|---|---|
| BlockMaster.sol | Structs ItemMaster { itemName, initBidValue, auctionResult }, BiddersMaster { bidderName, bidderAddress }, AuctionRegister { userAddress, bidValue } |
| AuctionContract.sol | Contract AuctionContract; imports contracts/BlockMaster.sol |
| state | address payable auctionManager, ItemMaster public auctionItem, maxBidValue, counters regNo and chainNo, AuctionRegister public winner |
| mappings | auctionBidderRegister (registration no. → bidder) and auctionChain (bid no. → bid) |
| modifiers | checkAuctionManager, checkUserIsNotAuctionManager, checkAuctionBidderRegister (not yet registered), checkAuctionBidderExistence (registered), checkBidValue(uint) (bid > current max), checkItemBiddingStatus (auction open), checkWinnerAddress, checkTransactionAmount |
| functions | setAuctionItem(name, value) → BidderRegisterMaster(name) → MyBidding(value) → declareAuctionResult() → transferBidAmount() (payable) |
How It Works
winnerBid values are entered in whole ETH. checkTransactionAmount converts them to wei (bidValue * 10**18) and requires msg.value to match exactly.
Key Requirements (Concepts Used)
- Structs imported from a separate file (Chapters 2, 13).
- Mappings with counters used as keys (Chapter 12).
- Modifiers, including a modifier with an argument (Chapter 22).
- Payable function and transfer to an
address payable(Chapters 3, 24). - Private helper functions such as
gotoNextBidder()(Chapter 15).
How to Run in Remix
- Create
contracts/BlockMaster.solandcontracts/AuctionContract.solfrom the resource files; compile and deploy AuctionContract from the first account (manager). - Manager: call
setAuctionItem("Painting", 1). - From two or three other accounts call
BidderRegisterMaster, thenMyBiddingwith rising values (e.g. 2, 3, 5). - Manager: call
declareAuctionResult()and readwinner. - Winner: set the VALUE field to the bid in Ether (e.g. 5 ether) and call
transferBidAmount(); the manager’s balance increases.
Limitations and Extension Exercises
| Observation in the teaching version | Improvement to try |
|---|---|
| Bids are only numbers; the winner may never pay. | Require bidders to send Ether with each bid (escrow) and refund out-bid users. |
| Bids are public, so this is an open (English-style) auction, not a sealed-bid auction. | Study commit–reveal for sealed bids. |
| No end time; the manager decides when to close. | Add an endTime set at item creation. |
Declaring a result with no bids underflows chainNo - 1 and reverts. | Require at least one bid with a clear message. |
| Registration checks loop over all bidders. | Use mapping(address => bool) registered. |
Exercise solution (escrow auction with refunds)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract EscrowAuction {
address payable public immutable seller = payable(msg.sender);
uint public immutable endTime;
address public highestBidder;
uint public highestBid;
bool public ended;
mapping(address => uint) public refunds; // out-bid amounts to withdraw
constructor(uint durationSeconds) {
endTime = block.timestamp + durationSeconds;
}
function bid() external payable {
require(block.timestamp < endTime, "Auction over");
require(msg.value > highestBid, "Bid too low");
if (highestBidder != address(0)) {
refunds[highestBidder] += highestBid; // previous leader can withdraw
}
highestBidder = msg.sender;
highestBid = msg.value;
}
function withdrawRefund() external {
uint amount = refunds[msg.sender];
require(amount > 0, "Nothing to withdraw");
refunds[msg.sender] = 0; // effects before interaction
(bool ok, ) = payable(msg.sender).call{value: amount}("");
require(ok, "Refund failed");
}
function endAuction() external {
require(block.timestamp >= endTime, "Not yet ended");
require(!ended, "Already ended");
ended = true;
(bool ok, ) = seller.call{value: highestBid}("");
require(ok, "Payment failed");
}
}
Key Takeaways
- Modifiers (including one with an argument) enforce who may bid and that bids keep increasing.
- Payable functions receive Ether; amounts must be converted between ETH and wei carefully.
- Real auctions need escrow, refunds (pull pattern) and a fixed end time.
Video : Project 3 : Smart Contract for Bidding / e-Auction System
Resource Files
Question / Answer (15 questions)
auctionManager.transfer(msg.value), which requires an address payable.checkBidValue(uint bidderValue) requires the new bid to be greater than maxBidValue, otherwise the bid is rejected.MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.
- Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
- Solidity Team. (n.d.). Units and Globally Available Variables. Solidity Documentation. https://docs.soliditylang.org/en/latest/units-and-global-variables.html
- Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
- ethereum.org. (n.d.). Smart contract security. Ethereum Developer Documentation. https://ethereum.org/en/developers/docs/smart-contracts/security/
- Remix Project. (n.d.). Remix IDE Documentation. https://remix-ide.readthedocs.io/en/latest/
- Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.