Solidity
…是抽象合約或介面,無法部署
我沒有任何程式語言經驗。但我有興趣了解如何創建自己的 ERC20 代幣,並且使用 remix ethereum 成功部署了它,沒有任何錯誤。但是,一旦我試圖複製粘貼另一個具有更多功能的原始碼,那麼供應就變成了 N/A,這導致我嘗試使用 truffle 和 openzeppelin。編譯過程中出現數千個錯誤,但現在一切正常。就在我試圖做的時候
truffle migrate --reset
它顯示此錯誤消息:
2_deploy_token.js ================= Error: *** Deployment Failed *** "VrapzCoin" is an abstract contract or an interface and cannot be deployed. * Import abstractions into the '.sol' file that uses them instead of deploying them separately. * Contracts that inherit an abstraction must implement all its method signatures exactly. * A contract that only implements part of an inherited abstraction is also considered abstract. at Deployer._preFlightCheck (/usr/local/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:178:1) at processTicksAndRejections (internal/process/task_queues.js:97:5) at /usr/local/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:281:1 at Migration._deploy (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/migration.js:70:1) at Migration._load (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/migration.js:57:1) at Migration.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/migration.js:167:1) at Object.runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:148:1) at Object.runFrom (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:110:1) at Object.runAll (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:114:1) at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:79:1) at runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:253:1) at /usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:218:1 Truffle v5.1.20 (core: 5.1.20) Node v13.12.0
這是我的 VrapzCoin.sol 看起來像:
pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; //import "openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol"; //this one was already included on ERC20.sol import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; contract VrapzCoin is ERC20, ERC20Detailed, ERC20Mintable { }
這是其餘的:
ERC20.sol
pragma solidity ^0.5.0; import "../../GSN/Context.sol"; import "./IERC20.sol"; ///import "../../math/SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Basic { uint256 public totalSupply; function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a / b; return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } contract BasicToken is ERC20Basic { using SafeMath for uint256; mapping(address => uint256) balances; function transfer(address _to, uint256 _value) public returns (bool) { require(_value > 0); require(_to != address(0)); require(_value <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } function balanceOf(address _owner) public view returns (uint256 balance) { return balances[_owner]; } } contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval(address indexed owner, address indexed spender, uint256 value); } contract StandardToken is ERC20, BasicToken { mapping (address => mapping (address => uint256)) internal allowed; function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { require(_value > 0); require(_to != address(0)); require(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } function approve(address _spender, uint256 _value) public returns (bool) { require(_value > 0); allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } function allowance(address _owner, address _spender) public view returns (uint256) { return allowed[_owner][_spender]; } function increaseApproval(address _spender, uint _addedValue) public returns (bool) { require(_addedValue > 0); allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) { require(_subtractedValue > 0); uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } } contract BurnableToken is BasicToken { event Burn(address indexed burner, uint256 value); function burn(uint256 _value) public { require(_value > 0); require(_value <= balances[msg.sender]); address burner = msg.sender; balances[burner] = balances[burner].sub(_value); totalSupply = totalSupply.sub(_value); emit Burn(burner, _value); } }
ERC20Detailed.sol
pragma solidity ^0.5.0; import "./IERC20.sol"; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = 'VrapzCoin'; _symbol = 'VRZ''; _decimals = 2; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } }
ERC20Mintable.sol
pragma solidity ^0.5.0; import "./ERC20.sol"; import "../../access/roles/MinterRole.sol"; /** * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole}, * which have permission to mint (create) new tokens as they see fit. * * At construction, the deployer of the contract is the only minter. */ contract ERC20Mintable is ERC20, MinterRole { /** * @dev See {ERC20-_mint}. * * Requirements: * * - the caller must have the {MinterRole}. */ function mint(address account, uint256 amount) public onlyMinter returns (bool) { mint(account, amount); return true; } }
constructor
我已經看到了應該添加到我自己的 .sol 文件(即 VrapzCoin.sol)中的分步教程,但我已經在ERC20Detailed.sol上找到了它。所以,我把它設置為我自己的。這是我的deploy_token.js看起來像:
module.exports = function(deployer){ deployer.deploy(VrapzCoin); };
這是我學習這些東西的第三天。我什至做不到。
希望大神指點下哪裡錯了。。。
ERC20Detailed 的建構子接收三個參數來使用 ERC20Detailed 你應該傳遞這三個參數。
問題是 VrapzCoin 繼承自 ERC20Detailed 並且從未正確初始化它。
由於未使用這些參數,您可以刪除它們,並且合約應該編譯
constructor() public { _name = 'VrapzCoin'; _symbol = 'VRZ'; _decimals = 2; }
注意:您的設置中可能還有其他問題,因為那應該是編譯器錯誤。