LoginSignup
1
3

More than 5 years have passed since last update.

SolidityのimportでIdentifier already declaredと言われる原因とその対処法

Last updated at Posted at 2018-08-01

Solidityで複数ファイルに分けたコントラクトをimportするとき、
DeclarationError: Identifier already declared
と言われてcompileに失敗することがある。
一方で、失敗しないときもある。その違いを探す。

1. 失敗しないとき

ContractA.sol
pragma solidity ^0.4.23;

import "../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract ContractA is Ownable {
    constructor () public {
        owner = msg.sender;
    }
}
ContractB.sol
pragma solidity ^0.4.23;

import "./ContractA.sol";
import "../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract ContractB is Ownable {
    ContractA contractA;
    constructor (ContractA _aAddress) public {
        owner = msg.sender;
        contractA = _aAddress;
    }
}

2. 失敗するとき

ContractA.sol
pragma solidity ^0.4.23;

import "../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract ContractA is Ownable {
    constructor () public {
        owner = msg.sender;
    }
}
ContractB.sol
pragma solidity ^0.4.23;

import "./ContractA.sol";
import "../node_modules/openzeppelin-zos/contracts/ownership/Ownable.sol";

contract ContractB is Ownable {
    ContractA contractA;
    constructor (ContractA _aAddress) public {
        owner = msg.sender;
        contractA = _aAddress;
    }
}
エラー内容
DeclarationError: Identifier already declared.
import "../node_modules/openzeppelin-zos/contracts/ownership/Ownable.sol";
^------------------------------------------------------------------------^

3. 原因

間違い探しみたいになってしまったが、1では全く同じOwnableをimportしている。
つまり、同じコントラクトを複数回importしてもエラーにはならない
一方2では、ContractAでzeppelin-solidityのOwnableを、ContractBでzeppelin-zosのOwnableをimportしている。
これは同じ名前の別のコントラクトを実装していることになりDeclarationError: Identifier already declared.が引き起こされる
このように自分でimportを書いている場合、このエラーに気づかないことはあまりないかもしれないが、ライブラリの内部的にimportが行われている場合には、気づくのが難しかったりする。特に、細かいversionの違いが厄介なことがある。

4. 対処法

  • 同じパッケージを使うように注意する
  • import {必要なもの} from ファイル名の構文を使って、なるべく不要なものはimportしないようにする。

例えば、2を以下のように変更するとエラーにならない。

ContractA.sol
pragma solidity ^0.4.23;

import "../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol";

contract ContractA is Ownable {
    constructor () public {
        owner = msg.sender;
    }
}
ContractB.sol
pragma solidity ^0.4.23;

import {ContractA} from "./ContractA.sol";
import "../node_modules/openzeppelin-zos/contracts/ownership/Ownable.sol";

contract ContractB is Ownable {
    ContractA contractA;
    constructor (ContractA _aAddress) public {
        owner = msg.sender;
        contractA = _aAddress;
    }
}
1
3
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
1
3