Truffle Deployment – What Address Deploys a Contract in Truffle Test

blockchainsoliditytestingtruffle

I have a contract called AccessControl, in which the owner of the contract is set when it is deployed.

I want to test that the method on it setCEO updates correctly, but in order to do this the request must come from the owner of the contract.

contract AccessControl {

    address public ceoAddress;

    modifier onlyCEO() {
        require(msg.sender == ceoAddress);
        _;
    }

    function setCEO(address _newCEO) external onlyCEO {
        require(_newCEO != address(0));

        ceoAddress = _newCEO;
    }
}

When I console.log in the tests the current ceoAddress like so:

const paymentPipe = await PaymentPipe.deployed();
console.log(await paymentPipe.ceoAddress());

I see that the address is 0x0000000000000000000000000000000000000000.

When I try to call setCEO in my tests from that account like so:

await paymentPipe.setCEO(bob, {from: contractAddress});

Truffle complains:

Error: sender account not recognized

If I try with any other account in the truffle test suite (i.e. accounts[x]) I get:

Error: VM Exception while processing transaction: revert

Implying that the method did not pass the require statement because the calling address was not the one set as CEO.

What address are contracts deployed from in the truffle test suite? And why, if I can see an address in my contract as 0x0000000000000000000000000000000000000000 can I not use this address to call functions?

Best Answer

I think your problem appear because ceoAddress is not initialized properly, and it will have the value of 0x0000000000000000000000000000000000000000.

Now to change it the contract requires msg.sender == ceoAddress, this implies that msg.sender should be 0x0000000000000000000000000000000000000000. This operation can't be done because you do not have the private key that generates such address.

One options is to initialize your variable in the constructor with the sender account

contract AccessControl {

    address public ceoAddress;

    modifier onlyCEO() {
        require(msg.sender == ceoAddress);
        _;
    }

    constructor() {
        // ---- Initialize ceoAddress ----
        ceoAddress = msg.sender;
    }

    function setCEO(address _newCEO) external onlyCEO {
        require(_newCEO != address(0));

        ceoAddress = _newCEO;
    }
}

Truffle uses the first address returned by eth.accounts to deploy contracts.

2_deploy_contracts.js

module.exports = function(deployer, network, accounts) {
    // You can pass other parameters like gas or change the from
    deployer.deploy(AccessControl, { from: accounts[2] });
}

Check Truffle documentation for more options to use.

Related Topic