This tutorial is meant for those with a basic knowledge of Ethereum and smart contracts, who have some knowledge of Solidity.
The purpose of building this blog is to write down the detailed operation history and my memo for learning the dApps and solidity programming.
If you are also interested and want to get hands dirty, just follow these steps below and have fun!~
Prerequisites
Smart contract overview
This contract is for selling NFT. The general idea is that users (accounts) can send their bids to the contract for winning the NFT during a bidding period. The initial ownership for this NFT is the contract owner account[0]
/ address(0)
(assume that we deploy the contract using account[0]
). The highest bidder will win the ownership of the NFT. Participants can withdraw their bids when the selling ends.
Remark: This is test version not for production use.
Overview of the contract code (EnglishAuction.sol):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;
interface IERC721 {
function transferFrom (
address from,
address to,
uint nftId
) external;
}
contract EnglishAuction {
event Start();
event Bid(address indexed sender, uint amount);
event Withdraw(address indexed bidder, uint amount);
event End(address highestBidder, uint amount);
IERC721 public immutable nft;
uint public immutable nftId;
address payable public immutable seller;
uint32 public endAt;
bool public started;
bool public ended;
address public highestBidder;
uint public highestBid;
mapping(address => uint) public bids;
constructor(address _nft, uint _nftId, uint _startingBid) {
nft = IERC721(_nft);
nftId = _nftId;
seller = payable(msg.sender);
highestBid = _startingBid;
}
function start() external {
require(msg.sender == seller, "not seller");
require(!started, "started");
started = true;
endAt = uint32(block.timestamp + 60); // 60 seconds should be long enough for the Demo and test.
nft.transferFrom(seller, address(this), nftId);
emit Start();
}
function bid() external payable {
require(started, "not started");
require(block.timestamp < endAt, "ended");
require(msg.value > highestBid, " value < highest bid");
if (highestBidder != address(0)) {
bids[highestBidder] += highestBid;
}
highestBid = msg.value;
highestBidder = msg.sender;
emit Bid(msg.sender, msg.value);
}
function withdraw() external {
uint bal = bids[msg.sender];
bids[msg.sender] = 0;
payable(msg.sender).transfer(bal);
emit Withdraw(msg.sender, bal);
}
function end() external {
require(started, "not started");
require(!ended, "ended!");
require(block.timestamp >= endAt, "not ended");
ended = true;
if (highestBidder != address(0)) {
nft.transferFrom(address(this), highestBidder, nftId);
seller.transfer(highestBid);
} else {
nft.transferFrom(address(this), seller, nftId);
}
emit End(highestBidder, highestBid);
}
}
License identifier and compiler version are defined at first.
Interfaces are identified using the “interface” keyword. It contains function signatures without the function definition implementation. It can be used in a contract to call functions in another contract.
Event can be emitted in a specific function and the log can be seen in decoded output of each function call.
State variables are those whose values are permanently stored in a contract storage. Immutable state variables cannot be modified after the contract has been constructed.
A constructor is executed upon contract creation, and where we initialize the newly created NFT address, NFT ID, seller (that is contract owneraccount[0]
) and the initial bid.
NFT ownership will be transferred from the contract owner to this contract when seller clicking "start" to executestart()
function. 60 seconds is specified as the bidding period. You can always modify it as a longer time. When the bidding process started, users can send their bids with specific value by executingbid()
.
Function end() is used to terminate the bidding process and withdraw is to withdraw bids from this contract.
Testing process
Remix is used for contract testing.
- 1 - Deploy the ERC721.sol contract. findSouceCodeHere.
Mint the NFT ownership to account[0]
by pasting the address(0), and specifying the nftId
as your lucky number:
- 2 - Deploy the EnglishAuction.sol contract
ERC721 contract address, nftId
and starting bids are needed:
- 3 - Approval for NFT ownership transmission
Contract ERC721 needs
account[0]
to approve that the contract EnglishAuction will be able to transfer the NFT ownership from the seller to the contract itself. contract address of EnglishAuction and nftId are needed:
- 4 - Start the bidding process
The seller can start the process by clicking
start
; other accounts can send bids with a specified amount of ETH:
- 5 - Check the Bidder information and ownership
Git repository
Welcome to visit the Git repo for source code, and feel free to reach me by leaving a message below or via email found in my profile.
Thank you!
hyc0812 / solidity-essentials
Solidity programming baby examples...
Solidity-Baby Steps...
The best path for earning Solidity is to approach examples.
Here are baby examples. Typing one-by-one is recommended.
References:
MyBlog explanation for using EnglishAuction and testing.
Example-1
updateBalance & getBalance
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract MyLedger {
mapping(address => uint) public balances;
function updateBalance(uint newBal) public {
balances[msg.sender] = newBal;
}
function getBalance() public view returns(uint) {
return balances[msg.sender];
}
}
Example-2
Inherited from Square
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/utils/Strings.sol";
contract Shape {
uint height;
uint width;
constructor(uint _height, uint _width) {
height = _height;
width = _width;
}
}
contract Square is Shape {
constructor(uint h, uint w) Shape(h, w) {}
function
…References
https://cryptomarketpool.com/interface-in-solidity-smart-contracts/#:~:text=An%20interface%20in%20Solidity%20behaves,order%20for%20it%20to%20operate.
CoverPage
https://www.youtube.com/watch?v=ZeFjGJpzI7E
Top comments (0)