argotorg / argotorg/solidity

Accessing function/event/error selector defined in parent interface through a child interface

Open
#16,840 3 comments 0 reactions 0 assignees View on GitHub
breaking change :warning: feature medium effort medium impact needs design
Dominant language
C++
Stars
25.7k
Forks
6.2k
Avg merge
2d 19h
Merged PRs (30d)
29

Description

## Abstract

Consider the the following code
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface A {
function a() external;
}

interface B is A {
function b() external;
}

contract test {
bytes4 public selectorFromA = A.a.selector;
bytes4 public selectorFromB = B.a.selector;
}
```

By inheritance `B is A`, the function `a()` it part of both interfaces, and should be implemented by contract implementing either `A` or `B`. However, the compiler fails to identify `a()` as a member of `B`, and the declaration of `selectorFromB` is seen as invalid.

```
TypeError: Member "a" not found or not visible after argument-dependent lookup in type(contract B).
--> tester.sol:14:35:
|
14 | bytes4 public selectorFromB = B.a.selector;
| ^^^
```

This should be supported

## Motivation

Beyond this simple exemple, we can consider the case of `ISafe`
```
import {ISafe} from "@safe-global/safe-smart-account/contracts/interfaces/ISafe.sol";
```
It is composed of many "module" interfaces, such as `IOwnerManager`. It would be great to be able to refer to function inside `ISafe` without having to load, and refer to the actual module that hold them.

I would like to be able to do
```solidity
import {ISafe} from "@safe-global/safe-smart-account/contracts/interfaces/ISafe.sol";
//...
abi.encodeCall(ISafe.swapOwner, ...);
```
and not have to do
```solidity
import {ISafe, IOwnerManager} from "@safe-global/safe-smart-account/interfaces/ISafe.sol";
(or)
import {IOwnerManager} from "@safe-global/safe-smart-account/interfaces/IOwnerManager.sol";
// ...
abi.encodeCall(IOwnerManager.swapOwner, ...);
```

## Specification

When resolving function, event or errors from a contract (or interface) for getting their selector, support the items declared both the contract (or interface) and the one declared in its parents. Currently, items declared in parents are not available.

## Backwards Compatibility

In our example above, if `A` and `B` declare functions with the same name and different argument, the ambiguity will cause a resolution issue that does not exist today. While it is breaking, I don't think this is a bad change. There is an ambiguity, and it should be mentioned to the user that the name actually cary two (or more) functions with the same name.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the provided A/B Solidity example and trace how member resolution handles selectorFromB. Check inherited function, event, and error selectors, including the specified ambiguity case; done when selectors can be accessed through child interfaces and ambiguous names produce a clear resolution error.

Written by the indexing model from the issue text.

Assessment

Tech stack
solidity
Domain
blockchain, compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.