DCIPs/EIPS/eip-5750.md

167 lines
8.8 KiB
Markdown
Raw Normal View History

---
eip: 5750
title: General Extensibility for Method Behaviors
description: Designating last param of dynamically sized bytes to be used for behavior extensions of methods.
author: Zainan Victor Zhou (@xinbenlv)
discussions-to: https://ethereum-magicians.org/t/erc-5750-method-with-extra-data/11176
status: Final
type: Standards Track
category: ERC
created: 2022-10-04
requires: 165
---
## Abstract
This EIP standardizes the passing of unstructured call data to functions to enable future extensibility.
## Motivation
The purpose of having extra data in a method is to allow further extensions to existing method interfaces.
It is it useful to make methods extendable. Any methods complying with this EIP, such as overloaded `transfer` and `vote` could use string reasons as the extra data. Existing EIPs that have exported methods compliant with this EIP can be extended for behaviors such as using the extra data to prove endorsement, as a salt, as a nonce, or as a commitment for a reveal/commit scheme. Finally, data can be passed forward to callbacks.
There are two ways to achieve extensibility for existing functions. Each comes with their set of challenges:
1. Add a new method
* What will the method name be?
* What will the parameters be?
* How many use-cases does a given method signature support?
* Does this support off-chain signatures?
2. Use one or more existing parameters, or add one or more new ones
* Should existing parameters be repurposed, or should more be added?
* How many parameters should be used?
* What are their sizes and types?
Standardizing how methods can be extended helps to answer these questions.
Finally, this EIP aims to achieve maximum backward and future compatibility. Many EIPs already partially support this EIP, such as [EIP-721](./eip-721.md) and [EIP-1155](./eip-1155.md). This EIP supports many use cases, from commit-reveal schemes ([EIP-5732](./eip-5732.md)), to adding digital signatures alongside with a method call. Other implementers and EIPs should be able to depend on the compatibility granted by this EIP so that all compliant method interfaces are eligible for future new behaviors.
## Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
When used in this EIP, the term `bytes` MUST be interpreted as the dynamically-sized byte array in Solidity data types.
1. Unlike many other ERCs which is compliant at the `contract` level, this ERC's specification specify compliance at `method` level.
2. Any method with a bytes as this method's last parameter is an _eligible_ method. It looks like this `function methodName(type1 value1, type2 value2, ... bytes data)`.
3. A _compliant_ method MUST be an _eligible_ method and MUST also designate that last `bytes` field in its method parameter for behaviors extensions.
4. If an _eligible_ method has an overloaded sibling method that
has the exact same method name and exact same preceding parameters
except for not having the last `bytes` parameter, the behavior
of the compliant method MUST be identical to
its overloaded sibling method when last `bytes` is an empty array.
### Examples of compliant and non-compliant methods
1. Here is a compliant method `methodName1` in a `Foo` contract
```solidity
contract Foo {
// @dev This method allows extension behavior via `_data` field;
function methodName1(uint256 _param1, address _param2, bytes calldata _data);
function firstNonRelatedMethod(uint256 someValue);
function secondNonRelatedMethod(uint256 someValue);
}
```
2. Here is a compliant method `methodName2` in a `Bar` contract which is an overloaded method for another `methodName2`.
```solidity
contract Foo {
// @dev This is a sibling method to `methodName2(uint256 _param1, address _param2, bytes calldata _data);`
function methodName2(uint256 _param1, address _param2);
// @dev This method allows extension behavior via `_data` field;
// When passed in an empty array for `_data` field, this method
// MUST behave IDENTICAL to
// its overloaded sibling `methodName2(uint256 _param1, address _param2);`
function methodName2(uint256 _param1, address _param2, bytes calldata _data);
function firstNonRelatedMethod(uint256 someValue);
function secondNonRelatedMethod(uint256 someValue);
}
```
3. Here is a non-compliant method `methodName1` because it do not allow extending behavior
```solidity
contract Foo {
// @dev This method DO NOT allow extension behavior via `_data` field;
function methodName1(uint256 _param1, address _param2, bytes calldata _data);
function firstNonRelatedMethod(uint256 someValue);
function secondNonRelatedMethod(uint256 someValue);
}
```
4. Here is a non-compliant method
`methodName2(uint256 _param1, address _param2, bytes calldata _data);`
because it behaves differently
to its overloaded sibling method
`methodName2(uint256 _param1, address _param2);` when `_data` is empty array.
```solidity
contract Foo {
// @dev This is a sibling method to `methodName2(uint256 _param1, address _param2, bytes calldata _data);`
function methodName2(uint256 _param1, address _param2);
// @dev This method allows extension behavior via `_data` field;
// When passed in an empty array for `_data` field, this method
// behave DIFFERENTLY to
// its overloaded sibling `methodName2(uint256 _param1, address _param2);`
function methodName2(uint256 _param1, address _param2, bytes calldata _data);
function firstNonRelatedMethod(uint256 someValue);
function secondNonRelatedMethod(uint256 someValue);
}
```
## Rationale
1. Using the dynamically-sized `bytes` type allows for maximum flexibility by enabling payloads of arbitrary types.
2. Having the bytes specified as the last parameter makes this EIP compatible with the calldata layout of solidity.
## Backwards Compatibility
Many existing EIPs already have compliant methods as part of their specification. All contracts compliant with those EIPs are either fully or partially compliant with this EIP.
Here is an incomplete list:
* In [EIP-721](./eip-721.md), the following method is already compliant:
* `function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;` is already compliant
* In [EIP-1155](./eip-1155.md), the following methods are already compliant
* `function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;`
* `function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;`
* In [EIP-777](./eip-777.md), the following methods are already compliant
* `function burn(uint256 amount, bytes calldata data) external;`
* `function send(address to, uint256 amount, bytes calldata data) external;`
However, not all functions that have a `bytes` as the last parameter are compliant. The following functions are not compliant without an overload since their last parameter is involved in functionality:
* In [EIP-2535](./eip-2535.md), the following methods is not compliant:
* `function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;`
* **Either** of the following can be done to create a compliance.
1. An overload MUST be created: `function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata, bytes calldata _data) external;` which adds a new `_data` after all parameters of original method.
2. The use of `bytes memory _calldata` MUST be relaxed to allow for extending behaviors.
* In [EIP-1271](./eip-1271.md), the following method is not compliant:
* `function isValidSignature(bytes32 _hash, bytes memory _signature) public view returns (bytes4 magicValue);`
* **Either** of the following can be done to create a compliance:
1. An new overload MUST be created: `function isValidSignature(bytes32 _hash, bytes memory _signature, bytes calldata _data) public view returns (bytes4 magicValue);` which adds a new `_data` after all parameters of original method.
2. The use of `bytes memory _signature` MUST be relaxed to allow for extending behaviors.
## Security Considerations
1. If using the extra data for extended behavior, such as supplying signature for onchain verification, or supplying commitments in a commit-reveal scheme, best practices should be followed for those particular extended behaviors.
2. Compliant contracts must also take into consideration that the data parameter will be publicly revealed when submitted into the mempool or included in a block, so one must consider the risk of replay and transaction ordering attacks. **Unencrypted personally identifiable information must never be included in the data parameter.**
## Copyright
Copyright and related rights waived via [CC0](../LICENSE.md).