Hi @decrypter,
OK, I understand what you mean now 
What I still donât understand, though, is why you are concerned about whether the close() function in Destroyable can still be called if it is overridden in Bank.
As a result of the onlyOwner modifier, the close() function in Destroyable can only ever be called by the contract ownerâs address, and so it is already secure (at least in as much as the contract owner can be trusted as custodian of the contractâs remaining funds). If we didnât want selfdestruct() to be triggered (even by the contract owner), then all we would need to do is just not include Destroyable within our inheritance structure.
And I still come back to my original point that, if you give close() internal visibility, then you still overcomplicate the situation by creating a need for an additional public or external function to be added to enable the contract ownerâs external address to access the selfdestruct() functionality. This issue would still be present if close() was overriden in Bank, because if close() has internal visibility in Destroyable, then the overriding close() function in Bank would also have to be internal. This is because only external visibility of an overridden function can be modified to public visibility in the overriding function; all other visibility types must remain unchanged.
However, to answer your specific questionâŚ
Overriddenâf()
âin the base contract (A) cannot be called directly from either an external contract or non-contract (i.e. wallet) address. However, you could add another external or public function which could call it indirectly, as follows:
// Destroyable
contract Destroyable is Ownable {
function close() public virtual onlyOwner {
selfdestruct(owner);
}
}
// Excerpt from Bank, which inherits Destroyable
// Call the overriding function in Bank directly, to destroy the Bank contract
function close() public override onlyOwner {
selfdestruct(owner);
}
// Call this function, which calls the overridden function in Destroyable
// to destroy the Bank contract
function accessOverriddenFx() external {
Destroyable.close();
}
Ifâf()
âin the base contract (A) has internal
visibility (which I think is what you were suggesting as a preventative measure) and is overridden in the derived contract (B), then overridingâf()
âin B can also only have internal visibility. Neither of the twoâf()
âfunctions can be called directly from either an external contract or non-contract (i.e. wallet) address. However, you could implement an external or public function which could call either overridingâf()
âin B, or overriddenâf()
âin A, as follows:
// The same Destroyable contract for both alternatives
contract Destroyable is Ownable {
function close() internal virtual onlyOwner {
selfdestruct(owner);
}
}
// Excerpt from Bank, which inherits Destroyable - alternative 1
// Executing the overriding function in Bank to destroy the Bank contract
function close() internal override onlyOwner { // overriding function
selfdestruct(owner); // executed
}
function accessOverridingFx() external { // call this function
close();
}
// Excerpt from Bank, which inherits Destroyable - alternative 2
// Executing the overridden function in Destroyable to destroy the Bank contract
function close() internal override onlyOwner { // overriding function
selfdestruct(owner); // not executed
}
function accessOverriddenFx() external { // call this function
Destroyable.close();
}
Below are the links to the official Solidity documentation in terms of Inheritance and Function Overriding. You may already have consulted this, but I just want to include it here for completeness, as this is the documentation I have checked to draw my conclusions on the scenario you have asked about.
https://docs.soliditylang.org/en/latest/contracts.html#inheritance
https://docs.soliditylang.org/en/latest/contracts.html#function-overriding
Let me know if you have any further questions 