Solidity

…是抽象合約或介面,無法部署

  • April 12, 2020

我沒有任何程式語言經驗。但我有興趣了解如何創建自己的 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;
}

注意:您的設置中可能還有其他問題,因為那應該是編譯器錯誤。

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