1

In a typical split contract, where onlyOwner being the standard zeppelin Ownerable modifier, how can the onlyOwner of A be enforced when it's called from B?

contract I is Ownerable {
    function transferAsset(address _from, address _to) public onlyOwner;
}

contract A is I {
    address asset;

    function transferAsset(address _to) public onlyOwner {
        asset = _to;
    }
}

contract B is I {
    I contractA;

    function doTransfer(address _to) public onlyOwner {
        contractA = I(A_Deployed_Address);

        contractA.transferAsset(_to);
    }
}

[edit]

Sorry for not making things clear in my original question. In my case I'm deploying both contract A and B from truffle, so both of their owner will be the deployment account that truffle uses.

Then it seems I have no choice but to change the owner of B to A's deployed address so that A can call B's transferAsset, which is basically Eli Drion's answer. I'm just a bit concerned if I do that, will there be any potential downfall that all future calling of B's onlyOwner modified functions must be initiated from A and not its original deployer?

And if I take the approach of deploying B from A, doesn't that imply import B in A, which would result in a bloated A that defeats the purpose of split contract (and back to the out-of-gas problem I'm having during contract deployment)

  • Are you trying to say you want A to be owned by B for B's exclusive use, or you want B to create a contract for someone and give ownership away? – Rob Hitchens - B9lab Apr 13 '18 at 16:51
0

Typically, Ownable contract includes in its constructor the following line owner = msg.sender. It means that whoever deploys the contract, will be set as the owner.

A inherits of I which inherits of Ownable. So, A inherits of it too.

When B will call A, the msg.sender will be B's address, and it won't match (except if you changed it later) the owner of A, since you use the modifier onlyOwner.

0

I assume that you create A from the contract B. In this case the contract creator will be the msg.sender instead of the one who originated the transaction.

This is a common problem when you split your code in different contracts and I assume that you'd like to propagate the ownership across the contracts.

In this case you must to use tx.origin instead of msg.sender when you define your ownable contract. Since usually the common implementation is using the latter.

contract Ownable {
  address public owner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  function Ownable() public {
    owner = tx.origin;
  }

  modifier onlyOwner() {
    require(tx.origin == owner);
    _;
  }

  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    require(newOwner != owner);

    owner = newOwner;
    emit OwnershipTransferred(owner, newOwner);
  }
}

tx.origin is the one who generated the transaction and in your case will be the same in B and A. If you use msg.sender you'll have the original address in B but the B's address in A.

  • But isn't it (still) true that tx.origin should be avoided? -- link – Jerry Ji Apr 14 '18 at 1:25
  • yes but I don't know another way to do so then. Unless you use the sender and you change the ownership of the contract after has been created in the contract B. If you are the one who create that contract. – mirg Apr 14 '18 at 2:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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