1

I'm under the impression that the owner of the contract is simply referred to as accounts[0] in Truffle's testing environment, but I'm getting the error by the modifier that the caller of a certain function is not the owner.

I have instantiated contract A and contract B and the following code is in contract B:

    modifier requireContractOwner() {
        require(msg.sender == contractOwner, "Caller is not contract owner");
        _;
    }

    function _authorizeCaller(address addr)
        external
        requireContractOwner
    {
        authorizedCaller[addr] = true;
    }

And I'm calling the functions from contract A:

    function authorizeCaller(address addr) public {
        B._authorizeCaller(addr);
    }

The way I instantiated A is:

    constructor(address dataContract) public {
        contractOwner = msg.sender;
        B = B(dataContract);
    }

and B:

   constructor() public {
        contractOwner = msg.sender;
        authorizedCaller[msg.sender] = true;
    }

Following is how I deploy them:

module.exports = function (deployer, network, accounts) {
  deployer.deploy(B).then(() => {
    return deployer
      .deploy(A, B.address)
      .then(() => {
       // configuration
      });
  });
};

The problem is, when I test calling the function with the owner of the contract:

      let B = await B.new();
      let A = await A.new(B.address);
      await A.authorizeCaller(accounts[1], {
        from: accounts[0],
        gasPrice: 0,
      });

the testing fails saying that accounts[0] is not the owner of the contract by the modifier requireContractOwner().

1 Answer 1

2

I'm under the impression that the owner of the contract is simply referred to as accounts[0] in Truffle's testing environment...

Unless you explicitly specify {from: someAccount}, the default is indeed {from: accounts[0]}.


And I'm calling the functions from contract A:

function authorizeCaller(address addr) public {
    B._authorizeCaller(addr);
}

Here, the value of msg.sender when function _authorizeCaller is executed will be the address of contract A, not the address of the deployer of contract A.

Hence the expression msg.sender == contractOwner will evaluate to false.

You should generally implement the requireContractOwner modifier in a utility contract:

contract Owned {
    address public contractOwner;

    constructor() public {
        contractOwner = msg.sender;
    }

    modifier requireContractOwner() {
        require(msg.sender == contractOwner, "Caller is not contract owner");
        _;
    }
}

And then inherit this contract and use it wherever needed:

import "./Owned.sol";

contract B is Owned {
    constructor() public {
        // constructor of `Owned` has already executed at this point
        ...
    }

    function _authorizeCaller(address addr) external requireContractOwner {
        ...
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.