You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two or more parent contracts define a function with the same name and signature
The inheritance order (left-to-right) does not match the developer's intended resolution
Vulnerable Pattern
contractOwnable {
function owner() publicviewvirtualreturns (address) {
return _owner; // Returns EOA owner
}
}
contractGovernance {
function owner() publicviewvirtualreturns (address) {
return governance; // Returns governance contract
}
}
// C3 linearization: rightmost (Ownable) takes precedence// Developer intended Governance.owner() but gets Ownable.owner()contractTreasuryisGovernance, Ownable {
// owner() resolves to Ownable (rightmost) — may not be intended// Should be: is Ownable, Governance (if Governance should win)
}
Detection Heuristics
Identify all contracts using multiple inheritance (is A, B, C)
For each inheritance chain, check if parent contracts define functions with the same name and signature
Verify the inheritance order follows general-to-specific (most base first, most derived last) — Solidity's C3 linearization gives precedence to the rightmost parent
Check override specifiers: override(A, B) should explicitly list which parents are being overridden
Trace the actual resolution order and compare against documented or intended behavior
False Positives
Only one parent defines the function (no ambiguity)
The contract explicitly overrides the function with override(A, B) and provides its own implementation
The inheritance order is intentionally general-to-specific and produces the correct resolution
Remediation
Order inheritance from most base to most derived (general-to-specific, left-to-right)
Explicitly override conflicting functions and specify which parents: override(ContractA, ContractB)