Skip to content
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

full function signature string and hash, not just selector #14360

Closed
thedavidmeister opened this issue Jun 26, 2023 · 4 comments
Closed

full function signature string and hash, not just selector #14360

thedavidmeister opened this issue Jun 26, 2023 · 4 comments
Labels
closed due inactivity The issue/PR was automatically closed due to inactivity. feature needs investigation stale The issue/PR was marked as stale because it has been open for too long.

Comments

@thedavidmeister
Copy link

thedavidmeister commented Jun 26, 2023

Abstract

We already have function.selector to get the 4 byte selector of some function (https://docs.soliditylang.org/en/v0.8.20/abi-spec.html#abi-function-selector).

This selector is fine for collision resistance within a single contract.

For cross referencing against signature databases such as https://openchain.xyz/signatures which are open registries of signature across all possible contract, the collision resistance is too low.

It's not difficult to find selectors that collide in these databases, especially when the selectors have been clearly crafted deliberately to collide (e.g. https://openchain.xyz/signatures?query=0x00000000).

Best would be exposing the source data (abi function signature string) and perhaps intermediate step (the 32 byte hash) that goes into computing a selector in the first place, so that smart contract devs have more flexibility here.

Motivation

When applying a pattern of generic support for arbitrary data (my use case is wanting to have initializable proxy/clone contracts with bytes memory data as the signature of initialize) the caller often needs to know the ABI in order to encode this data.

In the case of a generic tool, it's unlikely that the ABI for any arbitrary contract is available. However, often signature are uploaded to signature databases, which provide just enough information to encode some bytes correctly. The response from the signature database won't contain any quality of life information, not even a name or basic description of what each value in the signature is, but at least the tooling could understand something about the structure of the bytes.

This pattern is known and has been discussed https://twitter.com/PatrickAlphaC/status/1517156225670078465

💪 This gives us greater flexibility when designing protocols to take arbitrary inputs.

ERC-5750 even specifies that bytes memory data is a desirable extension method that interfaces should be compliant with in order to future proof themselves https://eips.ethereum.org/EIPS/eip-5750

For example, it specifies that data can be passed to a callback. The callback may well treat the data as an encoded function to call, such as might be found in the callback of an EIP 3156 flash borrower onFlashLoan (where opaque bytes are shuffled around between lender/borrower and need to somehow drive the borrower to take action then repay the loan), or some kind of governance contract, etc.

However, 5750 stops short of specifying how an individual contract can permissionlessly advertise exactly how that extension point should be consumed. For situations where the bytes encoding matches some function signature, one could imagine a simple solution where the function selector (available in solidity) of the extension data is emitted as an event, or available as a read only function on an interface.

But then, imagine that someone sees your contract advertising a mere 4 byte selector as the structure of its extensible data, then maliciously griefs you by generating and advertising the same selector into a signature database with a completely different ABI. At this point, automated tooling is faced with ambiguity as to how it might encode bytes. Had your contract emitted the full hash of the signature, or the string of the function signature itself, then such an attack would not be possible.

The signatures can be crafted manually with strings and keccaks in contract code, but this is fragile to do manually, especially for more complex types such as nested structs. Without going fully down the route of proposing another ERC to define all the above, Solidity could easily provide the function signature string and/or hash natively alongside the existing selector feature. If this pattern becomes sufficiently popular and adopted, some future ERC might naturally coalesce, in the meantime, anyone who wants this kind of thing can implement it themselves.

The motivation of avoiding manual/fragile code here is essentially the same as when selector was originally introduced

Note also that the original conversations around "function signature" vs. "cryptographic signature" being confusing still apply. We would need to be clear to disambiguate in any naming proposed.

Specification

Two new properties on interface methods, events and errors:

  • .abiFunctionSignature => canonical string of the signature e.g. "foo(uint256)"
  • .fullSelector => equivalent to keccak256(foo.abiFunctionSignature) but perhaps more semantic and efficient as it can be reliably computed at compile time, it's exactly the 32 bytes that are normally truncated down to 4 bytes to compute .selector

Technically either one of these can be implemented without the other, although if I had to choose only one I'd pick the string representation as we can always do the hashing ourselves, but we can't go back the other way without some kind of registry service. Not enforcing the need for a registry, so that kind of thing would be opt in, seems like it can only be a good thing.

Backwards Compatibility

No backwards compatibility issues.

@github-actions
Copy link

This issue has been marked as stale due to inactivity for the last 90 days.
It will be automatically closed in 7 days.

@github-actions github-actions bot added the stale The issue/PR was marked as stale because it has been open for too long. label Sep 24, 2023
@thedavidmeister
Copy link
Author

still looking for feedback on this

@github-actions github-actions bot removed the stale The issue/PR was marked as stale because it has been open for too long. label Sep 26, 2023
Copy link

github-actions bot commented Mar 7, 2024

This issue has been marked as stale due to inactivity for the last 90 days.
It will be automatically closed in 7 days.

@github-actions github-actions bot added the stale The issue/PR was marked as stale because it has been open for too long. label Mar 7, 2024
Copy link

Hi everyone! This issue has been automatically closed due to inactivity.
If you think this issue is still relevant in the latest Solidity version and you have something to contribute, feel free to reopen.
However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the forum instead.

@github-actions github-actions bot added the closed due inactivity The issue/PR was automatically closed due to inactivity. label Mar 14, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed due inactivity The issue/PR was automatically closed due to inactivity. feature needs investigation stale The issue/PR was marked as stale because it has been open for too long.
Projects
None yet
Development

No branches or pull requests

2 participants