Solidity Inheritance – Who Can Call the Parent Function in Function Overwriting

contract-designcontract-developmentinheritanceSecuritysolidity

I want to know who is still able to call an original overwritten function in case of inheritance.

Let's assume I have the following setup:

contract A{
   address public owner;

   function A(){
       owner = msg.sender;
   }

   function doSomething(){
       // does something
   }
}

contract B is A{

   function doSomething(){
       require(msg.sender == owner);
       // do something like A but restrict this function execution to owner
       super.doSomething();
   }

}

If I deploy contract B can some external account that is not the owner still call doSomething of parent contract A? Or could some malicious contract execute the following:

contract EvilDoer{

    function doSomethingEvil{
         A contractB = A(addressOfdeployedB);

         contractB.doSomething();
    }

}

Or are overwritten functions shielded from external use?

EDIT: Overloading

Maybe it would be interesting and helpful to me and others to elaborate on the following as well: What happens in case of function overloading, i.e. if the signature in the child class is different from its parent (e.g. assume function doSomething(uint256 someNumber){...} in contract B)?

Best Answer

Last question first: overloading concept applies to Solidity but, as for other programming languages supporting overloading functions, i.e. C++, they are not related to each other in any way.

Functions with same name but different parameters are identified by different signatures, so they are actually different functions. If ContractA defines doSomething(), ContractB defines doSomething(string myString), and ContractB inherits from ContractA, final ContractB will have two valid functions that user can call: doSomething() and doSomething(string myString). Visibility also is part of the signature, but it can't be overloaded.

Main question now. From the outside of the contract, you cannot call a base function that has been overridden. This is because what you are calling from the outside is the final contract implementation, no matter how you define the interface on the client to call it.

If you defines

contract EvilDoer{
    function doSomethingEvil{
         A contractB = A(addressOfdeployedB);
         contractB.doSomething();
    }
}

You are simply defining another - and more restrictive - pointer to ContractB and to its implementation of doSomething(). And its implementation is the last one.

But hei, I know default function visibility is public, what if I define explicitly the base function in ContractA as external?

Not much, because you cannot override a function changing its extended signature. Visibility and return parameters are part of the extended function signature, so the compiler throws an error:

TypeError: Override changes extended function signature.

If you want to compile you need to use the same external modifier also in the ContractB function, and then again, the last implementation of function wins in any case.

Please note that changing visibility or return parameters it's not considered an overload neither, because functions are identified by signatures, contracts can't have two functions with the same signature and different extended attributes.

For more information about inheritance topics you can read the official documentation, in particular the information about the super keyword and the final inheritance graph of the contract.

Related Topic