Solidity
如何使用 openzeppelin 創建 ERC20 合約並初始化 _total_supply?
我正在嘗試學習如何使用 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;
因此,您確實沒有必要在您的子契約中保留類似的變數。