New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should private functions really clash ? #11889
Comments
The error message is of course bad because you cannot override the functions. I'm fine with allowing it, but then without a warning. |
I also think that such functions should be allowed and without a warning. If |
We should be careful if non-private can be changed to private in inheritance. |
Looks like it can't: contract C {
function f() internal virtual {}
}
contract D is C {
function f() private override {}
}
|
Also: contract C {
function x() external virtual returns (uint) {}
function y() public virtual returns (uint) {}
function z() internal virtual returns (uint) {}
}
contract D is C {
uint private override x;
uint private override y;
uint private override z;
}
|
Shadowing makes no sense considering inaccessible functions (i.e. private), so in essence allowing this makes sense. However it definitely opens up the possibility for crafting/hiding confusing code, given contracts can have many internal and private functions, combining that with inheritance sometimes it is really hard to decipher what is the actual code used for the contract. The virtual/override specifiers help with that. While I do not think it is a good idea to try "saving people from mistakes" with weird rules like this, but I would put the question on the table: should this change be made in a breaking release, just in order to trigger a more thorough review from people using the language? Users tend to review their contracts more carefully when they bump a breaking release. |
My use-case is a bit complex, and one might argue that it comes from bad design on our end. OpenZeppelin provides a lot of functionalities in its different contracts and library. We also offer a framework for upgradeable contracts. This framework includes solidity code, and javascript tooling to help use deploy and update their contracts. This tooling, in particular, checks dangerous behaviour, such a selfdestruct (see parity bug) and delegate calls (which can lead to self destruct). We want to protect users from using these in upgradeable contracts. We have an To limit false positives, we decided to:
The result is that we have this private function in some of our upgradeable contracts:
Now if I want to build a UUPSUpgradeable contract (inherits from ERC1967UpgradeUpgradeable) with the multicall feature ... I get my private function defined twice. I'm sure we can rework our transpilling workflow, and the way our checks are performed ... but you asked me for my usecase so here it is. |
I don't think the concern that @axic shared is a significant one. Private functions are the easiest to trace back to their definition because it just requires a search in the contract where it is used. |
Had the same issue in the mid 2020: #9610 |
Now |
We discussed this today on the call. Overall there were some concerns about safety of allowing this but no one was strongly against so we're fine with changing the behavior. This is however very low priority right now because we have other important tasks on the roadmap. It may take some time before we get to implementing this ourselves, but we'd accept a PR if someone badly wanted to have it right now. |
We can use GitCoin to boost this change :) Moreover, this could attract more contributors to the repo. |
Sure, why not. |
Hello @Amxx, I thought of an approach but not sure if this solves the exact problem. Please have a look:
Now since we are not able to inherit A and B together, we creat contracts that delegate calls to A and B:
And inherit these contracts together
This will allow us to access all the functions of A and B using the state of A_caller and B_caller. Best regards! |
In that you have to worry about storage compatibility of A and B, you can't call internal functions, you possibly have to do many checks... Basically, you are arguing that doing something like a diamond proxy is a solution to the private function conflict. While it is technically true, I really don't think it's a reasonable/acceptable solution. |
This should not have been close. The issue remains present and IMO a fix would be welcome. |
@cameel can you reopen it ? |
Sure. We're in the process of closing off stale issues that we're unlikely to ever to implement ourselves but since this one is pretty much waiting for an external contribution (and even has a bounty on it), I guess keeping it open is fine. |
…her contracts (rebase)
This issue has been marked as stale due to inactivity for the last 90 days. |
This issue is still relevant and is addressed by a pending PR. It should bot because for stale. |
when you inherit contracts, their functions and state variables are available to the derived contract. This includes functions marked as private. While you might expect that private functions in contract A and contract B would not be accessible from contract AB, Solidity allows access to these functions when they are inherited. This behavior is by design in Solidity. When you inherit from contracts A and B in contract AB, all the functions and state variables from A and B, including the private ones, are part of contract AB. This allows the derived contract to access and use those functions as if they were its own.
In this code, AB inherits from both A and B, and it can access and call the private functions from both of them. This behavior follows Solidity's inheritance model, where all functions from parent contracts are included in the derived contract. If you want to prevent access to the private functions from the derived contract, you should consider changing the access level of those functions to internal or external, depending on your intended use case and visibility requirements. |
Private functions (and variable) are clearly not accessible from the derived contract like public or internal ones are. Sure, they make it into the final bytecode, but there is no reason to not "namespace" them.
|
This does NOT work. Unlike internal functions, private functions are NOT accessible in child contract. |
This issue has been marked as stale due to inactivity for the last 90 days. |
Again, this issue is still relevant and is addressed by a pending PR. It should not be marked as stale. |
…her contracts (rebase)
This issue has been marked as stale due to inactivity for the last 90 days. |
Was it resolved or not? |
no |
Let consider the following code:
What I am expecting
implementation of
__myPrivateFunction
are private, and they only make sense in the context of the contract that they are part of (A
andB
). They are not accessible fromAB
, so it is not like if a call from a function withinAB
wouldn't be resolvable.IMO, this should compile, possibly with a warning, but not with an error.
What happens
I get an error:
TypeError: Derived contract must override function "__myPrivateFunction". Two or more base classes define function with same name and parameter types.
Question/Request
Is that behaviour wanted? needed? Whould it be possible to accept this kind of ghost-conflicts?
The text was updated successfully, but these errors were encountered: