第一週作業
---
基礎:
1. 發行總量100億顆、位數18的代幣!
2. 發行總量10張的SBT。
3. 開發猜數字的合約(一個人設定,大家猜,有人猜中,就結束不讓其他人猜了)
進階:
1. 發行有盲盒機制的NFT!
2. 理解ERC721A與ERC721的差異,並實作ERC721A合約,實際比較差異!
---
## 基礎1
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Basic0106_1 is ERC20 {
constructor() ERC20("Basic One", "BO") {
_mint(msg.sender, 10 ** 10);
}
}
```
---
## ***# Refactor***
```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract Basic0106_1 is ERC20 {
uint8 public decimal;
uint256 public maxSupply;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimal,
uint256 _maxSupply
) ERC20(_name, _symbol){
decimal = _decimal;
maxSupply = _maxSupply;
}
function decimals() public view override returns (uint8) {
return decimal;
}
function mint (uint256 amount) external {
require(amount + totalSupply() <= maxSupply, "over max supply.");
_mint(msg.sender, amount);
}
}
```
## 基礎2
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Advanced0106_2 is ERC721 {
uint256 public availableQuantity = 10;
constructor() ERC721("SBT Token", "SBT") {}
function mint(address to, uint256 quantity) external payable {
require(0 <= availableQuantity-quantity , "Not available quantity");
availableQuantity = availableQuantity-quantity;
_mint(to, quantity);//使用錯誤
}
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
require(
from == address(0) || to == address(0),
"You cannot transfer this token"
);
}
}
```
---
## ***# Refactor***
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Advanced0106_2 is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
uint256 public maxSupply;
modifier avaialbeMint(uint256 amount) {
require(amount + _tokenIds.current() <= maxSupply, "over max supply.");
_;
}
constructor(
string memory _name,
string memory _symbol,
uint256 _maxSupply)
ERC721(_name, _symbol){
maxSupply = _maxSupply;
}
function mint (uint256 amount) external avaialbeMint(amount){
for(uint256 i=0; i < amount ; i++){
uint256 tokenId = _tokenIds.current();
_mint(msg.sender, tokenId);
_tokenIds.increment();
}
}
function transferFrom(address from, address to, uint256 tokenId) public override {
require(
from == address(0) || to == address(0),
"You cannot transfer this token"
);
}
}
```
## 基礎3
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract Basic0106_3 {
event GuessResult(string message);
address public owner;
uint256 public targetNumber;
bool public result;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function setTargetNumber(uint256 _newTargetNumber) external onlyOwner{
targetNumber = _newTargetNumber;
result = false;
}
function guess(uint256 guessNumber) external {
require(result == false, "Not started yet!");
if(targetNumber == guessNumber) {
emit GuessResult("Bingo!");
result = true;
}
else {
emit GuessResult("Not correct number!");
}
}
}
```
---
## ***# Refactor***
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract Basic0106_3 {
event GuessResult(string message);
mapping (address => bool) public guessRecord;
struct GameInfo{
uint256 minValue;
uint256 maxValue;
uint256 target;
address winner;
bool result;
}
GameInfo gameInfo;
constructor (
uint256 _min,
uint256 _max,
uint256 _target
){
gameInfo = GameInfo(
{
minValue: _min,
maxValue: _max,
target: _target,
winner: msg.sender,
result: false
}
);
}
modifier onlyWinner {
require(gameInfo.winner == msg.sender);
_;
}
function setTargetNumber(uint256 _newTargetNumber) external onlyWinner {
require(gameInfo.result == true, "The game is still going!");
gameInfo.target = _newTargetNumber;
gameInfo.result = false;
}
function guess(uint256 guessNumber) external {
require(gameInfo.result == false, "The game hasn't started yet!");
require(gameInfo.winner != msg.sender, "You are the host!");
require(!guessRecord[msg.sender], "Already guessed.");
guessRecord[msg.sender] = true;
if(gameInfo.target == guessNumber) {
gameInfo.winner = msg.sender;
gameInfo.result = true;
emit GuessResult("Bingo!");
}
else {
emit GuessResult("Not correct number!");
}
}
function getWinner () external view returns (address){
return gameInfo.winner;
}
}
```
## 進階1
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Advanced0106_1 is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address public owner;
string url = "";
constructor() ERC721("BlindBox", "BOX") {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function _baseURI() internal view override returns (string memory) {
return url;
}
function setUrl(string calldata _url) public onlyOwner {
url = _url;
}
function mint(address to) public {
uint256 tokenId = _tokenIds.current();
_mint(to, tokenId);
_tokenIds.increment();
}
}
```
---
## ***# Refactor***
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Advanced0106_1 is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
using Strings for uint256;
address owner;
uint256 public maxSupply = 10;
bool private isOpened = false;
modifier onlyOwner{
require(msg.sender == owner);
_;
}
constructor (string memory _name, string memory _symbol) ERC721(_name, _symbol){
owner = msg.sender;
}
function openBlindBox() external onlyOwner{
isOpened = true;
}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://QmXxZBg4RnGxC2dDxfUSAmxgGooHsoncPQgCLiNw8kj3Ls/";
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (!isOpened){
return _baseURI();
}
return string(abi.encodePacked("ipfs://QmWQcaFFCm9ofyVN2ZwGbTGopLEbQ6QSc2Xn1C7ekKAYDF/", tokenId.toString(), ".json"));
}
function mint (uint256 amount) external{
require(amount + _tokenIds.current() < maxSupply, "Over max supply.");
for(uint256 i = 0; i < amount ; i++){
uint256 tokenId = _tokenIds.current();
_mint(msg.sender, tokenId);
_tokenIds.increment();
}
}
}
```
## 進階2
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "erc721a/contracts/ERC721A.sol";
contract Advanced0106_2 is ERC721A {
constructor() ERC721A("ERC721A Token", "721AT") {}
function mint(address to, uint256 quantity) external payable {
_mint(to, quantity);
}
function transferFromByERC721A(
address from,
address to,
uint256 tokenId
) external payable {
transferFrom(from, to, tokenId);
}
}
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Advanced0106_2_2 is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721("ERC721 Token", "721T") {}
function mint(address to) public {
uint256 tokenId = _tokenIds.current();
_mint(to, tokenId);
_tokenIds.increment();
}
function batchMint(address to, uint256 quantity) external payable {
for (uint i = 0; i < quantity; i++) {
mint(to);
}
}
function transferFromByERC721(
address from,
address to,
uint256 tokenId
) external payable {
_transfer(from, to, tokenId);
}
}
```
---
## ***# Refactor***
```solidity
```