LoginSignup
10
8

More than 3 years have passed since last update.

Truffleのテストが実行できないエラーに対応する

Posted at

ブロックチェーンアプリケーション開発の教科書のERC20準拠のトークン作成でエラーに遭遇したのでメモ。

結論

solidityのバージョンエラーとopenzeppelinのコードに変更があったことによるエラーでした。
以下のように修正することでテストが実行できました。

pragma solidity ^0.5.0;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract DappsToken is ERC20 {
  string public name = "DappsToken";
  string public symbol = "DTKN";
  uint public decimals = 18;

  constructor(uint initialSupply) public {
    _mint(msg.sender, initialSupply);
  }

}

エラー対応①

テストを実行すると以下のようなエラーが出た。

truffle(develop)> test

Compiling your contracts...
===========================
> Compiling ./contracts/DappsToken.sol
> Compiling ./contracts/Migrations.sol
> Compiling openzeppelin-solidity/contracts/ownership/Ownable.sol

SyntaxError: Source file requires different compiler version (current compiler is 0.5.0+commit.1d4f565a.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity ^0.4.23;
^----------------------^

DeclarationError: Identifier not found or not unique.
contract DappsToken is StandardToken {
                       ^-----------^

Error: Truffle is currently using solc 0.5.0, but one or more of your contracts specify "pragma solidity ^0.4.23".
Please update your truffle config or pragma statement(s).
(See https://truffleframework.com/docs/truffle/reference/configuration#compiler-configuration for information on
configuring Truffle to use a specific solc compiler version.)

Compilation failed. See above.

エラー内容としては、以下の2点。
- truffleの対応バージョンが0.5.0からなのでsolidityのバージョンが古い
- StandardTokenが見つからない

truffleの対応バージョンが0.5.0からなのでsolidityのバージョンが古い

バージョンを修正。

-pragma solidity ^0.4.23;
+pragma solidity ^0.5.0;

StandardTokenが見つからない

openzeppelin-solidity/contracts/token/StandardToken.sol'が正しそうだが、最新のopenzeppelinのソースコードにはStandardToken.solというファイルは無く、代わりにERC20.solというファイルが出来ていた。こちらを使うのが正しそう。

-import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
+import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

-contract DappsToken is StandardToken {
+contract DappsToken is ERC20 {

エラー対応②

上記の修正を行いもう一度テストするとまたエラー。

Compiling your contracts...
===========================
> Compiling ./contracts/DappsToken.sol
> Compiling ./contracts/Migrations.sol
> Compiling openzeppelin-solidity/contracts/math/SafeMath.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol

DeclarationError: Undeclared identifier. Did you mean "totalSupply"?
    totalSupply_ = initialSupply;
    ^----------^

DeclarationError: Undeclared identifier. Did you mean "balanceOf"?
    balances[msg.sender] = initialSupply;
    ^------^

Compilation failed. See above.

totalSupplyとbalancesが無い

openzeppelin-solidity/contracts/token/ERC20/BasicToken.solにinternalのmapping, 変数として定義されていたため、継承先でも触ることが出来たが、最新版ではprivateで定義されているため参照出来ない。

openzeppelin-solidity/BasicToken.sol at v1.12.0 · OpenZeppelin/openzeppelin-solidity · GitHub

mapping(address => uint256) internal balances;

uint256 internal totalSupply_;

openzeppelin-solidity/ERC20.sol at master · OpenZeppelin/openzeppelin-solidity · GitHub

mapping (address => uint256) private _balances;

mapping (address => mapping (address => uint256)) private _allowed;

uint256 private _totalSupply;

代わりにmintという関数で同様の処理を行うことができそう。

/**
 * @dev Internal function that mints an amount of the token and assigns it to
 * an account. This encapsulates the modification of balances such that the
 * proper events are emitted.
 * @param account The account that will receive the created tokens.
 * @param value The amount that will be created.
 */
function _mint(address account, uint256 value) internal {
    require(account != address(0), "ERC20: mint to the zero address");

    _totalSupply = _totalSupply.add(value);
    _balances[account] = _balances[account].add(value);
    emit Transfer(address(0), account, value);
}

下記のように修正。

-    totalSupply_ = initialSupply;
-    balances[msg.sender] = initialSupply;
+    _mint(msg.sender, initialSupply);

無事に実行できた。

truffle(develop)> test

Compiling your contracts...
===========================
> Compiling ./contracts/DappsToken.sol
> Compiling ./contracts/Migrations.sol
> Compiling openzeppelin-solidity/contracts/math/SafeMath.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
> Artifacts written to /var/folders/05/8v72f98537x82ygl33y3_xzw0000gp/T/test-11942-93269-g4qlu1.bbje4
> Compiled successfully using:
   - solc: 0.5.0+commit.1d4f565a.Emscripten.clang



  0 passing (0ms)

最終的には下記のように変更することでテストが実行できた。

pragma solidity ^0.5.0;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract DappsToken is ERC20 {
  string public name = "DappsToken";
  string public symbol = "DTKN";
  uint public decimals = 18;

  constructor(uint initialSupply) public {
    _mint(msg.sender, initialSupply);
  }

}

参考

OpenZeppelinを活用してセキュアのコントラクトを書く - Qiita
GitHub - OpenZeppelin/openzeppelin-solidity: OpenZeppelin is a library for secure smart contract development
ブロックチェーンアプリケーション開発の教科書 | 加嵜 長門, 篠原 航, 丸山 弘詩 |本 | 通販 | Amazon

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8