[Ethereum] ReferenceError: cannot access ‘CONTRACT’ before initialization

ganachejavascriptsoliditytruffle

I'm trying to test a single smart contract (PCE_Contract.sol) with (PCE_Contract_test.js) using Truffle. When I run Truffle test, console output is :

ReferenceError: Cannot access 'PCE_Contract' before initialization

PCE_Contract_test.js:

const PCE_Contract = artifacts.require("./PCE_Contract");

contract('PCE_Contract', () => {

it('should deploy SC properly', async() => {

  const PCE_Contract = await PCE_Contract.deployed();

  console.log(PCE_Contract.address);

  assert(PCE_Contract !== '');

});

});

PCE_Contract.sol:

pragma solidity ^0.7.0;

contract PCE_Contract {

  uint256 public LOCK_PERIOD  = 365 days;
  address public investor;

  mapping(address => Deposit) deposits;

  constructor(){
  
  investor = msg.sender;
  }

  struct Deposit {
      uint256 value;
      uint256 releaseTime;
  }

  function investment() public payable {
       require(msg.value > 0,
         "You must make a non-zero deposit.");

       if (deposits[investor].releaseTime == 0) {
           uint256 releaseTime = block.timestamp + LOCK_PERIOD;
           deposits[investor] = Deposit(msg.value, releaseTime);

       } else {
           deposits[investor].value += msg.value;
       }
   }

   function withdraw() public {

    require(deposits[investor].value > 0,
      "You have no deposits available.");

    require(deposits[msg.sender].releaseTime < block.timestamp,
      "Your lock period has not ended yet.");

    msg.sender.transfer(deposits[investor].value);

    deposits[msg.sender].value = 0;
    deposits[msg.sender].releaseTime = 0;
}

function getDeposit(address holder) public view
  returns (uint256 value, uint256 releaseTime)

  {
        return(deposits[holder].value, deposits[holder].releaseTime);
    }

}

Truffle v5.1.49 (core: 5.1.49)
Solidity – ^0.7.0 (solc-js)
Node v12.18.4
Web3.js v1.2.1

Any help is appreciated !

Best Answer

Your problem is here:

const PCE_Contract = artifacts.require("./PCE_Contract");
...
{
    const PCE_Contract = await PCE_Contract.deployed();
    ...
}

The second declaration of PCE_Contract masks the first declaration of PCE_Contract.

So you are essentially attempting to use variable PCE_Contract before it has been declared (exactly as the error-message tells you).

If you placed these two declarations in the same scope, then you would get the error before the script was even executed. But since you placed them in two different scopes, the script was eligible for execution (and subsequently, the error did not occur before execution, only during execution).


Side note:

You can get rid of the ./ prefix in artifacts.require("./PCE_Contract"), because Truffle imports the artifacts from the JSON files generated by the compiler, not from the Solidity files where your actual source code is located (hence relative paths are not required in artifacts.require statements).

Related Topic