How to call the function of another smart contract in Solidity? With an example of OpenZeppelin transferOwnership function

When I'm learning OpenZeppelin, I found its Ownable library has a function transferOwnership, which can give the owner of current contract to an address. I can understand change owner to an account address of someone, however, it can also change owner to a contract address. My question is: If I change owner of current contract to another contract address, how can I use the other contract to handle the owner of my original contract? I tried inheritance with super key word, it doesn't work.

The failure code is as follow.

BTW, if it's useful to change owner of current contract to another contract address? Is there any example project to use this case?

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/access/Ownable.sol";

contract MyContract is Ownable {
    function getCurrentBalance() public view onlyOwner returns (uint) {
        return address(this).balance;
    }
    receive() external payable {}
}

contract ManageOwner is MyContract {
    function changeOwner(address newOwner) public  {
        super.transferOwnership(newOwner);
    }
}

Inheritance "Leaves you in the same contract", so it's obviously not what you want here.

In other words, there are two different contracts involved in the transfer of a contract's ownership to another contract, so inheriting the first contract is certainly not the way to go about, in this case.

Generally speaking, you just need the original contract to inherit from Ownable, which means that it implements function transferOwnership.

Then, you can simply execute this function using the current owner - presumably, your EOA (short for Externally Owned Account, which is just a plain wallet with a private key), and pass the address of the other contract as the new owner.

If you want to be able to transfer the ownership of the original contract, from that other contract to some other address (contract or account), then you'll need to implement infrastructure within that other contract to support it.


Yes, it is very useful, or at least - used to be very useful prior to the introduction of Upgradable Proxies and Upgradability Infrastructure, which have pretty much made it obsolete, I believe.

You can find here an example of a real-world project (dating back to before Upgradability concepts were introduced), which transfers the ownership of a contract to another contract.


EDIT:

I take back the made it obsolete part.

Having the ownership of a contract held by another contract is still useful regardless of upgradability.

1 Like

Thanks a lot for your patient reply, it really helps me.
These two contracts are deployed separately in two address, I want use contract B to invoke contract A's function to change owner.
I don't know the program of this part. I will try to use interface today to handle this. Maybe this is the right way.

That's not how you do it.

You need to use the current owner of contract A, in order to execute the ownership transfer from that current owner to contract B.

Assuming that the current owner is your EOA (i.e., your own wallet), you need to execute:

A.transferOwnership(B.address)

Using your EOA, not using contract B in any way (other than passing the address of contract B).

I use interface and success. The codes are as follow:

import "@openzeppelin/contracts/access/Ownable.sol";

contract A is Ownable {

    receive() external payable {}

    function getCurrentBalance() public view onlyOwner returns (uint) {
        return address(this).balance;
    }
}

interface I {
    function getCurrentBalance() external view returns (uint) ;
    function transferOwnership(address newOwner) external;
}


contract B is Ownable {

    I public itf = I(contract_A_address_); 

    receive() external payable {}

    function getBalanceOfA() public view onlyOwner returns (uint) {
        return itf.getCurrentBalance();
    }

    function changeAOwner(address newOwner) public onlyOwner{
        itf.transferOwnership(newOwner);
    }
}

First, deploy contract A. 2nd, copy contract A address to contract B. 3rd, deploy B. 4th, call transferOwnership function of contract A with address of contract B as args. 5th, call changeAOwner function of contract B to handle ownership of contract A.

Thank you Barakman again.

1 Like

I have a similar problem, I have a dividend contract that is owned by another contract, but I would like to change the owner of this dividend contract to a metamask wallet. Can someone help me?