Solidity

如何使用 openzeppelin 創建 ERC20 合約並初始化 _total_supply?

  • November 4, 2021

我正在嘗試學習如何使用 OpenZeppelin 庫創建 ERC20 合約。

我正在嘗試創建 ERC20 合約並在下面的程式碼中設置總供應量和余額:

pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract sampleToken is ERC20 
{
string public name = "ExampleToken";
string public symbol = "EGT";
uint public decimals = 18;
uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);
constructor() public 
   {
_totalSupply = INITIAL_SUPPLY;
_balances[msg.sender] = INITIAL_SUPPLY;
   }
}

在我的第一次嘗試中,我去了 openzeppelin 庫的 ERC20.sol 並將 _totalSupply 和 _balances 更改為內部,我得到了以下錯誤

> Compilation warnings encountered:

   Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
--> project:/contracts/sampleToken.sol

,Warning: Visibility for constructor is ignored. If you want the contract to be non-deployable, making it "abstract" is sufficient.
 --> project:/contracts/sampleToken.sol:11:1:
  |
11 | constructor() public 
  | ^ (Relevant source part starts here and spans across multiple lines).


TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:7:1:
 |
7 | string public name = "ExampleToken";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:61:5:
  |
61 |     function name() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:7:1:
 |
7 | string public name = "ExampleToken";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:61:5:
  |
61 |     function name() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:8:1:
 |
8 | string public symbol = "EGT";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:69:5:
  |
69 |     function symbol() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:8:1:
 |
8 | string public symbol = "EGT";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:69:5:
  |
69 |     function symbol() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable return types differ.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Contract "sampleToken" should be marked as abstract.
--> project:/contracts/sampleToken.sol:5:1:
 |
5 | contract sampleToken is ERC20 
 | ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation: 
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:53:5:
  |
53 |     constructor(string memory name_, string memory symbol_) {
  |     ^ (Relevant

然後經過我的研究,我將變數的所有狀態返回到私有並使用 _mint 函式,如下所示

pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract sampleToken is ERC20 
{
string public name = "ExampleToken";
string public symbol = "EGT";
uint public decimals = 18;
uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);
constructor() public 
   _mint(msg.sender, INITIAL_SUPPLY);
}

我收到以下錯誤

> Compilation warnings encountered:

   Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
--> project:/contracts/sampleToken.sol

,Warning: Visibility for constructor is ignored. If you want the contract to be non-deployable, making it "abstract" is sufficient.
 --> project:/contracts/sampleToken.sol:11:1:
  |
11 | constructor() public 
  | ^ (Relevant source part starts here and spans across multiple lines).


SyntaxError: Functions without implementation cannot have modifiers.
 --> project:/contracts/sampleToken.sol:11:1:
  |
11 | constructor() public 
  | ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:7:1:
 |
7 | string public name = "ExampleToken";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:61:5:
  |
61 |     function name() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:7:1:
 |
7 | string public name = "ExampleToken";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:61:5:
  |
61 |     function name() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:8:1:
 |
8 | string public symbol = "EGT";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:69:5:
  |
69 |     function symbol() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:8:1:
 |
8 | string public symbol = "EGT";
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:69:5:
  |
69 |     function symbol() public view virtual override returns (string memory) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable is missing "override" specifier.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Public state variables can only override functions with external visibility.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden function is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Overriding public state variable return types differ.
--> project:/contracts/sampleToken.sol:9:1:
 |
9 | uint public decimals = 18;
 | ^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overridden public state variable is here:
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:86:5:
  |
86 |     function decimals() public view virtual override returns (uint8) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Contract "sampleToken" should be marked as abstract.
--> project:/contracts/sampleToken.sol:5:1:
 |
5 | contract sampleToken is ERC20 
 | ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation: 
 --> @openzeppelin/contracts/token/ERC20/ERC20.sol:53:5:
  |
53 |     constructor(string memory name_, string memory symbol_) {
  |     ^ (Relevant source part starts here and spans across multiple lines).

,TypeError: Referenced declaration is neither modifier nor base class.
 --> project:/contracts/sampleToken.sol:12:5:
  |
12 |     _mint(msg.sender, INITIAL_SUPPLY);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Constructor must be implemented if declared.
 --> project:/contracts/sampleToken.sol:11:1:
  |
11 | constructor() public 
  | ^ (Relevant source part starts here and spans across multiple lines).

請指導我如何解決這些問題。

您最大的問題來自沒有呼叫 ERC-20 建構子。注意建構子行上的 ERC20(name, symbol)。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract myERC20Token is ERC20 
{
   constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol) {
       _mint(msg.sender, initialSupply);
   }
   
   function decimals() public view virtual override returns (uint8) {
       return 10;
   }
}

然後,小數不是Open zeppelin 實現中的變數,它是一個可以在需要時覆蓋的函式,就像我在前面的程式碼範例中所做的那樣:

如果您對預設的 18 位小數沒問題:

function decimals() public view virtual override returns (uint8) {
   return 18;
}

那麼就不需要覆蓋小數函式。

順便說一下,ERC-20 實現已經在內部定義了:

uint256 private _totalSupply;
string private _name;
string private _symbol;

因此,您確實沒有必要在您的子契約中保留類似的變數。

引用自:https://ethereum.stackexchange.com/questions/112864