Tutorial - play with an auction demo based on ERC721
Tags: tutorial, programming, solidity, nft
Published: 2022-06-06 14:45:57

> _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
- [Remix](https://remix.ethereum.org/) for contract testing
- Basic knowledge of [Ethereum](https://ethereum.org/en/) and [Solidity](https://docs.soliditylang.org/en/v0.8.14/)



#### 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):
```solidity
// 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](https://docs.soliditylang.org/en/v0.6.5/contracts.html#constant-and-immutable-state-variables) 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 owner `account[0]`) and the initial bid.
> NFT ownership will be transferred from the contract owner to this contract when seller clicking "start" to execute `start()` 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 executing `bid()`.
> Function end() is used to terminate the bidding process and withdraw is to withdraw bids from this contract.

### Testing process

[Remix](https://remix.ethereum.org/) is used for contract testing.

- 1 - Deploy the ERC721.sol contract. [findSouceCodeHere]
(https://github.com/hyc0812/solidity-essentials/blob/main/ERC721.sol).

Mint the NFT ownership to `account[0]` by pasting the address(0), and specifying the `nftId` as your lucky number:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l5ehlt914iynm8bo6iz4.png)

- 2 - Deploy the EnglishAuction.sol contract

ERC721 contract address, `nftId` and starting bids are needed:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbhslepvcbgvah5vcntg.png)

- 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0d4z96u9pq4ujs80i6hq.png)

- 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97481gg0fot0cpydp944.png)

- 5 - Check the Bidder information and ownership
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e1i93sumhw1lv5czpgrz.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ry0d87sa9v29l9kj97h8.png)





### 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!

{% embed https://github.com/hyc0812/solidity-essentials %}
### References
https://cryptomarketpool.com/interface-in-solidity-smart-contracts/#:~:text=An%20interface%20in%20Solidity%20behaves,order%20for%20it%20to%20operate.
[CoverPage](https://beincrypto.com/physical-nft-displays-becoming-the-new-rage-for-collectors/)
https://www.youtube.com/watch?v=ZeFjGJpzI7E