From 5476d4ca5690ce65b4ce09e6c4329ab2964287c7 Mon Sep 17 00:00:00 2001 From: lightclient <14004106+lightclient@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:24:13 -0600 Subject: [PATCH 01/20] Update EIP-6357: Move to Last Call (#7) Co-authored-by: Gavin John --- ERCS/erc-6357.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-6357.md b/ERCS/erc-6357.md index da8d7614aef..9664ba7f275 100644 --- a/ERCS/erc-6357.md +++ b/ERCS/erc-6357.md @@ -4,7 +4,8 @@ title: Single-contract Multi-delegatecall description: Allows an EOA to call multiple functions of a smart contract in a single transaction author: Gavin John (@Pandapip1) discussions-to: https://ethereum-magicians.org/t/eip-6357-single-contract-multicall/12621 -status: Review +status: Last Call +last-call-deadline: 2023-11-10 type: Standards Track category: ERC created: 2023-01-18 From 28e9dca929241340cd79c217fd8c99190a278233 Mon Sep 17 00:00:00 2001 From: Joey <31974730+Joeysantoro@users.noreply.github.com> Date: Thu, 26 Oct 2023 15:39:34 -0400 Subject: [PATCH 02/20] erc7528 review (#11) --- ERCS/erc-7528.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ERCS/erc-7528.md b/ERCS/erc-7528.md index 399c671d72a..2140f1b0b7e 100644 --- a/ERCS/erc-7528.md +++ b/ERCS/erc-7528.md @@ -4,7 +4,7 @@ title: ETH (Native Asset) Address Convention description: An address placeholder for ETH when used in the same context as an ERC-20 token. author: Joey Santoro (@joeysantoro) discussions-to: https://ethereum-magicians.org/t/eip-7808-eth-native-asset-address-convention/15989 -status: Draft +status: Review type: Standards Track category: ERC created: 2023-10-03 @@ -39,8 +39,6 @@ Any fields or events where the Token is a non-enshrined wrapped ERC-20 version o ## Rationale -Smart Contract Systems which use both ETH and [ERC-20](./eip-20.md) in the same context should have a single address convention for the ETH case. - ### Considered alternative addresses Many existing implementations of the same use case as this standard use addresses such as 0x0, 0x1, and 0xe for gas efficiency of having leading zero bytes. @@ -53,10 +51,6 @@ Ultimately, all of these addresses collide with potential precompile addresses a This standard has no known compatibility issues with other standards. -## Reference Implementation - -N/A - ## Security Considerations Using ETH as a Token instead of WETH exposes smart contract systems to re-entrancy and similar classes of vulnerabilities. Implementers must take care to follow the industry standard development patterns (e.g. checks-effects-interactions) when the Token is ETH. From 0c1943fc5aa921fd52b8fa857b8685c4ef088aca Mon Sep 17 00:00:00 2001 From: OniReimu Date: Fri, 27 Oct 2023 06:52:01 +1100 Subject: [PATCH 03/20] Update ERC-5521: Move to Review (#14) * Transit from EIP repo * `eip` changed to `erc` as required * 5521: revert erc refs back to eip --------- Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- ERCS/erc-5521.md | 100 +++++++++++++++++++++++++++----- assets/erc-5521/system-arch.png | Bin 0 -> 186548 bytes 2 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 assets/erc-5521/system-arch.png diff --git a/ERCS/erc-5521.md b/ERCS/erc-5521.md index 4bf16cae954..5336c5fbd3d 100644 --- a/ERCS/erc-5521.md +++ b/ERCS/erc-5521.md @@ -4,7 +4,7 @@ title: Referable NFT description: An ERC-721 extension to construct reference relationships among NFTs author: Saber Yu (@OniReimu), Qin Wang , Shange Fu , Yilin Sai , Shiping Chen , Sherry Xu , Jiangshan Yu discussions-to: https://ethereum-magicians.org/t/eip-x-erc-721-referable-nft/10310 -status: Draft +status: Review type: Standards Track category: ERC created: 2022-08-10 @@ -13,7 +13,9 @@ requires: 165, 721 ## Abstract -This standard is an extension of [ERC-721](./eip-721.md). It proposes two referrable indicators, referring and referred, and a time-based indicator `createdTimestamp`. The relationship between each NFT forms a Directed acyclic graph (DAG). The standard allows users to query, track and analyze their relationships. +This standard is an extension of [ERC-721](./eip-721.md). It proposes two referable indicators, referring and referred, and a time-based indicator `createdTimestamp`. The relationship between each NFT forms a directed acyclic graph (DAG). The standard allows users to query, track and analyze their relationships. + +![System Architecture](../assets/eip-5521/system-arch.png) ## Motivation @@ -25,18 +27,78 @@ By adding the `referring` indicator, users can mint new NFTs (e.g., C, D, E) by 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. -`Relationship`: a structure that contains `referring`, `referred`, `createdTimestamp`, and other customized attributes such as `mapping (uint256 => address) privityOfAgreement` recording the ownerships of referred NFTs at the time the rNFTs were being created. -`referring`: an out-degree indicator, used to show the users this NFT refers to; -`referred`: an in-degree indicator, used to show the users who have refereed this NFT; -`createdTimestamp`: a time-based indicator, used to compare the timestamp of mint. +- `Relationship`: a structure that contains `referring`, `referred`, `createdTimestamp`, and other customized and **OPTIONAL** attributes (i.e., not necessarily included in the standard) such as `privityOfAgreement` recording the ownerships of referred NFTs at the time the rNFTs were being created or `profitSharing` recording the profit sharing of `referring`. +- `referring`: an out-degree indicator, used to show the users this NFT refers to; +- `referred`: an in-degree indicator, used to show the users who have refereed this NFT; +- `createdTimestamp`: a time-based indicator, used to compare the timestamp of mint, which **MUST NOT** be editable anyhow by callers; + +- `safeMint`: mint a new rNFT; +- `setNode`: set the referring list of an rNFT and update the referred list of each one in the referring list; + - `setNodeReferring`: set the referring list of an rNFT; + - `setNodeReferred`: set the referred list of the given rNFTs sourced from different contracts; + - `setNodeReferredExternal`: set the referred list of the given rNFTs sourced from external contracts; +- `referringOf`: get the referring list of an rNFT; +- `referredOf`: get the referred list of an rNFT. + +Implementers of this standard **MUST** have all of the following functions: + +```solidity + +pragma solidity ^0.8.4; + +interface IERC_5521 { + + /// Logged when a node in the rNFT gets referred and changed. + /// @notice Emitted when the `node` (i.e., an rNFT) is changed. + event UpdateNode(uint256 indexed tokenId, + address indexed owner, + address[] _address_referringList, + uint256[][] _tokenIds_referringList, + address[] _address_referredList, + uint256[][] _tokenIds_referredList + ); + + /// @notice set the referred list of an rNFT associated with different contract addresses and update the referring list of each one in the referred list. Checking the duplication of `addresses` and `tokenIds` is **RECOMMENDED**. + /// @param `tokenId` of rNFT being set. `addresses` of the contracts in which rNFTs with `tokenIds` being referred accordingly. + /// @requirement + /// - the size of `addresses` **MUST** be the same as that of `tokenIds`; + /// - once the size of `tokenIds` is non-zero, the inner size **MUST** also be non-zero; + /// - the `tokenId` **MUST** be unique within the same contract; + /// - the `tokenId` **MUST NOT** be the same as `tokenIds[i][j]` if `addresses[i]` is essentailly `address(this)`. + function setNode(uint256 tokenId, address[] memory addresses, uint256[][] memory tokenIds) external; + + /// @notice set the referring list of an rNFT associated with different contract addresses. + /// @param `tokenId` of rNFT being set, `addresses` of the contracts in which rNFTs with `_tokenIds` being referred accordingly. + function setNodeReferring(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private; + + /// @notice set the referred list of an rNFT associated with different contract addresses. + /// @param `_tokenIds` of rNFTs, associated with `addresses`, referred by the rNFT with `tokenId` in `this` contract. + function setNodeReferred(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private; + + /// @notice get the referring list of an rNFT. + /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT. + /// @return the referring mapping of the rNFT. + function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); + + /// @notice get the referred list of an rNFT. + /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT. + /// @return the referred mapping of the rNFT. + function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); +} + +interface TargetContract { + /// @notice set the referred list of an rNFT associated with external contract addresses. + /// @param `_tokenIds` of rNFTs associated with the contract address `_address` being referred by the rNFT with `tokenId`. + /// @requirement + /// - `_address` **MUST NOT** be the same as `address(this)` where `this` is executed by an external contract where `TargetContract` interface is implemented. + function setNodeReferredExternal(address _address, uint256 tokenId, uint256[] memory _tokenIds) external; -`safeMint`: mint a new rNFT; -`setNode`: set the referring list of an rNFT and update the referred list of each one in the referring list; -`setNodeReferring`: set the referring list of an rNFT; -`setNodeReferred`: set the referred list of the given rNFTs; -`setNodeReferredExternal`: set the referred list of the given rNFTs sourced from other contracts; -`referringOf`: Get the referring list of an rNFT; -`referredOf`: Get the referred list of an rNFT. + function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); + + function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory); +} + +``` ## Rationale @@ -62,8 +124,6 @@ Test cases are included in [ERC_5521.test.js](../assets/eip-5521/ERC_5521.test.j ```solidity -// SPDX-License-Identifier: MIT - pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; @@ -237,13 +297,21 @@ contract ERC_5521 is ERC721, IERC_5521, TargetContract { ## Security Considerations +### Timestamp + The `createdTimestamp` only covers the block-level timestamp (based on block headers), which does not support fine-grained comparisons such as transaction-level. +### Ownership and Reference + The change of ownership has nothing to do with the reference relationship. Normally, the distribution of profits complies to the aggreement when the NFT was being created regardless of the change of ownership unless specified in the agreement. Referring a token will not refer its descendants by default. In the case that only a specific child token gets referred, it means the privity of contract will involve nobody other than the owner of this specific child token. Alternatively, a chain-of-reference all the way from the root token to a specific very bottom child token (from root to leaf) can be constructured and recorded in the `referring` to explicitly define the distribution of profits. -The `safeMint` function has been deliberately designed to allow unrestricted minting and relationship setting, akin to the open referencing system seen in platforms like Google Scholar. This decision facilitates strong flexibility, enabling any user to create and define relationships between tokens without centralized control. While this design aligns with the intended openness of the system, it inherently carries certain risks. Unauthorized or incorrect references can be created, mirroring the challenges faced in traditional scholarly referencing where erroneous citations may occur. Additionally, the open nature may expose the system to potential abuse by malicious actors, who might manipulate relationships or inflate token supply. It is important to recognize that these risks are not considered design flaws but intentional trade-offs, balancing the system's flexibility against potential reliability concerns. Stakeholders should be aware that the on-chain data integrity guarantees extend only to what has been recorded on the blockchain and do not preclude the possibility of off-chain errors or manipulations. Thus, users and integrators should exercise caution and judgment in interpreting and using the relationships and other data provided by this system. +### Open Minting and Relationship Risks + +The `safeMint` function has been deliberately designed to allow unrestricted minting and relationship setting, akin to the open referencing system seen in platforms such as Google Scholar. This decision facilitates strong flexibility, enabling any user to create and define relationships between NFTs without centralized control. While this design aligns with the intended openness of the system, it inherently carries certain risks. Unauthorized or incorrect references can be created, mirroring the challenges faced in traditional scholarly referencing where erroneous citations may occur. Additionally, the open nature may expose the system to potential abuse by malicious actors, who might manipulate relationships or inflate token supply. It is important to recognize that these risks are not considered design flaws but intentional trade-offs, which balances the system's flexibility against potential reliability concerns. + +Stakeholders should be aware that the on-chain data integrity guarantees extend only to what has been recorded on the blockchain and do not preclude the possibility of off-chain errors or manipulations. Thus, users and integrators should exercise caution and judgment in interpreting and using the relationships and other data provided by this system. ## Copyright diff --git a/assets/erc-5521/system-arch.png b/assets/erc-5521/system-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..04a66feecf9aa0a8254f7de1a4959c7369bc1e71 GIT binary patch literal 186548 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

oH7 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

!BvN#<;v}Zmo8swCNHK@7 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 Date: Thu, 26 Oct 2023 15:55:23 -0400 Subject: [PATCH 04/20] erc 7535 (#13) --- ERCS/erc-7535.md | 165 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 ERCS/erc-7535.md diff --git a/ERCS/erc-7535.md b/ERCS/erc-7535.md new file mode 100644 index 00000000000..7f3bf663f6e --- /dev/null +++ b/ERCS/erc-7535.md @@ -0,0 +1,165 @@ +--- +eip: 7535 +title: Native Asset ERC-4626 Tokenized Vault +description: ERC-4626 Tokenized Vaults with Ether (Native Asset) as the underlying asset +author: Joey Santoro (@joeysantoro) +discussions-to: https://ethereum-magicians.org/t/eip-7535-eth-native-asset-tokenized-vault/16068 +status: Draft +type: Standards Track +category: ERC +created: 2023-10-12 +requires: 20, 4626, 7528 +--- + +## Abstract + +This standard is an extension of the [ERC-4626](./eip-4626.md) spec with an identical interface and behavioral overrides for handling Ether or any native asset as the underlying. + +## Motivation + +A standard for tokenized ETH Vaults has the same benefits as [ERC-4626](./eip-4626.md), particularly in the case of Liquid Staking Tokens, (i.e. fungible [ERC-20](./eip-20.md) wrappers around ETH staking). + +Maintaining the same exact interface as ERC-4626 further amplifies the benefits as the standard will be maximally compatible with existing ERC-4626 tooling and protocols. + +## Specification + +All [ERC-7535](./eip-7535.md) tokenized Vaults MUST implement ERC-4626 (and by extension ERC-20) with behavioral overrides for the methods `asset`, `deposit`, and `mint` specified below. + +### ERC-4626 Breaking Changes + +* Any `assets` quantity refers to wei of Ether rather than ERC-20 balances. +* Any ERC-20 `transfer` calls are replaced by Ether transfer (`send` or `call`) +* Any ERC-20 `transferFrom` approval flows for `asset` are not implemented +* `deposit` and `mint` have state mutability `payable` +* `deposit` uses `msg.value` as the primary input and MAY ignore `assets` + +### Methods + +#### asset + +MUST return `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` per [ERC-7528](./eip-7528.md). + +```yaml +- name: asset + type: function + stateMutability: view + + inputs: [] + + outputs: + - name: assetTokenAddress + type: address +``` + +#### deposit + +Mints `shares` Vault shares to `receiver` by depositing exactly `msg.value` of Ether. + +MUST have state mutability of `payable`. + +MUST use `msg.value` as the primary input parameter for calculating the `shares` output. MAY ignore `assets` parameter as an input. + +MUST emit the `Deposit` event. + +MUST revert if all of `msg.value` cannot be deposited (due to deposit limit being reached, slippage, etc). + +```yaml +- name: deposit + type: function + stateMutability: payable + + inputs: + - name: assets + type: uint256 + - name: receiver + type: address + + outputs: + - name: shares + type: uint256 +``` + +#### mint + +Mints exactly `shares` Vault shares to `receiver` by depositing `assets` of ETH. + +MUST have state mutability of `payable`. + +MUST emit the `Deposit` event. + +MUST revert if all of `shares` cannot be minted (due to deposit limit being reached, slippage, the user not sending a large enough `msg.value` of Ether to the Vault contract, etc). + +```yaml +- name: mint + type: function + stateMutability: payable + + inputs: + - name: shares + type: uint256 + - name: receiver + type: address + + outputs: + - name: assets + type: uint256 +``` + + +### Events + +The event usage MUST be identical to ERC-4626. + +### Wrapped ETH + +Any ERC-4626 Vault that uses a Wrapped ETH ERC-20 as the `asset` MUST NOT implement ERC-7535. ERC-7535 only applies to native ETH. + +## Rationale + +This standard was designed to maximize compatibility with ERC-4626 while minimizing additional opinionated details on the interface. Examples of this decision rationale are described below: + +* maintaining the redundant `assets` input to the `deposit` function while making its usage optional +* not enforcing a relationship between `msg.value` and `assets` in a `mint` call +* not enforcing any behaviors or lack thereof for `fallback`/`__default__` methods, payability on additional vault functions, or handling ETH forcibly sent to the contract + +All breaking implementation level changes with ERC-4626 are purely to accomodate for the usage of Ether or any native asset instead of an ERC-20 token. + +## Backwards Compatibility + +ERC-7535 is fully backward compatible with ERC-4626 at the function interface level. Certain implementation behaviors are different due to the fact that ETH is not ERC-20 compliant, such as the priority of `msg.value` over `assets`. + +It has no known compatibility issues with other standards. + +## Reference Implementation + +TODO / WIP + +## Security Considerations + +In addition to all security considerations of [ERC-4626](./eip-4626.md), there are security implications of having ETH as the Vault asset. + +### `call` vs `send` + +Contracts should take care when using `call` to transfer ETH, as this allows additional reentrancy vulnerabilities and arbitrary code execution beyond what is possible with trusted ERC-20 tokens. + +It is safer to simply `send` ETH with a small gas stipend. + +Implementers should take extra precautions when deciding how to transfer ETH. + +### Forceful ETH transfers + +ETH can be forced into any Vault through the `SELFDESTRUCT` opcode. Implementers should validate that this does not disrupt Vault accounting in any way. + +Similarly, any additional `payable` methods should be checked to ensure they do not disrupt Vault accounting. + +### Wrapped ETH + +Smart contract systems which implement ERC-4626 should consider only supporting ERC-20 underlying assets, and default to using a Wrapped ETH ERC-20 instead of implementing ERC-7535 for handling ETH. + +The subtle differences between ERC-4626 and ERC-7535 can introduce code fragmentation and security concerns. + +Cleaner use cases for ERC-7535 are ETH exclusive, such as Wrapped ETH and Liquid Staking Tokens. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From 9e2d1ec4416b1e73d8571616128214fa793cd729 Mon Sep 17 00:00:00 2001 From: Phan Dang Quy Date: Fri, 27 Oct 2023 03:26:37 +0700 Subject: [PATCH 05/20] Add ERC-7254 (#16) * Add ERC-7254 * 7254: remove extra newlines --------- Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- ERCS/erc-7254.md | 133 ++++++++++++++++++++ assets/erc-7254/ERC7254.sol | 233 +++++++++++++++++++++++++++++++++++ assets/erc-7254/IERC7254.sol | 151 +++++++++++++++++++++++ 3 files changed, 517 insertions(+) create mode 100644 ERCS/erc-7254.md create mode 100644 assets/erc-7254/ERC7254.sol create mode 100644 assets/erc-7254/IERC7254.sol diff --git a/ERCS/erc-7254.md b/ERCS/erc-7254.md new file mode 100644 index 00000000000..21cf1c0d74c --- /dev/null +++ b/ERCS/erc-7254.md @@ -0,0 +1,133 @@ +--- +eip: 7254 +title: Token Revenue Sharing +description: Revenue token is a token that shares rewards for holders. +author: Quy Phan (@quyphandang), Quy Phan +discussions-to: https://ethereum-magicians.org/t/token-revenue-sharing/14872 +status: Draft +type: Standards Track +category: ERC +created: 2023-06-29 +--- + +## Abstract + +With the aspiration of bringing forth unique functionality and enhancing value for holders of [ERC-20](./erc-20.md) tokens, our project aims to effortlessly reward token holders without necessitating users to lock, stake, or farm their tokens. Whenever the project generates profits, these profits can be distributed to the token holders. + +Revenue Sharing is an extended version of [ERC-20](./erc-20.md). It proposes an additional payment method for token holders. + +This standard includes updating rewards for holders and allowing token holders to withdraw rewards. + +Potential use cases encompass: + +* Companies distributing dividends to token holders. +* Direct sharing of revenue derived from business activities, such as marketplaces, Automated Market Makers (AMMs), and games. + + +## Specification + +### Methods + +#### maxTokenReward + +Returns max token reward. + +``` js +function maxTokenReward() public view returns (uint256) +``` + +#### informationOf + +Returns the account information of another account with the address `token` and `account`, including: inReward, outReward and withdraw. + +``` js +function informationOf(address token, address account) public view returns (UserInformation memory) +``` + +#### informationOfBatch + +Returns the list account information of another account with the `account`, including: inReward, outReward and withdraw. + +``` js +function informationOfBatch(address account) public view returns (UserInformation[] memory) +``` + +#### UserInformation + +`inReward`: when user's balance decreases, inReward will be updated +`outReward`: when user's balance increases, outReward will be updated +`withdraw`: total amount of reward tokens withdrawn + +```solidity +struct UserInformation { + uint256 inReward; + uint256 outReward; + uint256 withdraw; +} +``` + +#### tokenReward + +Returns the list token reward address of the token. + +``` js +function tokenReward() public view returns (address[] memory) +``` + +#### updateReward + +Updates rewardPerShare of token reward. +rewardPerShare = rewardPerShare + amount / totalSupply() + +``` js +function updateReward(address[] memory token, uint256[] memory amount) public +``` + +#### viewReward + +Returns the list amount of reward for an account + +``` js +function viewReward(address account) public view returns (uint256[] memory) +``` + +#### getReward + +Gets and returns reward with list token reward. + +``` js +function getReward(address[] memory token) public +``` + +#### getRewardPerShare + +Returns the reward per share of token reward. + +``` js +function getRewardPerShare(address token) public view returns (uint256) +``` + +#### existsTokenReward + +Returns the status of token reward. + +``` js +function existsTokenReward(address token) public view returns (bool) +``` + +## Rationale + +TBD + +## Reference Implementation + +* [ERC-7254](../assets/erc-7254/ERC7254.sol) +* [IERC-7254](../assets/erc-7254/IERC7254.sol) + +## Security Considerations + +Needs discussion. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). diff --git a/assets/erc-7254/ERC7254.sol b/assets/erc-7254/ERC7254.sol new file mode 100644 index 00000000000..3d341a2f740 --- /dev/null +++ b/assets/erc-7254/ERC7254.sol @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +/** +* @dev Implementation of the {IERC7254} interface. +* +* This implementation is agnostic to the way tokens are created. This means +* that a supply mechanism has to be added in a derived contract using {_mint}. + + +* Additionally, an {Approval} event is emitted on calls to {transferFrom}. +* This allows applications to reconstruct the allowance for all accounts just +* by listening to said events. Other implementations of the EIP may not emit +* these events, as it isn't required by the specification. +* +* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} +* functions have been added to mitigate the well-known issues around setting +* allowances. See {IERC7254-approve}. +*/ +contract ERC7254 is ERC20 { + struct UserInformation { + uint256 inReward; + uint256 outReward; + uint256 withdraw; + } + mapping(address => mapping(address => UserInformation)) private userInformation; + mapping(address => uint256) private rewardPerShare; + mapping(address => bool) private isTokenReward; + address[] private _tokenReward; + uint256 public constant MAX = 2**128; + /** + * @dev Emitted when the add reward of a `contributor` is set by + * a call to {approve}. + */ + event UpdateReward(address indexed contributor, uint256 value); + + /** + * @dev Emitted when `value` tokens reward to another (`to`) from caller + * `caller`. + * + * Note that `value` may be zero. + */ + event GetReward(address indexed owner, address indexed to, uint256 value); + + /** + * @dev Emitted when `token` tokens reward is added. + * + */ + event Add(address token); + + /** + * @dev Sets the values for {name} and {symbol} and {tokenReward}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All three of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_, address tokenReward_) ERC20(name_, symbol_){ + _tokenReward.push(tokenReward_); + isTokenReward[tokenReward_] = true; + } + + /** + * @dev Returns max token reward. + */ + function maxTokenReward() public view virtual returns(uint256){ + return 8; + } + + /** + * @dev Returns list user information by `account`. + */ + function informationOfBatch(address account) public view virtual returns (UserInformation[] memory) { + UserInformation[] memory user = new UserInformation[](_tokenReward.length); + for (uint256 i = 0; i < _tokenReward.length; ++i) { + user[i] = userInformation[_tokenReward[i]][account]; + } + return user; + } + + /** + * @dev Returns user information by `token reward` and `account`. + */ + function informationOf(address token, address account) public view virtual returns(UserInformation memory){ + return userInformation[token][account]; + } + + /** + * @dev Returns list token reward. + */ + function tokenReward() public view virtual returns (address[] memory) { + return _tokenReward; + } + + /** + * @dev Returns reward per share. + */ + function getRewardPerShare(address token) public view virtual returns (uint256){ + return rewardPerShare[token]; + } + + /** + * @dev Indicates whether token exist. + */ + function existsTokenReward(address token) public view virtual returns (bool){ + return isTokenReward[token]; + } + + /** + * @dev Returns the amount of reward by `account`. + */ + function viewReward(address account) public view virtual returns (uint256[] memory){ + uint256[] memory rewardOf = new uint256[](_tokenReward.length); + for( uint256 i = 0; i < _tokenReward.length; ++i){ + UserInformation memory user = informationOf(_tokenReward[i], account); + uint256 reward = balanceOf(account) * rewardPerShare[_tokenReward[i]] + user.inReward - user.withdraw - user.outReward; + rewardOf[i] = reward / MAX; + } + return rewardOf; + } + + /** + * @dev Add `amount` tokens . + * + * Emits a {UpdateReward} event. + */ + function updateReward(address[] memory token, uint256[] memory amount) public virtual { + require(token.length == amount.length, "ERC7254: token and amount length mismatch"); + address owner = _msgSender(); + if(totalSupply() != 0){ + for( uint256 i = 0; i < token.length; ++i){ + require(isTokenReward[token[i]], "ERC7254: token reward is not approved"); + IERC20(token[i]).transferFrom(owner, address(this), amount[i]); + _updateRewardPerShare(token[i], amount[i]); + emit UpdateReward(owner, amount[i]); + } + + } + } + + /** + * @dev Moves reward to another (`to`) from caller. + * + * + * Emits a {GetReward} event. + */ + function getReward(address[] memory token, address to) public virtual { + address owner = _msgSender(); + for( uint256 i = 0; i < token.length; ++i){ + UserInformation storage user = userInformation[token[i]][owner]; + uint256 reward = balanceOf(owner) * rewardPerShare[token[i]] + user.inReward - user.withdraw - user.outReward; + _withdraw(token[i], owner, reward); + if(reward / MAX > 0){ + IERC20(token[i]).transfer(to, reward / MAX); + } + emit GetReward(owner, to, reward); + } + } + + /** + * @dev Update list inReward of user. + * + */ + function _inReward(address user, uint256 amount) internal virtual { + for (uint256 i = 0; i < _tokenReward.length; ++i){ + UserInformation storage userFrom = userInformation[_tokenReward[i]][user]; + userFrom.inReward += amount * rewardPerShare[_tokenReward[i]]; + } + } + + /** + * @dev Update list outReward of user. + * + */ + function _outReward(address user, uint256 amount) internal virtual { + for (uint i = 0; i < _tokenReward.length; ++i){ + UserInformation storage userTo = userInformation[_tokenReward[i]][user]; + userTo.outReward += amount * rewardPerShare[_tokenReward[i]]; + } + } + + + /** + * @dev add reward withdraw of owner. + * + */ + function _withdraw(address token, address owner, uint256 reward) internal virtual { + require(owner != address(0), "ERC7254: withdraw from the zero address"); + UserInformation storage user = userInformation[token][owner]; + user.withdraw += reward; + } + + /** + * @dev Update reward per share. + * + */ + function _updateRewardPerShare(address token, uint256 amount) internal virtual { + require(token != address(0), "ERC7254: token the zero address"); + require(totalSupply() != 0, "ERC7254: totalSupply is zero"); + rewardPerShare[token] = rewardPerShare[token] + amount * MAX / totalSupply(); + } + + /** + * @dev add token reward. + * + */ + function _add(address[] memory token) internal virtual { + require(_tokenReward.length + token.length <= maxTokenReward(), "ERC7254: exceeds maxTokenReward"); + for ( uint256 i = 0; i < token.length; ++i ){ + require(!existsTokenReward(token[i]), "ERC7254: token already exists"); + require(token[i] != address(0), "ERC7254: token reward from the zero address"); + _tokenReward.push(token[i]); + isTokenReward[token[i]] = true; + emit Add(token[i]); + } + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal override { + if (from != address(0)) { + _inReward(from, amount); + } + if (to != address(0)) { + _outReward(to, amount); + } + } +} \ No newline at end of file diff --git a/assets/erc-7254/IERC7254.sol b/assets/erc-7254/IERC7254.sol new file mode 100644 index 00000000000..e130a0d44dc --- /dev/null +++ b/assets/erc-7254/IERC7254.sol @@ -0,0 +1,151 @@ + // SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC7254 standard as defined in the EIP. + */ +interface IERC7254 { + + struct UserInformation { + uint256 inReward; + uint256 outReward; + uint256 withdraw; + } + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Emitted when the add reward of a `contributor` is set by + * a call to {approve}. + */ + event UpdateReward(address indexed contributor, uint256 value); + + /** + * @dev Emitted when `value` tokens reward to another (`to`). + * + * Note that `value` may be zero. + */ + event GetReward(address indexed owner, address indexed to, uint256 value); + + /** + * @dev Emitted when `token` tokens reward is added. + * + */ + event Add(address token); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns max token reward. + */ + function maxTokenReward() external view returns(uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Returns list user information by `account`. + */ + function informationOfBatch(address account) external view returns (UserInformation[] memory); + + /** + * @dev Returns user information by `token reward` and `account`. + */ + function informationOf(address token, address account) external view returns(UserInformation memory); + + /** + * @dev Returns list token reward. + */ + function tokenReward() external view returns (address[] memory); + + /** + * @dev Returns reward per share. + */ + function getRewardPerShare(address token) external view returns (uint256); + + /** + * @dev Indicates whether token exist. + */ + function existsTokenReward(address token) external view returns (bool); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) external returns (bool); + + /** + * @dev Add `amount` tokens . + * + * Returns a rewardPerShare. + * + * Emits a {UpdateReward} event. + */ + function updateReward(address[] memory token, uint256[] memory amount) external; + + /** + * @dev Returns the amount of reward by `account`. + */ + function viewReward(address account) external returns (uint256[] memory); + + /** + * @dev Moves reward to another (`to`) from caller. + * + * Emits a {GetReward} event. + */ + function getReward(address[] memory token, address to) external; +} From 0707dfc77f68c4898abe8af670c257270c641e50 Mon Sep 17 00:00:00 2001 From: Joey <31974730+Joeysantoro@users.noreply.github.com> Date: Thu, 26 Oct 2023 16:40:09 -0400 Subject: [PATCH 06/20] ERC-7540: Asynchronous ERC-4626 Tokenized Vaults (#10) * async vaults erc * Update ERCS/erc-7540.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> * Update ERCS/erc-7540.md Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --------- Co-authored-by: lightclient <14004106+lightclient@users.noreply.github.com> --- ERCS/erc-7540.md | 323 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 ERCS/erc-7540.md diff --git a/ERCS/erc-7540.md b/ERCS/erc-7540.md new file mode 100644 index 00000000000..352cbf3c128 --- /dev/null +++ b/ERCS/erc-7540.md @@ -0,0 +1,323 @@ +--- +eip: 7540 +title: Asynchronous ERC-4626 Tokenized Vaults +description: Extension of ERC-4626 with asynchronous deposit and redemption support +author: Jeroen Offerijns (@hieronx), Alina Sinelnikova (@ilinzweilin), Vikram Arun (@vikramarun), Joey Santoro (@joeysantoro) +discussions-to: https://ethereum-magicians.org/t/eip-7540-asynchronous-erc-4626-tokenized-vaults/16153 +status: Draft +type: Standards Track +category: ERC +created: 2023-10-18 +requires: 20, 165, 4626 +--- + +## Abstract + +The following standard extends [ERC-4626](./eip-4626.md) by adding support for asynchronous deposit and redemption flows. The async flows are called Requests. + +New methods are added to asynchronously Request a deposit or redemption, and view the pending status of the Request. The existing `deposit`, `mint`, `withdraw`, and `redeem` ERC-4626 methods are used for executing Claimable Requests. + +Implementations can choose to whether to add asynchronous flows for deposits, redemptions, or both. + +## Motivation + +The ERC-4626 Tokenized Vaults standard has helped to make yield-bearing tokens more composable across decentralized finance. The standard is optimized for atomic deposits and redemptions up to a limit. If the limit is reached, no new deposits or redemptions can be submitted. + +This limitation does not work well for any smart contract system with asynchronous actions or delays as a prerequisite for interfacing with the Vault (e.g. real-world asset protocols, undercollateralized lending protocols, cross-chain lending protocols, liquid staking tokens, or insurance safety modules). + +This standard expands the utility of ERC-4626 Vaults for asynchronous use cases. The existing Vault interface (deposit/withdraw/mint/redeem) is fully utilized to claim asynchronous Requests. + +## Specification + +### Definitions: + +The existing definitions from [ERC-4626](./eip-4626.md) apply. In addition, this spec defines: + +- Request: a function call that initiates an asynchronous deposit/redemption flow +- Pending: the state where a Request has been made but is not yet Claimable +- Claimable: the state where a Request is processed by the Vault enabling the user to claim corresponding `shares` (for async deposit) or `assets` (for async redeem) +- Claimed: the state where a Request is finalized by the user and the user receives the output token (e.g. `shares` for a deposit Request) +- Claim function: the corresponding Vault method to bring a Request to Claimed state (e.g. `deposit` or `mint` claims `shares` from `requestDeposit`). Lower case claim always describes the verb action of calling a Claim function. +- operator: the account specified by the sender of the Request which has the right to claim a given Request once it is Claimable +- asynchronous deposit Vault: a Vault that implements asynchronous Requests for deposit flows +- asynchronous redemption Vault: a Vault that implements asynchronous redemption flows +- fully asynchronous Vault: a Vault that implements asynchronous Requests for both deposit and redemption + +### Request Flows + +ERC-7540 Vaults MUST implement one or both of asynchronous deposit and redemption Request flows. If either flow is not implemented in a Request pattern, it MUST use the ERC-4626 standard synchronous interaction pattern. + +All ERC-7540 asynchronous tokenized Vaults MUST implement ERC-4626 with overrides for certain behavior described below. + +Asynchronous deposit Vaults MUST override the ERC-4626 specification as follows: + +1. The `deposit` and `mint` methods do not transfer `asset` to the Vault, because this already happened on `requestDeposit`. +2. `previewDeposit` and `previewMint` MUST revert for all callers and inputs. + +Asynchronous redeem Vaults MUST override the ERC-4626 specification as follows: + +1. The `redeem` and `withdraw` methods do not transfer `shares` to the Vault, because this already happened on `requestRedeem`. +2. The `owner/operator` field of `redeem` and `withdraw` MUST be `msg.sender` to prevent the theft of requested redemptions by a non-owner/operator. +3. `previewRedeem` and `previewWithdraw` MUST revert for all callers and inputs. + +### Request Lifecycle + +After submission, Requests go through Pending, Claimable, and Claimed stages. An example lifecycle for a deposit Request is visualized in the table below. + +| **State** | **User** | **Vault** | +|-------------|---------------------------------|-----------| +| Pending | `requestDeposit(assets, operator)` | `asset.transferFrom(msg.sender, vault, assets)`; `pendingDepositRequest[operator] += assets` | +| Claimable | | *Internal Request fulfillment*: `pendingDepositRequest[msg.sender] -= assets`; `maxDeposit[operator] += assets` | +| Claimed | `deposit(assets, receiver)` | `maxDeposit[msg.sender] -= assets`; `vault.balanceOf[receiver] += shares` | + +An important Vault inequality is that following a Request(s), the cumulative requested quantity MUST be more than `pendingDepositRequest + maxDeposit - claimed`. The inequality may come from fees or other state transitions outside implemented by Vault logic such as cancellation of a Request, otherwise this would be a strict equality. + +Requests MUST NOT skip or otherwise short-circuit the Claim state. In other words, to initiate and claim a Request, a user MUST call both request* and the corresponding Claim function separately, even in the same block. + +For asynchronous Vaults, the exchange rate between `shares` and `assets` including fees and yield is up to the Vault implementation. In other words, pending redemption Requests MAY NOT be yield bearing and MAY NOT have a fixed exchange rate. + + +### Methods + +#### requestDeposit + +Transfers `assets` from `msg.sender` into the Vault and submits a Request for asynchronous `deposit/mint`. This places the Request in Pending state, with a corresponding increase in `pendingDepositRequest` for the amount `assets`. + +When the Request is Claimable, `maxDeposit` and `maxMint` will be increased for the case where the `receiver` input is the `operator`. `deposit` or `mint` can subsequently be called by `operator` to receive `shares`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state. + +The `shares` that will be received on `deposit` or `mint` MAY NOT be equivalent to the value of `convertToShares(assets)` at the time of Request, as the price can change between Request and Claim. + +MUST support [ERC-20](./eip-20.md) `approve` / `transferFrom` on `asset` as a deposit Request flow. + +MUST revert if all of `assets` cannot be requested for `deposit`/`mint` (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc). + +Note that most implementations will require pre-approval of the Vault with the Vault's underlying `asset` token. + +MUST emit the `RequestDeposit` event. + +```yaml +- name: requestDeposit + type: function + stateMutability: nonpayable + + inputs: + - name: assets + type: uint256 + - name: operator + type: address +``` + +#### pendingDepositRequest + +The amount of requested `assets` in Pending state for the `operator` to `deposit` or `mint`. + +MUST NOT include any `assets` in Claimable state for `deposit` or `mint`. + +MUST NOT show any variations depending on the caller. + +MUST NOT revert unless due to integer overflow caused by an unreasonably large input. + +```yaml +- name: pendingDepositRequest + type: function + stateMutability: view + + inputs: + - name: operator + type: address + + outputs: + - name: assets + type: uint256 +``` + +#### requestRedeem + +Assumes control of `shares` from `owner` and submits a Request for asynchronous `redeem/withdraw`. This places the Request in Pending state, with a corresponding increase in `pendingRedeemRequest` for the amount `shares`. + +MAY support either a locking or a burning mechanism for `shares` depending on the Vault implemention. + +If a Vault uses a locking mechanism for `shares`, those `shares` MUST be burned from the Vault balance before or upon claiming the Request. + +MUST support a redeem Request flow where the control of `shares` is taken from `owner` directly where `msg.sender` has ERC-20 approval over the `shares` of `owner`. + +When the Request is Claimable, `maxRedeem` and `maxWithdraw` will be increased for the case where the `owner` input is the `operator`. `redeem` or `withdraw` can subsequently be called by `operator` to receive `assets`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state. + +The `assets` that will be received on `redeem` or `withdraw` MAY NOT be equivalent to the value of `convertToAssets(shares)` at time of Request, as the price can change between Pending and Claimed. + +SHOULD check `msg.sender` can spend `owner` funds using allowance. + +MUST revert if all of `shares` cannot be requested for `redeem` / `withdraw` (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc). + +MUST emit the `RequestRedeem` event. + +```yaml +- name: requestRedeem + type: function + stateMutability: nonpayable + + inputs: + - name: shares + type: uint256 + - name: operator + type: address + - name: owner + type: address +``` + +#### pendingRedeemRequest + +The amount of requested `shares` in Pending state for the `operator` to `redeem` or `withdraw`. + +MUST NOT include any `shares` in Claimable state for `redeem` or `withdraw`. + +MUST NOT show any variations depending on the caller. + +MUST NOT revert unless due to integer overflow caused by an unreasonably large input. + +```yaml +- name: pendingRedeemRequest + type: function + stateMutability: view + + inputs: + - name: operator + type: address + + outputs: + - name: shares + type: uint256 +``` + +### Events + +#### DepositRequest + +`sender` has locked `assets` in the Vault to Request a deposit. `operator` controls this Request. + +MUST be emitted when a deposit Request is submitted using the `requestDeposit` method. + +```yaml +- name: DepositRequest + type: event + + inputs: + - name: sender + indexed: true + type: address + - name: operator + indexed: true + type: address + - name: assets + indexed: false + type: uint256 +``` + +#### RedeemRequest + +`sender` has locked `shares`, owned by `owner`, in the Vault to Request a redemption. `operator` controls this Request. + +MUST be emitted when a redemption Request is submitted using the `requestRedeem` method. + +```yaml +- name: RedeemRequest + type: event + + inputs: + - name: sender + indexed: true + type: address + - name: operator + indexed: true + type: address + - name: owner + indexed: true + type: address + - name: assets + indexed: false + type: uint256 +``` + +### [ERC-165](./eip-165.md) support + +Smart contracts implementing this standard MUST implement the [ERC-165](./eip-165.md) `supportsInterface` function. + +Asynchronous deposit Vaults MUST return the constant value `true` if `0xea446681` is passed through the `interfaceID` argument. + +Asynchronous redemption Vaults MUST return the constant value `true` if `0x2e9dd5bd` is passed through the `interfaceID` argument. + +## Rationale + +### Symmetry and Non-inclusion of requestWithdraw and requestMint + +In ERC-4626, the spec was written to be fully symmetrical with respect to converting `assets` and `shares` by including deposit/withdraw and mint/redeem. + +Due to the asynchronous nature of Requests, the Vault can only operate with certainty on the quantity that is fully known at the time of the Request (`assets` for `deposit` and `shares` for `redeem`). The deposit Request flow cannot work with a `mint` call, because the amount of `assets` for the requested `shares` amount may fluctuate before the fulfillment of the Request. Likewise, the redemption Request flow cannot work with a `withdraw` call. + +### Optionality of flows + +Certain use cases are only asynchronous on one flow but not the other between Request and redeem. A good example of an asynchronous redemption Vault is a liquid staking token. The unstaking period necessitates support for asynchronous withdrawals, however, deposits can be fully synchronous. + +### Non Inclusion of a Request Cancelation Flow + +In many cases, canceling a Request may not be straightforward or even technically feasible. The state transition of cancelations could be synchronous or asynchronous, and the way to claim a cancelation interfaces with the remaining Vault functionality in complex ways. + +A separate EIP should be developed to standardize behavior of cancelling a pending Request. Defining the cancel flow is still important for certain classes of use cases for which the fulfillment of a Request can take a considerable amount of time. + +### Request Implementation flexibility + +The standard is flexible enough to support a wide range of interaction patterns for Request flows. Pending Requests can be handled via internal accounting, globally or on per-user levels, use ERC-20 or [ERC-721](./eip-721.md), etc. + +Likewise yield on redemption Requests can accrue or not, and the exchange rate of any Request may be fixed or variable depending on the implementation. + +### Not allowing short-circuiting for claims + +If claims can short circuit, this creates ambiguity for integrators and complicates the interface with overloaded behavior on Request functions. + +Instead there can be router contracts which atomically check for Claimable amounts immediately upon Request. Frontends can dynamically route Requests in this way depending on the state and implementation of the Vault. + +### Operator function parameter on requestDeposit and requestRedeem + +To support flows where a smart contract manages the Request lifecycle on behalf of a user, the `operator` parameter is included in the `requestDeposit` and `requestRedeem` functions. This is not called `owner` because the `assets` or `shares` are not transferred from this account on Request submission, unlike the behaviour of an `owner` on `redeem`. It is also not called `receiver` because the `shares` or `assets` are not necessarily transferred on claiming the Request, this can be chosen by the operator when they call `deposit`, `mint`, `redeem`, or `withdraw`. + +### No Outputs for Request functions + +`requestDeposit` and `requestRedeem` may not have a known exchange rate that will happen when the Request becomes Claimed. Returning the corresponding `assets` or `shares` could not work in this case. + +The Requests could also output a timestamp representing the minimum amount of time expected for the Request to become Claimable, however not all Vaults will be able to return a reliable timestamp. + +### No Event for Claimable state + +The state transition of a Request from Pending to Claimable happens at the Vault implementation level and is not specified in the standard. Requests may be batched into the Claimable state, or the state may transition automatically after a timestamp has passed. It is impractical to require an event to emit after a Request becomes Claimable at the user or batch level. + +### Reversion of Preview Functions in Async Request Flows + +The preview functions do not take an address parameter, therefore the only way to discriminate discrepancies in exchange rate are via the `msg.sender`. However, this could lead to integration/implementation complexities where support contracts cannot determine the output of a claim on behalf of an `operator`. + +In addition, there is no on-chain benefit to previewing the Claim step as the only valid state transition is to Claim anyway. If the output of a Claim is undesirable for any reason, the calling contract can revert on the output of that function call. + +It reduces code and implementation complexity at little to no cost to simply mandate reversion for the preview functions of an async flow. + +### Mandated Support for [ERC-165](./eip-165.md) + +Implementing support for [ERC-165](./eip-165.md) is mandated because of the [optionality of flows](#optionality-of-flows). Integrations can use the `supportsInterface` method to check whether a vault is fully asynchronous, partially asynchronous, or fully synchronous, and use a single contract to support all cases. + +## Backwards Compatibility + +The interface is fully backwards compatible with [ERC-4626](./eip-4626.md). The specification of the `deposit`, `mint`, `redeem`, and `withdraw` methods is different as described in [Specification](#specification). + +## Reference Implementation + +WIP + +## Security Considerations + +The methods `pendingDepositRequest` and `pendingRedeemRequest` are estimates useful for display purposes, and can be outdated due to the asynchronicity. + +In general, asynchronicity concerns make state transitions in the Vault much more complex and vulnerable to security risks. Access control on Vault operations, clear documentation of state transitioning, and invariant checks should all be performed to mitigate these risks. + +It is worth highlighting again here that the Claim functions for any asynchronous flows MUST enforce that `msg.sender == operator/owner` to prevent theft of Claimable `assets` or `shares` + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From 58e7abd202a906e66296ff9612fbf9477392d623 Mon Sep 17 00:00:00 2001 From: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> Date: Thu, 26 Oct 2023 19:50:49 -0400 Subject: [PATCH 07/20] Re-enable eipw (#35) --- .github/workflows/ci.yml | 6 +- config/eipw.toml | 910 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 914 insertions(+), 2 deletions(-) create mode 100644 config/eipw.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 423bc26d726..f1d31a86ccc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,11 +111,13 @@ jobs: - name: Checkout EIP Repository uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - - uses: ethereum/eipw-action@b8de7ea9ad5cb842301e63898afb996c451c18cf + - uses: ethereum/eipw-action@6858f56d1d9e5cbe49a0afd85150669f6983ed20 id: eipw with: token: ${{ secrets.GITHUB_TOKEN }} - unchecked: 1, 5069, 5757 + unchecked: 1 + path: ERCS/ + options-file: config/eipw.toml markdownlint: name: Markdown Linter diff --git a/config/eipw.toml b/config/eipw.toml new file mode 100644 index 00000000000..b7acd15d8ae --- /dev/null +++ b/config/eipw.toml @@ -0,0 +1,910 @@ +[[modifiers]] +kind = "set-default-annotation" +name = "status" +value = "Stagnant" +annotation_type = "warning" + +[[modifiers]] +kind = "set-default-annotation" +name = "status" +value = "Withdrawn" +annotation_type = "warning" + +[lints.markdown-re-eip-dash] +kind = "markdown-regex" +mode = "excludes" +pattern = '(?i)eip[\s]*[0-9]+' +message = "proposals must be referenced with the form `EIP-N` (not `EIPN` or `EIP N`)" + +[lints.preamble-date-created] +kind = "preamble-date" +name = "created" + +[lints.preamble-re-description-eip-dash] +kind = "preamble-regex" +name = "description" +mode = "excludes" +pattern = '(?i)eip[\s]*[0-9]+' +message = "proposals must be referenced with the form `EIP-N` (not `EIPN` or `EIP N`)" + +[lints.preamble-re-description-colon] +kind = "preamble-regex" +name = "description" +mode = "excludes" +pattern = ":" +message = "preamble header `description` should not contain `:`" + +[lints.preamble-refs-description] +kind = "preamble-proposal-ref" +name = "description" + +[lints.preamble-enum-category] +kind = "preamble-one-of" +name = "category" +values = [ + "ERC", +] + +[lints.preamble-re-description] +kind = "preamble-regex" +name = "description" +mode = "excludes" +pattern = '(?i)standar\w*\b' +message = "preamble header `description` should not contain `standard` (or similar words.)" + +[lints.preamble-re-title-erc-dash] +kind = "preamble-regex" +name = "title" +mode = "excludes" +pattern = '(?i)erc[\s]*[0-9]+' +message = "proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`)" + +[lints.preamble-re-description-erc-dash] +kind = "preamble-regex" +name = "description" +mode = "excludes" +pattern = '(?i)erc[\s]*[0-9]+' +message = "proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`)" + +[lints.markdown-refs] +kind = "markdown-proposal-ref" +prefix = "erc-" +suffix = ".md" + +[lints.preamble-req-withdrawal-reason] +kind = "preamble-required-if-eq" +when = "status" +equals = "Withdrawn" +then = "withdrawal-reason" + +[lints.preamble-order] +kind = "preamble-order" +names = [ + "eip", + "title", + "description", + "author", + "discussions-to", + "status", + "last-call-deadline", + "type", + "category", + "created", + "requires", + "withdrawal-reason", +] + +[lints.preamble-requires-status] +kind = "preamble-requires-status" +requires = "requires" +status = "status" +flow = [ + [ + "Draft", + "Stagnant", +], + ["Review"], + ["Last Call"], + [ + "Final", + "Withdrawn", + "Living", +], +] + +[lints.markdown-order-section] +kind = "markdown-section-order" +sections = [ + "Abstract", + "Motivation", + "Specification", + "Rationale", + "Backwards Compatibility", + "Test Cases", + "Reference Implementation", + "Security Considerations", + "Copyright", +] + +[lints.markdown-rel-links] +kind = "markdown-relative-links" +exceptions = [ + '^https://(www\.)?github\.com/ethereum/consensus-specs/blob/[a-f0-9]{40}/.+$', + '^https://(www\.)?github\.com/ethereum/consensus-specs/commit/[a-f0-9]{40}$', + '^https://(www\.)?github\.com/ethereum/devp2p/blob/[0-9a-f]{40}/.+$', + '^https://(www\.)?github\.com/ethereum/devp2p/commit/[0-9a-f]{40}$', + '^https://(www\.)?github\.com/bitcoin/bips/blob/[0-9a-f]{40}/bip-[0-9]+\.mediawiki$', + '^https://www\.w3\.org/TR/[0-9][0-9][0-9][0-9]/.*$', + '^https://[a-z]*\.spec\.whatwg\.org/commit-snapshots/[0-9a-f]{40}/$', + '^https://www\.rfc-editor\.org/rfc/.*$', +] + +[lints.preamble-req-category] +kind = "preamble-required-if-eq" +when = "type" +equals = "Standards Track" +then = "category" + +[lints.preamble-eip] +kind = "preamble-uint" +name = "eip" + +[lints.markdown-json-cite] +kind = "markdown-json-schema" +language = "csl-json" +additional_schemas = [[ + "https://resource.citationstyles.org/schema/v1.0/input/json/csl-data.json", + """ +{ + \"description\": \"JSON schema for CSL input data\", + \"$schema\": \"http://json-schema.org/draft-07/schema#\", + \"$id\": \"https://resource.citationstyles.org/schema/v1.0/input/json/csl-data.json\", + \"type\": \"array\", + \"items\": { + \"type\": \"object\", + \"properties\": { + \"type\": { + \"type\": \"string\", + \"enum\": [ + \"article\", + \"article-journal\", + \"article-magazine\", + \"article-newspaper\", + \"bill\", + \"book\", + \"broadcast\", + \"chapter\", + \"classic\", + \"collection\", + \"dataset\", + \"document\", + \"entry\", + \"entry-dictionary\", + \"entry-encyclopedia\", + \"event\", + \"figure\", + \"graphic\", + \"hearing\", + \"interview\", + \"legal_case\", + \"legislation\", + \"manuscript\", + \"map\", + \"motion_picture\", + \"musical_score\", + \"pamphlet\", + \"paper-conference\", + \"patent\", + \"performance\", + \"periodical\", + \"personal_communication\", + \"post\", + \"post-weblog\", + \"regulation\", + \"report\", + \"review\", + \"review-book\", + \"software\", + \"song\", + \"speech\", + \"standard\", + \"thesis\", + \"treaty\", + \"webpage\" + ] + }, + \"id\": { + \"type\": [\"string\", \"number\"] + }, + \"citation-key\": { + \"type\": \"string\" + }, + \"categories\": { + \"type\": \"array\", + \"items\": { + \"type\": \"string\" + } + }, + \"language\": { + \"type\": \"string\" + }, + \"journalAbbreviation\": { + \"type\": \"string\" + }, + \"shortTitle\": { + \"type\": \"string\" + }, + \"author\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"chair\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"collection-editor\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"compiler\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"composer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"container-author\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"contributor\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"curator\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"director\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"editor\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"editorial-director\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"executive-producer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"guest\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"host\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"interviewer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"illustrator\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"narrator\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"organizer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"original-author\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"performer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"producer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"recipient\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"reviewed-author\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"script-writer\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"series-creator\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"translator\": { + \"type\": \"array\", + \"items\": { + \"$ref\": \"#/definitions/name-variable\" + } + }, + \"accessed\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"available-date\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"event-date\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"issued\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"original-date\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"submitted\": { + \"$ref\": \"#/definitions/date-variable\" + }, + \"abstract\": { + \"type\": \"string\" + }, + \"annote\": { + \"type\": \"string\" + }, + \"archive\": { + \"type\": \"string\" + }, + \"archive_collection\": { + \"type\": \"string\" + }, + \"archive_location\": { + \"type\": \"string\" + }, + \"archive-place\": { + \"type\": \"string\" + }, + \"authority\": { + \"type\": \"string\" + }, + \"call-number\": { + \"type\": \"string\" + }, + \"chapter-number\": { + \"type\": [\"string\", \"number\"] + }, + \"citation-number\": { + \"type\": [\"string\", \"number\"] + }, + \"citation-label\": { + \"type\": \"string\" + }, + \"collection-number\": { + \"type\": [\"string\", \"number\"] + }, + \"collection-title\": { + \"type\": \"string\" + }, + \"container-title\": { + \"type\": \"string\" + }, + \"container-title-short\": { + \"type\": \"string\" + }, + \"dimensions\": { + \"type\": \"string\" + }, + \"division\": { + \"type\": \"string\" + }, + \"DOI\": { + \"type\": \"string\" + }, + \"edition\": { + \"type\": [\"string\", \"number\"] + }, + \"event\": { + \"description\": \"[Deprecated - use 'event-title' instead. Will be removed in 1.1]\", + \"type\": \"string\" + }, + \"event-title\": { + \"type\": \"string\" + }, + \"event-place\": { + \"type\": \"string\" + }, + \"first-reference-note-number\": { + \"type\": [\"string\", \"number\"] + }, + \"genre\": { + \"type\": \"string\" + }, + \"ISBN\": { + \"type\": \"string\" + }, + \"ISSN\": { + \"type\": \"string\" + }, + \"issue\": { + \"type\": [\"string\", \"number\"] + }, + \"jurisdiction\": { + \"type\": \"string\" + }, + \"keyword\": { + \"type\": \"string\" + }, + \"locator\": { + \"type\": [\"string\", \"number\"] + }, + \"medium\": { + \"type\": \"string\" + }, + \"note\": { + \"type\": \"string\" + }, + \"number\": { + \"type\": [\"string\", \"number\"] + }, + \"number-of-pages\": { + \"type\": [\"string\", \"number\"] + }, + \"number-of-volumes\": { + \"type\": [\"string\", \"number\"] + }, + \"original-publisher\": { + \"type\": \"string\" + }, + \"original-publisher-place\": { + \"type\": \"string\" + }, + \"original-title\": { + \"type\": \"string\" + }, + \"page\": { + \"type\": [\"string\", \"number\"] + }, + \"page-first\": { + \"type\": [\"string\", \"number\"] + }, + \"part\": { + \"type\": [\"string\", \"number\"] + }, + \"part-title\": { + \"type\": \"string\" + }, + \"PMCID\": { + \"type\": \"string\" + }, + \"PMID\": { + \"type\": \"string\" + }, + \"printing\": { + \"type\": [\"string\", \"number\"] + }, + \"publisher\": { + \"type\": \"string\" + }, + \"publisher-place\": { + \"type\": \"string\" + }, + \"references\": { + \"type\": \"string\" + }, + \"reviewed-genre\": { + \"type\": \"string\" + }, + \"reviewed-title\": { + \"type\": \"string\" + }, + \"scale\": { + \"type\": \"string\" + }, + \"section\": { + \"type\": \"string\" + }, + \"source\": { + \"type\": \"string\" + }, + \"status\": { + \"type\": \"string\" + }, + \"supplement\": { + \"type\": [\"string\", \"number\"] + }, + \"title\": { + \"type\": \"string\" + }, + \"title-short\": { + \"type\": \"string\" + }, + \"URL\": { + \"type\": \"string\" + }, + \"version\": { + \"type\": \"string\" + }, + \"volume\": { + \"type\": [\"string\", \"number\"] + }, + \"volume-title\": { + \"type\": \"string\" + }, + \"volume-title-short\": { + \"type\": \"string\" + }, + \"year-suffix\": { + \"type\": \"string\" + }, + \"custom\": { + \"title\": \"Custom key-value pairs.\", + \"type\": \"object\", + \"description\": \"Used to store additional information that does not have a designated CSL JSON field. The custom field is preferred over the note field for storing custom data, particularly for storing key-value pairs, as the note field is used for user annotations in annotated bibliography styles.\", + \"examples\": [ + { + \"short_id\": \"xyz\", + \"other-ids\": [\"alternative-id\"] + }, + { + \"metadata-double-checked\": true + } + ] + } + }, + \"required\": [\"type\", \"id\"], + \"additionalProperties\": false + }, + \"definitions\": { + \"name-variable\": { + \"anyOf\": [ + { + \"properties\": { + \"family\": { + \"type\": \"string\" + }, + \"given\": { + \"type\": \"string\" + }, + \"dropping-particle\": { + \"type\": \"string\" + }, + \"non-dropping-particle\": { + \"type\": \"string\" + }, + \"suffix\": { + \"type\": \"string\" + }, + \"comma-suffix\": { + \"type\": [\"string\", \"number\", \"boolean\"] + }, + \"static-ordering\": { + \"type\": [\"string\", \"number\", \"boolean\"] + }, + \"literal\": { + \"type\": \"string\" + }, + \"parse-names\": { + \"type\": [\"string\", \"number\", \"boolean\"] + } + }, + \"additionalProperties\": false + } + ] + }, + \"date-variable\": { + \"title\": \"Date content model.\", + \"description\": \"The CSL input model supports two different date representations: an EDTF string (preferred), and a more structured alternative.\", + \"anyOf\": [ + { + \"properties\": { + \"date-parts\": { + \"type\": \"array\", + \"items\": { + \"type\": \"array\", + \"items\": { + \"type\": [\"string\", \"number\"] + }, + \"minItems\": 1, + \"maxItems\": 3 + }, + \"minItems\": 1, + \"maxItems\": 2 + }, + \"season\": { + \"type\": [\"string\", \"number\"] + }, + \"circa\": { + \"type\": [\"string\", \"number\", \"boolean\"] + }, + \"literal\": { + \"type\": \"string\" + }, + \"raw\": { + \"type\": \"string\" + } + }, + \"additionalProperties\": false + } + ] + } + } +} +""", +]] +schema = """ +{ + \"$id\": \"https://eips.ethereum.org/assets/eip-1/schema/json/citation.json\", + \"description\": \"Citation format for EIPs\", + \"$schema\": \"http://json-schema.org/draft-07/schema#\", + \"allOf\": [ + { + \"$ref\": \"https://resource.citationstyles.org/schema/v1.0/input/json/csl-data.json#/items\" + }, + { + \"required\": [ + \"DOI\", + \"URL\" + ], + \"properties\": { + \"URL\": { + \"format\": \"uri\" + }, + \"custom\": { + \"properties\": { + \"additional-urls\": { + \"type\": \"array\", + \"items\": { + \"format\": \"uri\" + } + } + } + } + } + } + ] +} +""" +help = "see https://github.com/ethereum/eipw/blob/master/eipw-lint/src/lints/markdown/json_schema/citation.json" + +[lints.preamble-no-dup] +kind = "preamble-no-duplicates" + +[lints.preamble-requires-ref-description] +kind = "preamble-require-referenced" +name = "description" +requires = "requires" + +[lints.preamble-re-title] +kind = "preamble-regex" +name = "title" +mode = "excludes" +pattern = '(?i)standar\w*\b' +message = "preamble header `title` should not contain `standard` (or similar words.)" + +[lints.preamble-re-title-eip-dash] +kind = "preamble-regex" +name = "title" +mode = "excludes" +pattern = '(?i)eip[\s]*[0-9]+' +message = "proposals must be referenced with the form `EIP-N` (not `EIPN` or `EIP N`)" + +[lints.preamble-date-last-call-deadline] +kind = "preamble-date" +name = "last-call-deadline" + +[lints.markdown-req-section] +kind = "markdown-section-required" +sections = [ + "Abstract", + "Specification", + "Rationale", + "Security Considerations", + "Copyright", +] + +[lints.markdown-link-status] +kind = "markdown-link-status" +status = "status" +flow = [ + [ + "Draft", + "Stagnant", +], + ["Review"], + ["Last Call"], + [ + "Final", + "Withdrawn", + "Living", +], +] + +[lints.preamble-re-title-colon] +kind = "preamble-regex" +name = "title" +mode = "excludes" +pattern = ":" +message = "preamble header `title` should not contain `:`" + +[lints.preamble-list-requires] +kind = "preamble-list" +name = "requires" + +[lints.preamble-len-description] +kind = "preamble-length" +name = "description" +min = 2 +max = 140 + +[lints.preamble-requires-ref-title] +kind = "preamble-require-referenced" +name = "title" +requires = "requires" + +[lints.markdown-html-comments] +kind = "markdown-html-comments" +name = "status" +warn_for = [ + "Draft", + "Withdrawn", +] + +[lints.preamble-author] +kind = "preamble-author" +name = "author" + +[lints.preamble-uint-requires] +kind = "preamble-uint-list" +name = "requires" + +[lints.preamble-len-requires] +kind = "preamble-length" +name = "requires" +min = 1 + +[lints.markdown-link-first] +kind = "markdown-link-first" +pattern = "(?i)(?:eip|erc)-[0-9]+" + +[lints.markdown-re-erc-dash] +kind = "markdown-regex" +mode = "excludes" +pattern = '(?i)erc[\s]*[0-9]+' +message = "proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`)" + +[lints.preamble-list-author] +kind = "preamble-list" +name = "author" + +[lints.preamble-enum-type] +kind = "preamble-one-of" +name = "type" +values = [ + "Standards Track", +] + +[lints.preamble-len-title] +kind = "preamble-length" +name = "title" +min = 2 +max = 44 + +[lints.preamble-discussions-to] +kind = "preamble-url" +name = "discussions-to" + +[lints.preamble-req] +kind = "preamble-required" +names = [ + "eip", + "title", + "description", + "author", + "discussions-to", + "status", + "type", + "created", +] + +[lints.preamble-re-discussions-to] +kind = "preamble-regex" +name = "discussions-to" +mode = "includes" +pattern = "^https://ethereum-magicians.org/t/[^/]+/[0-9]+$" +message = "preamble header `discussions-to` should point to a thread on ethereum-magicians.org" + +[lints.preamble-refs-title] +kind = "preamble-proposal-ref" +name = "title" + +[lints.preamble-enum-status] +kind = "preamble-one-of" +name = "status" +values = [ + "Draft", + "Review", + "Last Call", + "Final", + "Stagnant", + "Withdrawn", + "Living", +] + +[lints.preamble-trim] +kind = "preamble-trim" + +[lints.preamble-req-last-call-deadline] +kind = "preamble-required-if-eq" +when = "status" +equals = "Last Call" +then = "last-call-deadline" + +[lints.preamble-file-name] +kind = "preamble-file-name" +name = "eip" +prefix = "erc-" +suffix = ".md" + + From 0e6ad5c280ebf42b247b323ae04c942e0b5e3431 Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Thu, 26 Oct 2023 18:18:44 -0700 Subject: [PATCH 08/20] Updated 5164 to Last Call (#3) * Updated 5164 to Last Call * Bumped last call deadline by a few more days --- ERCS/erc-5164.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-5164.md b/ERCS/erc-5164.md index 2180c02f4bf..fde5b3f5622 100644 --- a/ERCS/erc-5164.md +++ b/ERCS/erc-5164.md @@ -4,7 +4,8 @@ title: Cross-Chain Execution description: Defines an interface that supports execution across EVM networks. author: Brendan Asselstine (@asselstine), Pierrick Turelier (@PierrickGT), Chris Whinfrey (@cwhinfrey) discussions-to: https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658 -status: Review +status: Last Call +last-call-deadline: 2023-11-15 type: Standards Track category: ERC created: 2022-06-14 From a5f4f4632e6df7915343fdbfa57ce4d270cf2562 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Fri, 27 Oct 2023 14:20:49 +1300 Subject: [PATCH 09/20] ERC-5189 updates (#4) * Update eip-5189.md Some cleanups * 5189 lint fixes * EIP 5189 validations * EIP-5189 Preample order * EIP-5189 Additional dependencies * EIP-5189 Add fee token * Add endorser calldata * EIP-5189 in draft * EIP-5189 Author update * Add missing reference block dep --------- Co-authored-by: Philippe Castonguay --- ERCS/erc-5189.md | 179 +++++++++++++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 59 deletions(-) diff --git a/ERCS/erc-5189.md b/ERCS/erc-5189.md index 786275fc930..0fabaf837f2 100644 --- a/ERCS/erc-5189.md +++ b/ERCS/erc-5189.md @@ -2,104 +2,138 @@ eip: 5189 title: Account Abstraction via Endorsed Operations description: An account abstraction proposal that avoids protocol changes while maintaining compatibility with existing smart contract wallets. -author: Agustín Aguilar (@agusx1211), Philippe Castonguay (@phabc) +author: Agustín Aguilar (@agusx1211), Philippe Castonguay (@phabc), Michael Standen (@ScreamingHawk) discussions-to: https://ethereum-magicians.org/t/erc-account-abstraction-via-endorsed-operations/9799 +status: Draft type: Standards Track category: ERC -status: Stagnant created: 2022-06-29 --- ## Abstract -This EIP proposes a form of account abstraction that ensures compatibility with existing smart contract wallets and provides flexibility for alternative designs while avoiding introducing changes to the consensus layer. Instead of defining a strict structure for meta-transactions, this proposal introduces the figure of `endorser` contracts. These smart contract instances are tasked with determining the quality of the submitted meta-transactions, thus safely helping bundlers determine if a meta-transaction should be kept in the mempool or not. Developers that intend to make their smart contract wallet compatible with this EIP must create and deploy an instance of an `endorser`; this instance must be seeded with a small amount of ETH to be burnt that incentivizes its good behavior. + +This EIP proposes a form of account abstraction (AA) that ensures compatibility with existing smart contract wallets and provides flexibility for alternative designs while avoiding introducing changes to the consensus layer. Instead of defining a strict structure for AA transactions, this proposal introduces the figure of `endorser` contracts. These smart contract instances are tasked with determining the quality of the submitted AA transactions, thus safely helping bundlers determine if a transaction should be kept in the mempool or not. Developers that intend to make their smart contract wallet compatible with this EIP must create and deploy an instance of an `endorser` or use an existing one compatible with their wallet. ## Motivation -This account abstraction proposal aims to implement a generalized system for executing meta-transactions while maintaining the following goals: + +This account abstraction proposal aims to implement a generalized system for executing AA transactions while maintaining the following goals: * **Achieve the primary goal of account abstraction:** allow users to use smart contract wallets containing arbitrary verification and execution logic instead of EOAs as their primary account. * **Decentralization:** -* * Allow any bundler to participate in the process of including meta-transactions. -* * Work with all activity happening over a public mempool without having to concentrate transactions on centralized relayers. -* * Define structures that help maintain a healthy mempool without risking its participants from getting flooded with invalid or malicious payloads. -* * Avoid trust assumptions between bundlers, developers, and wallets. + * Allow any bundler to participate in the process of including AA transactions. + * Work with all activity happening over a public mempool without having to concentrate transactions on centralized relayers. + * Define structures that help maintain a healthy mempool without risking its participants from getting flooded with invalid or malicious payloads. + * Avoid trust assumptions between bundlers, developers, and wallets. * **Support existing smart contract wallet implementations:** Work with all the smart contract wallets already deployed and active while avoiding forcing each wallet instance to be manually upgraded. * **Provide an unrestrictive framework:** Smart contract wallets are very different in design, limitations, and capabilities from one another; the proposal is designed to accommodate almost all possible variations. * **No overhead:** Smart contract wallets already have a cost overhead compared to EOA alternatives, the proposal does not worsen the current situation. * **Support other use cases:** -* * Privacy-preserving applications. -* * Atomic multi-operations (similar to EIP-3074). -* * Payment of transaction fees using ERC-20 tokens. -* * Scheduled execution of smart contracts without any user input. -* * Applications that require a generalistic relayer. + * Privacy-preserving applications. + * Atomic multi-operations (similar to [EIP-3074](./eip-3074.md)). + * Payment of transaction fees using [ERC-20](./eip-20.md) tokens. + * Scheduled execution of smart contracts without any user input. + * Applications that require a generalistic relayer. ## Specification -To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, meta-transactions are packed up in a struct called `Operation`, operations are structs composed by the following fields: -| Field | Type | Description | -|-------------------|---------|--------------------------------------------------------------------------------------------------------| -| entrypoint | address | contract address that must be called with `callData` to execute the `operation`. | -| callData | bytes | data that must be passed to the `entrypoint` call to execute the `operation`. | -| gasLimit | uint64 | minimum gasLimit that must be passed when executing the `operation`. | -| endorser | address | address of the endorser contract that should be used to validate the `operation`. | -| endorserGasLimit | uint64 | amount of gas that should be passed to the endorser when validating the `operation`. | -| maxFeePerGas | uint256 | max amount of basefee that the `operation` execution is expected to pay, (similar to EIP-1559 `max_fee_per_gas`) | -| priorityFeePerGas | uint256 | fixed amount of fees that the `operation` execution is expected to pay to the bundler (similar to EIP-1559 `max_priority_fee_per_gas`). | +To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, AA transactions are packed up in a struct called `Operation`, operations are structs composed by the following fields: + +| Field | Type | Description | +| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| entrypoint | address | contract address that must be called with `callData` to execute the `operation`. | +| callData | bytes | data that must be passed to the `entrypoint` call to execute the `operation`. | +| gasLimit | uint64 | minimum gasLimit that must be passed when executing the `operation`. | +| feeToken | address | contract address of the [ERC-20](./eip-20.md) token used to repay the bundler. _(`address(0)` for the native token)_. | +| endorser | address | address of the endorser contract that should be used to validate the `operation`. | +| endorserCallData | bytes | additional data that must be passed to the `endorser` when calling `isOperationReady()`. | +| endorserGasLimit | uint64 | amount of gas that should be passed to the endorser when validating the `operation`. | +| maxFeePerGas | uint256 | max amount of basefee that the `operation` execution is expected to pay. _(Similar to [EIP-1559](./eip-1559.md) `max_fee_per_gas`)_. | +| priorityFeePerGas | uint256 | fixed amount of fees that the `operation` execution is expected to pay to the bundler. _(Similar to [EIP-1559](./eip-1559.md) `max_priority_fee_per_gas`)_. | -These `Operation` objects can be sent to a dedicated operations mempool. A specialized class of actors called bundlers (either miners running special-purpose code, or just users that can relay transactions to miners) listen for operations on the mempool and execute these transactions. +These `Operation` objects can be sent to a dedicated operations mempool. A specialized class of actors called bundlers (either block producers running special-purpose code, or just users that can relay transactions to block producers) listen for operations on the mempool and execute these transactions. -Transactions are executed by calling the `entrypoint` with the provided `callData`. The `entrypoint` can be any contract, but most commonly it will be the wallet contract itself, alternatively it can be an intermediary utility that deploys the wallet and then performs the transaction. +Transactions are executed by calling the `entrypoint` with the provided `callData`. The `entrypoint` can be any contract, but most commonly it will be the wallet contract itself. Alternatively it can be an intermediary utility that deploys the wallet and then performs the transaction. + +### Endorser functionality -#### Endorser functionality Mempool participants need to be able to able to filter "good operations" (operations that pay the bundler the defined fee) from "bad operations" (operations that either miss payment or revert altogether). This categorization is facilitated by the `endorser`; the endorser must be a deployed smart contract that implements the following interface: ```solidity interface Endorser { + struct BlockDependency { + uint256 maxNumber; + uint256 maxTimestamp; + } + struct Dependency { address addr; bool balance; bool code; bool nonce; + bool allSlots; bytes32[] slots; } function isOperationReady( address _entrypoint, bytes calldata _data, + bytes calldata _endorserCallData, uint256 _gasLimit, uint256 _maxFeePerGas, uint256 _maxPriorityFeePerGas ) external view returns ( bool readiness, + BlockDependency memory blockDependency, Dependency[] memory dependencies ); } ``` -It should also be registered in the `EndorserRegistry` with a minimum amount of burned ETH (Mempool operators are free to accept operations from endorsers without any burn, but they would increase their risk exposing themselves to denial of service attacks). +Endorsers SHOULD be registered in the `EndorserRegistry` with a minimum amount of burned ETH (Mempool operators are free to accept operations from endorsers without any burned ETH, but they would increase their risk exposing themselves to denial of service attacks). When the `isOperationReady` method is called, the endorser must return this information: * **readiness:** when returning`true`, it means the transaction WILL be executed correctly and the bundler WILL be paid the offered gas fees (even if the underlying intent of the operation fails). +* **blockDependency:** maximum values for block values; once the block reaches these values, the `readiness` result MUST be re-evaluated. * **dependencies:** a comprehensive list of addresses and storage slots that must be monitored; any state change in these dependencies MUST trigger a re-evaluation of the operation's readiness. -The information provided by the endorser helps the mempool operator maintain a pool of "good" meta-transactions that behave correctly; it DOES NOT guarantee that such transactions will be able to be executed correctly. Bundlers must always simulate the result of the execution before including a transaction in a block. +The information provided by the endorser helps the mempool operator maintain a pool of "good" AA transactions that behave correctly; it DOES NOT guarantee that such transactions will be able to be executed correctly. Bundlers must always simulate the result of the execution before including a transaction in a block. They can alternatively monitor the dependencies for changes induced by other transactions in the mempool. + +For efficiency, additional information CAN be provided to the endorser with `_endorserCallData`. +If used, the endorser MUST validate that the provided `_endorserCallData` is valid and relevant to the other values provided. + +### Block Dependencies + +| Field | Type | Description | +| ------------ | ------- | ------------------------------------------------------------------- | +| maxNumber | uint256 | The maximum value of `block.number` that `readiness` applies to. | +| maxTimestamp | uint256 | The maximum value of `block.timestamp` that `readiness` applies to. | -#### Dependencies -| Field | Type | Description | -| -------- | -------- | -------- | -| addr | address | Contract address of the dependencies entry *(only one entry per address should be allowed)*. | -| balance | bool | `true` if the balance of `addr` should be considered a dependency of the `operation`. | -| code | bool | `true` if the code of `addr` should be considered a dependency of the `operation`. | -| nonce | bool | `true` if the nonce of `addr` should be considered a dependency of the `operation`. | -| slots | bytes32[] | List of all storage slots of `addr` that should be considered dependencies of `operation`. | +The `endorser` can use the `maxNumber` and `maxTimestamp` fields to limit the validity of the `readiness` result. This is useful for operations that are only valid for a certain period of time. + +Note that all values are **inclusive**. If the `endorser` determines the validity of the `operation` is indefinite, the `maxNumber` and `maxTimestamp` fields should be set to `type(uint256).max`. + +### Dependencies + +| Field | Type | Description | +| -------- | --------- | --------------------------------------------------------------------------------------------- | +| addr | address | Contract address of the dependencies entry. _(Only one entry per address should be allowed)_. | +| balance | bool | `true` if the balance of `addr` should be considered a dependency of the `operation`. | +| code | bool | `true` if the code of `addr` should be considered a dependency of the `operation`. | +| nonce | bool | `true` if the nonce of `addr` should be considered a dependency of the `operation`. | +| allSlots | bool | `true` if all storage slots of `addr` should be considered a dependency of the `operation` . | +| slots | bytes32[] | List of all storage slots of `addr` that should be considered dependencies of `operation`. | The `endorser` does not need to include all accessed storage slots on the dependencies list, it only needs to include storage slots that after a change may also result in a change of readiness. +Note that `allSlots` and `slots` are mutually exclusive, if `allSlots` is set to `true`, then `slots` MUST be an empty array. The `endorser` should prefer to use `slots` over `allSlots` whenever possible. + > E.g. A wallet may pay fees using funds stored as WETH. During `isValidOperation()`, the endorser contract may call the `balanceOf` method of the `WETH` contract to determine if the wallet has enough `WETH` balance. Even though the ETH balance of the WETH contract and the code of the WETH contract are being accessed, the endorser only cares about the user's WETH balance for this operation and hence does not include these as dependencies. ### Misbehavior detection + The `endorser` contracts may behave maliciously or erratically in the following ways: * (1) It may consider an operation `ready`, but when the operation is executed it transfers less than the agreed-upon fees to the bundler. @@ -110,25 +144,29 @@ The bundler must always discard and re-evaluate the readiness status after a cha If, when simulating the final inclusion of the operation, the bundler discovers that it does not result in correct payment (either because the transaction fails, or transferred amount is below the defined fee), then it should proceed to ban the `endorser` for one of the following reasons: -1) The `endorser` returns `isOperationReady == true` even though the `operation` is not healthy to be included in a block. -2) The `operation` changed readiness status from `true` to `false` while all dependencies remained unchanged. +1. The `endorser` returns `isOperationReady() == true` even though the `operation` is not healthy to be included in a block. +2. The `operation` changed readiness status from `true` to `false` while all dependencies remained unchanged. After an `endorser` is banned, the mempool operator should drop all `operations` related to such endorser. > Notice: The mempool operator could call one last time `isOperationReady` to determine if the `endorser` should be banned because `(1)` or `(2)`, but this step is not strictly necessary since both scenarios lead to the `endoser` being banned. -### Client behavior upon receiving an operation -When a client receives an `operation`, it must first run some basic sanity checks, namely that: +### Bundler behavior upon receiving an operation + +Bundlers can add their own rules for how to ensure the successful relaying of AA transactions and for getting paid for relaying these transactions. However, we propose here a baseline specification that should be sufficient. + +When a bundler receives an `operation`, it SHOULD perform these sanity checks: * The `endorserGasLimit` is sufficiently low (<= `MAX_ENDORSER_GAS`). * The endorser (i) is registered and has enough burn (>= `MIN_ENDORSER_BURN`), and (ii) it has not been internally flagged as banned. * The `gasLimit` is at least the cost of a `CALL` with a non-zero value. -* The `maxFeePerGas` and `priorityPerGas` are above a configurable minimum value the client is willing to accept. +* The `feeToken` is `address(0)` or a known [ERC-20](./eip-20.md) token that the bundler is willing to accept. +* The `maxFeePerGas` and `priorityPerGas` are above a configurable minimum value the bundler is willing to accept. * If another operation exists in the mempool with the exact same dependency set AND the same endorser address, the `maxFeePerGas` and `priorityFeePerGas` of the newly received operation MUST be 12% higher than the one on the mempool to replace it. (Similar with how EOA with same nonce work) -If the `operation` passes these checks, then the client MUST call `isOperationReady()` on the `endorser`. If the endorser considers the operation ready, then the client MUST add the operation to the mempool. Otherwise, the operation MUST discarded. +If the `operation` passes these checks, then the bundler MUST call `isOperationReady()` on the `endorser`. If the endorser considers the operation ready, then the client MUST add the operation to the mempool. Otherwise, the operation MUST be dropped. -The `endorser` result MUST be invalidated and its readiness be re-evaluated if any of the values of the provided dependencies change. If the operation readiness changes to `false`, the operation MUST be discarded. +The `endorser` result SHOULD be invalidated and its readiness SHOULD be re-evaluated if any of the values of the provided dependencies change. If the operation readiness changes to `false`, the operation MUST be discarded. Before including the operation in a block, a last simulation MUST be performed, this time without calling the `endorser`, but by constructing the block and probing the result. All transactions in the block listed **before** the operation must be simulated and the endorser must be queried again there for readiness in-case some dependencies changed. @@ -138,42 +176,46 @@ Additional events that must invalidate the readiness are: * A transaction or operation modifies the same storage slots (as the dependencies) is queued before the given operation. -#### Optional rules +### Optional rules + Mempool clients could implement additional rules to further protect against maliciously constructed transactions. + * Limit the size of accepted dependencies to `MAX_OPERATION_DEPENDENCIES`, dropping operations that cross the boundary. * Limit the number of times an operation may trigger a re-evaluation to `MAX_OPERATION_REEVALS`, dropping operations that cross the boundary. * Limit the number of operations in the mempool that depend on the same dependency slots. If these rules are widely adopted, wallet developers should keep usage of dependencies to the lowest possible levels. -#### Evaluation -To evaluate an `operation`, the client must call the `isOperationReady` method, with a `gasLimit` above or equal to `endorserGasLimit`. +### Evaluation + +To evaluate an `operation`, the bundler must call the `isOperationReady()` method, with a `gasLimit` above or equal to `endorserGasLimit`. -If the call fails, or the `endorser` returns `ready == false`, then the operation must be dropped from the mempool. +If the call fails, or the `endorser` returns `readiness == false`, then the operation must be dropped from the mempool. -If the call succeeds and returns `ready == true`, then the operation can be kept in the mempool and used when constructing the next block. The client must keep track of all fields returned as `dependencies`. If any of these register a change, then readiness should be reevaluated. +If the call succeeds and returns `readiness == true`, then the operation can be kept in the mempool and used when constructing a block. +### After operation inclusion -#### After operation inclusion There is no limit in-place that defines that an operation can only be executed once. -The bundler MUST NOT drop an `operation` after successfully including such operation in a block, the `operation` must remain in the mempool and a last `isOperationReady` call must be performed. +The bundler MUST NOT drop an `operation` after successfully including such operation in a block, the `operation` must remain in the mempool and a last `isOperationReady()` call must be performed. If the `endorser` still returns `readiness == true` (after inclusion) then the operation SHOULD be treated as any other healthy operation, and thus it COULD be kept in the mempool. ### Endorser registry -The endorser registry serves as a place to register the burn of each endorser, anyone can increase the burn of any endorser by calling the `addBurn` function. + +The endorser registry serves as a place to register the burn of each endorser, anyone can increase the burn of any endorser by calling the `addBurn()` function. All burn is effectively locked forever; slashing can't be reliably proved on-chain without protocol alterations, so it remains a virtual event on which mempool operators will ignore the deposited ETH. #### Implementation + (EXAMPLE) ```solidity // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.15; - contract EndorserRegistry { event Burned( address indexed _endorser, @@ -196,7 +238,10 @@ contract EndorserRegistry { ``` ## Rationale -The main challenge with a purely smart contract wallet-based account abstraction system is DoS safety: how can a bundler that includes an operation make sure that it will pay fees without executing the entire operation? + +### Griefing protection + +The main challenge with a purely smart contract wallet-based account abstraction system is DoS safety: how can a bundler that includes an operation make sure it will be paid without executing the entire operation? Bundlers could execute the entire operation to determine if it is healthy or not, but this operation may be expensive and complex for the following reasons: @@ -210,16 +255,32 @@ In effect, we move the responsibility from the wallet to the wallet developer; t Additionally, the specification is kept as simple as possible as enforcing a highly structured behavior and schema for smart contract wallet transactions may stagnate the adoption of more innovative types of wallets and the adoption of a shared standard among them. -#### Differences with alternative proposals -1) This proposal does not require monitoring for forbidden opcodes or storage access boundaries. Wallets have complete freedom to use any EVM capabilities during validation and execution. -2) This proposal does not specify any replay protection logic since all existing smart contract wallets already have their own, and designs can vary among them. Nonces can be communicated to the bundler using a `dependency`. -3) This proposal does not specify a pre-deployment logic because it can be handled directly by the entrypoint. -4) This proposal does not require wallets to accept `execution` transactions from a trusted entrypoint contract, reducing overhead and allowing existing wallets to be compatible with the proposal. -5) This proposal does not distinguish between `execution` and `signature` payloads, this distinction remains implementation-specific. +### Burned ETH + +Anyone can deploy a endorser contract and wallet clients are the one providing which endorser contract should be used for the given transaction. Instead of having each bundler rely on an off-chain registry that they need to maintain, the endorser registry can be called to see if the requested endorser contract is present and how much ETH was burned for it. Bundlers can then decide a minimum treshshold for how much ETH burnt is required for an endorser contract to be accepted. Bundlers are also free to support endorsers contract that are not part of the registry or are part of it but have no ETH burned associated. +### Minimum overhead + +Since the validation of an AA transactions is done off-chain by the bundler rather than at execution time, there is no additional gas fee overhead for executing transactions. The bundler bears the risk rather than all users having to pay for that security. + +### Differences with alternative proposals + +1. This proposal does not require monitoring for forbidden opcodes or storage access boundaries. Wallets have complete freedom to use any EVM capabilities during validation and execution. +2. This proposal does not specify any replay protection logic since all existing smart contract wallets already have their own, and designs can vary among them. Nonces can be communicated to the bundler using a `dependency`. +3. This proposal does not specify a pre-deployment logic because it can be handled directly by the entrypoint. +4. This proposal does not require wallets to accept `execution` transactions from a trusted entrypoint contract, reducing overhead and allowing existing wallets to be compatible with the proposal. +5. This proposal does not distinguish between `execution` and `signature` payloads, this distinction remains implementation-specific. ## Backwards Compatibility + This EIP does not change he consensus layer, nor does impose changes on existing smart contract wallets, so there are no backwards compatibility issues. +## Security Considerations + +This EIP does not make changes to on-chain interactions. Endorsers are explicitly for off-chain validations. + +Bundlers are responsible for managing their own security and for ensuring that they are paid for the transactions they include in blocks. + ## Copyright + Copyright and related rights waived via [CC0](../LICENSE.md). From 64e9010d1e62e5bfebe7ed62a5bac4a831c2658b Mon Sep 17 00:00:00 2001 From: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> Date: Fri, 27 Oct 2023 11:27:26 -0400 Subject: [PATCH 10/20] Missed a few lints still using eip- (#36) --- .github/workflows/ci.yml | 2 +- config/eipw.toml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1d31a86ccc..0a3b013e495 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,7 @@ jobs: - name: Checkout EIP Repository uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - - uses: ethereum/eipw-action@6858f56d1d9e5cbe49a0afd85150669f6983ed20 + - uses: ethereum/eipw-action@6785fa283773db4819cb0abf17a185a1d9b6eb9f id: eipw with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/config/eipw.toml b/config/eipw.toml index b7acd15d8ae..f6813a49373 100644 --- a/config/eipw.toml +++ b/config/eipw.toml @@ -37,6 +37,8 @@ message = "preamble header `description` should not contain `:`" [lints.preamble-refs-description] kind = "preamble-proposal-ref" name = "description" +prefix = "erc-" +suffix = ".md" [lints.preamble-enum-category] kind = "preamble-one-of" @@ -95,6 +97,8 @@ names = [ ] [lints.preamble-requires-status] +prefix = "erc-" +suffix = ".md" kind = "preamble-requires-status" requires = "requires" status = "status" @@ -765,6 +769,8 @@ sections = [ ] [lints.markdown-link-status] +prefix = "erc-" +suffix = ".md" kind = "markdown-link-status" status = "status" flow = [ @@ -878,6 +884,8 @@ message = "preamble header `discussions-to` should point to a thread on ethereum [lints.preamble-refs-title] kind = "preamble-proposal-ref" name = "title" +prefix = "erc-" +suffix = ".md" [lints.preamble-enum-status] kind = "preamble-one-of" From 7666a2a96b9a61dd189008af3025625cd37cdf23 Mon Sep 17 00:00:00 2001 From: Gavin John Date: Fri, 27 Oct 2023 14:53:17 -0500 Subject: [PATCH 11/20] Set eip-review-bot's ref to dist --- .github/workflows/auto-review-bot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-review-bot.yml b/.github/workflows/auto-review-bot.yml index ff14c259c20..600268097b1 100644 --- a/.github/workflows/auto-review-bot.yml +++ b/.github/workflows/auto-review-bot.yml @@ -24,7 +24,7 @@ jobs: - name: Auto Review Bot id: auto-review-bot - uses: ethereum/eip-review-bot@3e9905fcb72cf81ae9ed732df429c28b17e155b1 + uses: ethereum/eip-review-bot@dist continue-on-error: true with: token: ${{ secrets.TOKEN }} From ffb313b128a14dced24fa6c4228c8c0fffd1d1b1 Mon Sep 17 00:00:00 2001 From: EIP Review Bot <128646734+eip-review-bot@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:57:23 -0500 Subject: [PATCH 12/20] Usurp @eth-bot --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 21f1400916a..5bb9268aae1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @eth-bot +* @eip-review-bot From 2e174159594cf11fae3b742442a544dd0bea190d Mon Sep 17 00:00:00 2001 From: Gavin John Date: Fri, 27 Oct 2023 15:21:03 -0500 Subject: [PATCH 13/20] Better anti-bot recursion --- .github/workflows/auto-review-trigger.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-review-trigger.yml b/.github/workflows/auto-review-trigger.yml index 45b815e390d..d11fb61ac6d 100644 --- a/.github/workflows/auto-review-trigger.yml +++ b/.github/workflows/auto-review-trigger.yml @@ -21,15 +21,19 @@ jobs: runs-on: ubuntu-latest name: Trigger steps: + - name: Stop Bot Recursion + run: exit 1 + if: (endsWith(github.event.sender.login, '-bot') || endsWith(github.event.sender.login, '[bot]')) && github.event.sender.login != 'renovate[bot]' + - name: Write PR Number - PR Target run: echo $PR_NUMBER > pr-number.txt - if: github.event_name == 'pull_request_target' && ((!endsWith(github.event.sender.login, '-bot') && !endsWith(github.event.sender.login, '[bot]')) || github.event.sender.login == 'renovate[bot]') + if: github.event_name == 'pull_request_target' env: PR_NUMBER: ${{ github.event.number }} - name: Write PR Number - PR Review run: echo $PR_NUMBER > pr-number.txt - if: github.event_name == 'pull_request_review' && !endsWith(github.event.sender.login, '-bot') && !endsWith(github.event.sender.login, '[bot]') + if: github.event_name == 'pull_request_review' env: PR_NUMBER: ${{ github.event.pull_request.number }} From 0c49aa950317a7d7423b95eaf7263cc73ecaeab7 Mon Sep 17 00:00:00 2001 From: Gavin John Date: Fri, 27 Oct 2023 15:58:22 -0500 Subject: [PATCH 14/20] Scuffed HTMLProofer (#55) --- .github/workflows/ci.yml | 41 ++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a3b013e495..4d006255811 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,15 +41,40 @@ jobs: runs-on: ubuntu-20.04 steps: - - name: Checkout EIP Repository - uses: actions/checkout@47fbe2df0ad0e27efb67a70beac3555f192b062f - - - name: Install Ruby - uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf + - name: Checkout EIPs + uses: actions/checkout@v4 with: - ruby-version: 3.1.4 # 3.2 fails, see https://github.com/github/pages-gem/issues/879 - bundler-cache: true - + repository: ethereum/EIPs + path: '' + - name: Checkout ERCs + uses: actions/checkout@v4 + with: + repository: ethereum/ERCs + path: ERCs + - name: Merge Repos + run: | + mkdir -p $GITHUB_WORKSPACE/ERCs/ERCS + mkdir -p $GITHUB_WORKSPACE/ERCs/EIPS + cp -rp $GITHUB_WORKSPACE/ERCs/ERCS/. $GITHUB_WORKSPACE/EIPS + cp -rp $GITHUB_WORKSPACE/ERCs/EIPS/. $GITHUB_WORKSPACE/EIPS + cp -rp $GITHUB_WORKSPACE/ERCs/assets/. $GITHUB_WORKSPACE/assets + cd $GITHUB_WORKSPACE/EIPS + find . -name "erc-*.md" -type f -exec sh -c 'echo mv "$1" "$(echo "$1" | sed s/erc/eip/)"' _ {} \; | sh + cd $GITHUB_WORKSPACE/assets + find . -name "erc-*" -type d -exec sh -c 'echo mv "$1" "$(echo "$1" | sed s/erc/eip/)"' _ {} \; | sh + cd $GITHUB_WORKSPACE + rm -rf ERCs + - name: Setup Ruby + uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 + with: + ruby-version: '3.1' # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + cache-version: 0 # Increment this number if you need to re-download cached gems + - name: Build with Jekyll + run: bundle exec jekyll build + env: + JEKYLL_ENV: production + - name: Build Website run: | bundle exec jekyll doctor From 7ed1fbacbd82e85ac2bfffc114ece73656e611a7 Mon Sep 17 00:00:00 2001 From: Jayden Windle Date: Sat, 28 Oct 2023 17:06:24 -0700 Subject: [PATCH 15/20] Update ERC-6551: Registry and execution interface changes Merged by EIP-Bot. --- ERCS/erc-6551.md | 397 +++++++++++++++++++++++++++++------------------ 1 file changed, 247 insertions(+), 150 deletions(-) diff --git a/ERCS/erc-6551.md b/ERCS/erc-6551.md index 7bf3d13f8fb..830723cbc25 100644 --- a/ERCS/erc-6551.md +++ b/ERCS/erc-6551.md @@ -2,13 +2,13 @@ eip: 6551 title: Non-fungible Token Bound Accounts description: An interface and registry for smart contract accounts owned by non-fungible tokens -author: Jayden Windle (@jaydenwindle), Benny Giang , Steve Jang, Druzy Downs (@druzydowns), Raymond Huynh (@huynhr), Alanah Lam , Wilkins Chung (@wwhchung) , Paul Sullivan (@sullivph) , Auryn Macmillan (@auryn-macmillan), Jan-Felix Schwarz (@jfschwarz), Anton Bukov (@k06a), Mikhail Melnik (@ZumZoom), Josh Weintraub (@jhweintraub) , Rob Montgomery (@RobAnon) +author: Jayden Windle (@jaydenwindle), Benny Giang , Steve Jang, Druzy Downs (@druzydowns), Raymond Huynh (@huynhr), Alanah Lam , Wilkins Chung (@wwhchung) , Paul Sullivan (@sullivph) , Auryn Macmillan (@auryn-macmillan), Jan-Felix Schwarz (@jfschwarz), Anton Bukov (@k06a), Mikhail Melnik (@ZumZoom), Josh Weintraub (@jhweintraub) , Rob Montgomery (@RobAnon) , vectorized (@vectorized) discussions-to: https://ethereum-magicians.org/t/non-fungible-token-bound-accounts/13030 status: Review type: Standards Track category: ERC created: 2023-02-23 -requires: 155, 165, 721, 1167, 1271 +requires: 165, 721, 1167, 1271 --- ## Abstract @@ -50,20 +50,32 @@ The following diagram illustrates the relationship between NFTs, NFT holders, to ### Registry -The registry serves as a single entry point for all token bound account address queries. It has two functions: +The registry is a singleton contract that serves as the entry point for all token bound account address queries. It has two functions: - `createAccount` - creates the token bound account for an NFT given an `implementation` address - `account` - computes the token bound account address for an NFT given an `implementation` address -The registry SHALL deploy each token bound account as an [ERC-1167](./eip-1167.md) minimal proxy with immutable constant data appended to the bytecode. +The registry is permissionless, immutable, and has no owner. The complete source code for the registry can be found in the [Registry Implementation](#registry-implementation) section. The registry MUST be deployed at address `0x000000006551c19487814612e58FE06813775758` using Nick's Factory (`0x4e59b44847b379578588920cA78FbF26c0B4956C`) with salt `0x0000000000000000000000000000000000000000fd8eb4e1dca713016c518e31`. -The deployed bytecode of each token bound account SHALL have the following structure: +The registry can be deployed to any EVM-compatible chain using the following transaction: + +``` +{ + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "value": "0x0", + "data": "0x0000000000000000000000000000000000000000fd8eb4e1dca713016c518e31608060405234801561001057600080fd5b5061023b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063246a00211461003b5780638a54c52f1461006a575b600080fd5b61004e6100493660046101b7565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b61004e6100783660046101b7565b6100e1565b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b60015284601552605560002060601b60601c60005260206000f35b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b600152846015526055600020803b61018b578560b760556000f580610157576320188a596000526004601cfd5b80606c52508284887f79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf887226060606ca46020606cf35b8060601b60601c60005260206000f35b80356001600160a01b03811681146101b257600080fd5b919050565b600080600080600060a086880312156101cf57600080fd5b6101d88661019b565b945060208601359350604086013592506101f46060870161019b565b94979396509194608001359291505056fea2646970667358221220ea2fe53af507453c64dd7c1db05549fa47a298dfb825d6d11e1689856135f16764736f6c63430008110033", +} +``` + +The registry MUST deploy each token bound account as an [ERC-1167](./eip-1167.md) minimal proxy with immutable constant data appended to the bytecode. + +The deployed bytecode of each token bound account MUST have the following structure: ``` ERC-1167 Header (10 bytes) (20 bytes) ERC-1167 Footer (15 bytes) - (32 bytes) + (32 bytes) (32 bytes) (32 bytes) (32 bytes) @@ -75,67 +87,66 @@ For example, the token bound account with implementation address `0xbebebebebebe 363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcf000000000000000000000000000000000000000000000000000000000000007b ``` -Each token bound account proxy SHALL delegate execution to a contract that implements the `IERC6551Account` interface. +Each token bound account proxy MUST delegate execution to a contract that implements the `IERC6551Account` interface. -The registry contract is permissionless, immutable, and has no owner. The complete source code for the registry can be found in the [Registry Implementation](#registry-implementation) section below. The registry SHALL be deployed at address `TBD` using Nick's Factory (`0x4e59b44847b379578588920cA78FbF26c0B4956C`) with salt `0x6551655165516551655165516551655165516551655165516551655165516551`. +The registry MUST deploy all token bound accounts using the `create2` opcode so that each account address is deterministic. Each token bound account address SHALL be derived from the unique combination of its implementation address, token contract address, token ID, chain ID, and salt. -The registry SHALL deploy all token bound accounts using the `create2` opcode so that each account address is deterministic. Each token bound account address SHALL be derived from the unique combination of its implementation address, token contract address, token ID, [EIP-155](./eip-155.md) chain ID, and salt. - -The registry SHALL implement the following interface: +The registry MUST implement the following interface: ```solidity interface IERC6551Registry { /** - * @dev The registry SHALL emit the AccountCreated event upon successful account creation + * @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation. */ - event AccountCreated( + event ERC6551AccountCreated( address account, address indexed implementation, + bytes32 salt, uint256 chainId, address indexed tokenContract, - uint256 indexed tokenId, - uint256 salt + uint256 indexed tokenId ); + /** + * @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails. + */ + error AccountCreationFailed(); + /** * @dev Creates a token bound account for a non-fungible token. * * If account has already been created, returns the account address without calling create2. * - * If initData is not empty and account has not yet been created, calls account with - * provided initData after creation. - * - * Emits AccountCreated event. + * Emits ERC6551AccountCreated event. * - * @return the address of the account + * @return account The address of the token bound account */ function createAccount( address implementation, + bytes32 salt, uint256 chainId, address tokenContract, - uint256 tokenId, - uint256 salt, - bytes calldata initData - ) external returns (address); + uint256 tokenId + ) external returns (address account); /** - * @dev Returns the computed token bound account address for a non-fungible token + * @dev Returns the computed token bound account address for a non-fungible token. * - * @return The computed address of the token bound account + * @return account The address of the token bound account */ function account( address implementation, + bytes32 salt, uint256 chainId, address tokenContract, - uint256 tokenId, - uint256 salt - ) external view returns (address); + uint256 tokenId + ) external view returns (address account); } ``` ### Account Interface -All token bound accounts SHOULD be created via the registry. +All token bound accounts SHOULD be created via the singleton registry. All token bound account implementations MUST implement [ERC-165](./eip-165.md) interface detection. @@ -147,7 +158,7 @@ All token bound account implementations MUST implement the following interface: /// @dev the ERC-165 identifier for this interface is `0x6faff5f1` interface IERC6551Account { /** - * @dev Allows the account to receive Ether + * @dev Allows the account to receive Ether. * * Accounts MUST implement a `receive` function. * @@ -157,41 +168,37 @@ interface IERC6551Account { receive() external payable; /** - * @dev Returns the identifier of the non-fungible token which owns the account + * @dev Returns the identifier of the non-fungible token which owns the account. * - * The return value of this function MUST be constant - it MUST NOT change - * over time + * The return value of this function MUST be constant - it MUST NOT change over time. * - * @return chainId The EIP-155 ID of the chain the token exists on + * @return chainId The chain ID of the chain the token exists on * @return tokenContract The contract address of the token * @return tokenId The ID of the token */ function token() external view - returns ( - uint256 chainId, - address tokenContract, - uint256 tokenId - ); + returns (uint256 chainId, address tokenContract, uint256 tokenId); /** - * @dev Returns a value that SHOULD be modified each time the account changes state + * @dev Returns a value that SHOULD be modified each time the account changes state. * * @return The current account state */ function state() external view returns (uint256); /** - * @dev Returns a magic value indicating whether a given signer is authorized to act on behalf of the account + * @dev Returns a magic value indicating whether a given signer is authorized to act on behalf + * of the account. * - * MUST return the bytes4 magic value 0x523e3260 if the given signer is valid + * MUST return the bytes4 magic value 0x523e3260 if the given signer is valid. * - * By default, the holder of the non-fungible token the account is bound to MUST be considered a valid - * signer + * By default, the holder of the non-fungible token the account is bound to MUST be considered + * a valid signer. * * Accounts MAY implement additional authorization logic which invalidates the holder as a - * signer or grants signing permissions to other non-holder accounts + * signer or grants signing permissions to other non-holder accounts. * * @param signer The address to check signing authorization for * @param context Additional data used to determine whether the signer is valid @@ -202,6 +209,7 @@ interface IERC6551Account { view returns (bytes4 magicValue); } + ``` ### Execution Interface @@ -211,17 +219,12 @@ All token bound accounts MUST implement an execution interface which allows vali Token bound accounts MAY support the following execution interface: ```solidity -/// @dev the ERC-165 identifier for this interface is `0x74420f4c` +/// @dev the ERC-165 identifier for this interface is `0x51945447` interface IERC6551Executable { /** - * @dev Executes a low-level operation if the caller is a valid signer on the account - * - * Reverts and bubbles up error if operation fails + * @dev Executes a low-level operation if the caller is a valid signer on the account. * - * @param to The target address of the operation - * @param value The Ether value to be sent to the target - * @param data The encoded operation calldata - * @param operation A value indicating the type of operation to perform + * Reverts and bubbles up error if operation fails. * * Accounts implementing this interface MUST accept the following operation parameter values: * - 0 = CALL @@ -230,16 +233,18 @@ interface IERC6551Executable { * - 3 = CREATE2 * * Accounts implementing this interface MAY support additional operations or restrict a signer's - * ability to execute certain operations + * ability to execute certain operations. * + * @param to The target address of the operation + * @param value The Ether value to be sent to the target + * @param data The encoded operation calldata + * @param operation A value indicating the type of operation to perform * @return The result of the operation */ - function execute( - address to, - uint256 value, - bytes calldata data, - uint256 operation - ) external payable returns (bytes memory); + function execute(address to, uint256 value, bytes calldata data, uint8 operation) + external + payable + returns (bytes memory); } ``` @@ -295,9 +300,9 @@ Finally, this proposal seeks to grant NFTs the ability to act as agents on-chain ERC-1167 minimal proxies are well supported by existing infrastructure and are a common smart contract pattern. This proposal deploys each token bound account using a custom ERC-1167 proxy implementation that stores the salt, chain id, token contract address, and token ID as ABI-encoded constant data appended to the contract bytecode. This allows token bound account implementations to easily query this data while ensuring it remains constant. This approach was taken to maximize compatibility with existing infrastructure while also giving smart contract developers full flexibility when creating custom token bound account implementations. -### EIP-155 Support +### Chain Identifier -This proposal uses an EIP-155 chain ID to identify each NFT along with its contract address and token ID. Token identifiers are globally unique on a single Ethereum chain, but may not be unique across multiple Ethereum chains. +This proposal uses the chain ID to identify each NFT along with its contract address and token ID. Token identifiers are globally unique on a single Ethereum chain, but may not be unique across multiple Ethereum chains. ## Backwards Compatibility @@ -319,17 +324,40 @@ import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/interfaces/IERC1271.sol"; import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; -contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Executable { +interface IERC6551Account { + receive() external payable; + + function token() + external + view + returns (uint256 chainId, address tokenContract, uint256 tokenId); + + function state() external view returns (uint256); + + function isValidSigner(address signer, bytes calldata context) + external + view + returns (bytes4 magicValue); +} + +interface IERC6551Executable { + function execute(address to, uint256 value, bytes calldata data, uint8 operation) + external + payable + returns (bytes memory); +} + +contract ERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Executable { uint256 public state; receive() external payable {} - function execute( - address to, - uint256 value, - bytes calldata data, - uint256 operation - ) external payable returns (bytes memory result) { + function execute(address to, uint256 value, bytes calldata data, uint8 operation) + external + payable + virtual + returns (bytes memory result) + { require(_isValidSigner(msg.sender), "Invalid signer"); require(operation == 0, "Only call operations are supported"); @@ -345,7 +373,7 @@ contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Ex } } - function isValidSigner(address signer, bytes calldata) external view returns (bytes4) { + function isValidSigner(address signer, bytes calldata) external view virtual returns (bytes4) { if (_isValidSigner(signer)) { return IERC6551Account.isValidSigner.selector; } @@ -356,6 +384,7 @@ contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Ex function isValidSignature(bytes32 hash, bytes memory signature) external view + virtual returns (bytes4 magicValue) { bool isValid = SignatureChecker.isValidSignatureNow(owner(), hash, signature); @@ -364,24 +393,16 @@ contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Ex return IERC1271.isValidSignature.selector; } - return ""; + return bytes4(0); } - function supportsInterface(bytes4 interfaceId) external pure returns (bool) { - return (interfaceId == type(IERC165).interfaceId || - interfaceId == type(IERC6551Account).interfaceId || - interfaceId == type(IERC6551Executable).interfaceId); + function supportsInterface(bytes4 interfaceId) external pure virtual returns (bool) { + return interfaceId == type(IERC165).interfaceId + || interfaceId == type(IERC6551Account).interfaceId + || interfaceId == type(IERC6551Executable).interfaceId; } - function token() - public - view - returns ( - uint256, - address, - uint256 - ) - { + function token() public view virtual returns (uint256, address, uint256) { bytes memory footer = new bytes(0x60); assembly { @@ -391,14 +412,14 @@ contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Ex return abi.decode(footer, (uint256, address, uint256)); } - function owner() public view returns (address) { + function owner() public view virtual returns (address) { (uint256 chainId, address tokenContract, uint256 tokenId) = token(); if (chainId != block.chainid) return address(0); return IERC721(tokenContract).ownerOf(tokenId); } - function _isValidSigner(address signer) internal view returns (bool) { + function _isValidSigner(address signer) internal view virtual returns (bool) { return signer == owner(); } } @@ -407,90 +428,166 @@ contract ExampleERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Ex ### Registry Implementation ```solidity -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; -import "@openzeppelin/contracts/utils/Create2.sol"; - -library ERC6551BytecodeLib { - function getCreationCode( - address implementation_, - uint256 chainId_, - address tokenContract_, - uint256 tokenId_, - uint256 salt_ - ) internal pure returns (bytes memory) { - return - abi.encodePacked( - hex"3d60ad80600a3d3981f3363d3d373d3d3d363d73", - implementation_, - hex"5af43d82803e903d91602b57fd5bf3", - abi.encode(salt_, chainId_, tokenContract_, tokenId_) - ); - } -} +interface IERC6551Registry { + /** + * @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation. + */ + event ERC6551AccountCreated( + address account, + address indexed implementation, + bytes32 salt, + uint256 chainId, + address indexed tokenContract, + uint256 indexed tokenId + ); -contract ERC6551Registry is IERC6551Registry { + /** + * @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails. + */ error AccountCreationFailed(); + /** + * @dev Creates a token bound account for a non-fungible token. + * + * If account has already been created, returns the account address without calling create2. + * + * Emits ERC6551AccountCreated event. + * + * @return account The address of the token bound account + */ function createAccount( address implementation, + bytes32 salt, uint256 chainId, address tokenContract, - uint256 tokenId, - uint256 salt, - bytes calldata initData - ) external returns (address) { - bytes memory code = ERC6551BytecodeLib.getCreationCode( - implementation, - chainId, - tokenContract, - tokenId, - salt - ); - - address _account = Create2.computeAddress(bytes32(salt), keccak256(code)); - - if (_account.code.length != 0) return _account; + uint256 tokenId + ) external returns (address account); - emit AccountCreated(_account, implementation, chainId, tokenContract, tokenId, salt); + /** + * @dev Returns the computed token bound account address for a non-fungible token. + * + * @return account The address of the token bound account + */ + function account( + address implementation, + bytes32 salt, + uint256 chainId, + address tokenContract, + uint256 tokenId + ) external view returns (address account); +} +contract ERC6551Registry is IERC6551Registry { + function createAccount( + address implementation, + bytes32 salt, + uint256 chainId, + address tokenContract, + uint256 tokenId + ) external returns (address) { assembly { - _account := create2(0, add(code, 0x20), mload(code), salt) - } - - if (_account == address(0)) revert AccountCreationFailed(); - - if (initData.length != 0) { - (bool success, bytes memory result) = _account.call(initData); - - if (!success) { - assembly { - revert(add(result, 32), mload(result)) + // Memory Layout: + // ---- + // 0x00 0xff (1 byte) + // 0x01 registry (address) (20 bytes) + // 0x15 salt (bytes32) (32 bytes) + // 0x35 Bytecode Hash (bytes32) (32 bytes) + // ---- + // 0x55 ERC-1167 Constructor + Header (20 bytes) + // 0x69 implementation (address) (20 bytes) + // 0x5D ERC-1167 Footer (15 bytes) + // 0x8C salt (uint256) (32 bytes) + // 0xAC chainId (uint256) (32 bytes) + // 0xCC tokenContract (address) (32 bytes) + // 0xEC tokenId (uint256) (32 bytes) + + // Silence unused variable warnings + pop(chainId) + + // Copy bytecode + constant data to memory + calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId + mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer + mstore(0x5d, implementation) // implementation + mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header + + // Copy create2 computation data to memory + mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode) + mstore(0x15, salt) // salt + mstore(0x01, shl(96, address())) // registry address + mstore8(0x00, 0xff) // 0xFF + + // Compute account address + let computed := keccak256(0x00, 0x55) + + // If the account has not yet been deployed + if iszero(extcodesize(computed)) { + // Deploy account contract + let deployed := create2(0, 0x55, 0xb7, salt) + + // Revert if the deployment fails + if iszero(deployed) { + mstore(0x00, 0x20188a59) // `AccountCreationFailed()` + revert(0x1c, 0x04) } + + // Store account address in memory before salt and chainId + mstore(0x6c, deployed) + + // Emit the ERC6551AccountCreated event + log4( + 0x6c, + 0x60, + // `ERC6551AccountCreated(address,address,bytes32,uint256,address,uint256)` + 0x79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf88722, + implementation, + tokenContract, + tokenId + ) + + // Return the account address + return(0x6c, 0x20) } - } - return _account; + // Otherwise, return the computed account address + mstore(0x00, shr(96, shl(96, computed))) + return(0x00, 0x20) + } } function account( address implementation, + bytes32 salt, uint256 chainId, address tokenContract, - uint256 tokenId, - uint256 salt + uint256 tokenId ) external view returns (address) { - bytes32 bytecodeHash = keccak256( - ERC6551BytecodeLib.getCreationCode( - implementation, - chainId, - tokenContract, - tokenId, - salt - ) - ); - - return Create2.computeAddress(bytes32(salt), bytecodeHash); + assembly { + // Silence unused variable warnings + pop(chainId) + pop(tokenContract) + pop(tokenId) + + // Copy bytecode + constant data to memory + calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId + mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer + mstore(0x5d, implementation) // implementation + mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header + + // Copy create2 computation data to memory + mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode) + mstore(0x15, salt) // salt + mstore(0x01, shl(96, address())) // registry address + mstore8(0x00, 0xff) // 0xFF + + // Store computed account address in memory + mstore(0x00, shr(96, shl(96, keccak256(0x00, 0x55)))) + + // Return computed account address + return(0x00, 0x20) + } } } ``` From b0d86bf7c81fb395d2178c02e1d3f105c7d305d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BA=CE=B1=CF=83=CF=83=CE=AC=CE=BD=CE=B4=CF=81=CE=B1=2Ee?= =?UTF-8?q?th?= <0xDADA@protonmail.com> Date: Mon, 30 Oct 2023 15:02:35 +0100 Subject: [PATCH 16/20] Update ERC-5564: missing necessary arg in computeStealthKey Merged by EIP-Bot. --- ERCS/erc-5564.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ERCS/erc-5564.md b/ERCS/erc-5564.md index f01ff65a046..bb1a82f433a 100644 --- a/ERCS/erc-5564.md +++ b/ERCS/erc-5564.md @@ -72,6 +72,7 @@ A recipient MUST be able to compute the private key for a stealth address by cal /// @notice Computes the stealth private key for a stealth address. /// @param stealthAddress The expected stealth address. /// @param ephemeralPubKey The ephemeral public key used to generate the stealth address. +/// @param viewingKey The recipient's viewing private key. /// @param spendingKey The recipient's spending private key. /// @return stealthKey The stealth private key corresponding to the stealth address. /// @dev The stealth address input is not strictly necessary, but it is included so the method @@ -79,6 +80,7 @@ A recipient MUST be able to compute the private key for a stealth address by cal function computeStealthKey( address stealthAddress, bytes memory ephemeralPubKey, + bytes memory viewingKey, bytes memory spendingKey ) external view returns (bytes memory); ``` From f8fd6add408f0b9a792a0523b0693aa5b7618592 Mon Sep 17 00:00:00 2001 From: lightclient <14004106+lightclient@users.noreply.github.com> Date: Mon, 30 Oct 2023 09:12:21 -0600 Subject: [PATCH 17/20] 7254: fix broken links (#65) --- ERCS/erc-7254.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7254.md b/ERCS/erc-7254.md index 21cf1c0d74c..9a5e50c4bca 100644 --- a/ERCS/erc-7254.md +++ b/ERCS/erc-7254.md @@ -12,9 +12,9 @@ created: 2023-06-29 ## Abstract -With the aspiration of bringing forth unique functionality and enhancing value for holders of [ERC-20](./erc-20.md) tokens, our project aims to effortlessly reward token holders without necessitating users to lock, stake, or farm their tokens. Whenever the project generates profits, these profits can be distributed to the token holders. +With the aspiration of bringing forth unique functionality and enhancing value for holders of [ERC-20](./eip-20.md) tokens, our project aims to effortlessly reward token holders without necessitating users to lock, stake, or farm their tokens. Whenever the project generates profits, these profits can be distributed to the token holders. -Revenue Sharing is an extended version of [ERC-20](./erc-20.md). It proposes an additional payment method for token holders. +Revenue Sharing is an extended version of [ERC-20](./eip-20.md). It proposes an additional payment method for token holders. This standard includes updating rewards for holders and allowing token holders to withdraw rewards. @@ -121,8 +121,8 @@ TBD ## Reference Implementation -* [ERC-7254](../assets/erc-7254/ERC7254.sol) -* [IERC-7254](../assets/erc-7254/IERC7254.sol) +* [ERC-7254](../assets/eip-7254/ERC7254.sol) +* [IERC-7254](../assets/eip-7254/IERC7254.sol) ## Security Considerations From 59468dfe0ef0b2333a5650619e27b92cde46f44c Mon Sep 17 00:00:00 2001 From: Gavin John Date: Mon, 30 Oct 2023 14:54:33 -0500 Subject: [PATCH 18/20] Fix incorrect run summary link (#68) --- .github/workflows/post-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-ci.yml b/.github/workflows/post-ci.yml index 7057a97f301..43e8bc83bb3 100644 --- a/.github/workflows/post-ci.yml +++ b/.github/workflows/post-ci.yml @@ -35,7 +35,7 @@ jobs: recreate: true message: | The commit ${{ steps.save-pr-data.outputs.pr_sha }} (as a parent of ${{ steps.save-pr-data.outputs.merge_sha }}) contains errors. - Please inspect the [Run Summary](https://github.com/ethereum/EIPs/pull/${{ steps.save-pr-data.outputs.pr_number }}/files) for details. + Please inspect the [Run Summary](https://github.com/ethereum/ercs/${{ steps.save-pr-data.outputs.pr_number }}/files) for details. - name: Add Waiting Label uses: actions-ecosystem/action-add-labels@288072f1a3b596f4350fe135bcfe381a23abadef From d015f5b8c64ec880776c17c5cef4fac2a3ec811d Mon Sep 17 00:00:00 2001 From: Gavin John Date: Mon, 30 Oct 2023 14:54:40 -0500 Subject: [PATCH 19/20] Fix stale bot repo check (#69) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 03eaf1bb8c6..a96921d17aa 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ permissions: jobs: stale: - if: github.repository == 'ethereum/eips' + if: github.repository == 'ethereum/ercs' runs-on: ubuntu-latest name: Mark Stale Issues steps: From d56cb136a0996ce834a20247526c1687e54e40f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toni=20Wahrst=C3=A4tter?= <51536394+nerolation@users.noreply.github.com> Date: Tue, 31 Oct 2023 06:40:28 +0100 Subject: [PATCH 20/20] Update ERC-5564: Fix broken links Merged by EIP-Bot. --- ERCS/erc-5564.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/ERCS/erc-5564.md b/ERCS/erc-5564.md index bb1a82f433a..60017c82d34 100644 --- a/ERCS/erc-5564.md +++ b/ERCS/erc-5564.md @@ -12,7 +12,7 @@ created: 2022-08-13 ## Abstract -This specification establishes a standardized method for interacting with stealth addresses, which allow senders of transactions or transfers to non-interactively generate private accounts exclusively accessible by their recipients. Moreover, this specification enables developers to create stealth address protocols based on the foundational implementation outlined in this EIP, utilizing a singleton contract to emit the necessary information for recipients. In addition to the base implementation, this ERC also outlines the first implementation of a cryptographic scheme, specifically the SECP256k1 curve. +This specification establishes a standardized method for interacting with stealth addresses, which allow senders of transactions or transfers to non-interactively generate private accounts exclusively accessible by their recipients. Moreover, this specification enables developers to create stealth address protocols based on the foundational implementation outlined in this ERC, utilizing a singleton contract to emit the necessary information for recipients. In addition to the base implementation, this ERC also outlines the first implementation of a cryptographic scheme, specifically the SECP256k1 curve. ## Motivation @@ -72,7 +72,6 @@ A recipient MUST be able to compute the private key for a stealth address by cal /// @notice Computes the stealth private key for a stealth address. /// @param stealthAddress The expected stealth address. /// @param ephemeralPubKey The ephemeral public key used to generate the stealth address. -/// @param viewingKey The recipient's viewing private key. /// @param spendingKey The recipient's spending private key. /// @return stealthKey The stealth private key corresponding to the stealth address. /// @dev The stealth address input is not strictly necessary, but it is included so the method @@ -80,14 +79,13 @@ A recipient MUST be able to compute the private key for a stealth address by cal function computeStealthKey( address stealthAddress, bytes memory ephemeralPubKey, - bytes memory viewingKey, bytes memory spendingKey ) external view returns (bytes memory); ``` The implementation of these methods is scheme-specific. The specification of a new stealth address scheme MUST specify the implementation for each of these methods. Additionally, although these function interfaces are specified in Solidity, they do not necessarily ever need to be implemented in Solidity, but any library or SDK conforming to this specification MUST implement these methods with compatible function interfaces. -A 256 bit integer (`schemeId`) is used to identify stealth address schemes. A mapping from the schemeId to its specification MUST be declared in the EIP that proposes to standardize a new stealth address scheme. It is RECOMMENDED that `schemeId`s are chosen to be monotonically incrementing integers for simplicity, but arbitrary or meaningful `schemeId`s may be chosen. Furthermore, the schemeId MUST be added to [this overview](../assets/eip-5564/scheme_ids.md). These extensions MUST specify: +A 256 bit integer (`schemeId`) is used to identify stealth address schemes. A mapping from the schemeId to its specification MUST be declared in the ERC that proposes to standardize a new stealth address scheme. It is RECOMMENDED that `schemeId`s are chosen to be monotonically incrementing integers for simplicity, but arbitrary or meaningful `schemeId`s may be chosen. Furthermore, the schemeId MUST be added to [this overview](../assets/erc-5564/scheme_ids.md). These extensions MUST specify: - The integer identifier for the scheme. @@ -152,14 +150,14 @@ contract IERC5564Announcer { ### Stealth meta-address format -The new address format for the stealth meta-address is based on [ERC-3770](./eip-3770.md) and extends it by adding a `st:` (*stealth*) prefix. +The new address format for the stealth meta-address extends the chain specific address format by adding a `st:` (*stealth*) prefix. Thus, a stealth meta-address on Ethereum has the following format: ``` st:eth:0x ``` -Stealth meta-addresses may be managed by the user and/or registered within a publicly available `Registry` contract, as delineated in [ERC-6538](./eip-6538). This provides users with a centralized location for identifying stealth meta-addresses associated with other individuals while simultaneously enabling recipients to express their openness to engage via stealth addresses. +Stealth meta-addresses may be managed by the user and/or registered within a publicly available `Registry` contract, as delineated in [ERC-6538](./erc-6538). This provides users with a centralized location for identifying stealth meta-addresses associated with other individuals while simultaneously enabling recipients to express their openness to engage via stealth addresses. *Notably, the address format is used only to differentiate stealth addresses from standard addresses, as the prefix is removed before performing any computations on the stealth meta-address.* @@ -167,7 +165,7 @@ Stealth meta-addresses may be managed by the user and/or registered within a pub ### Initial Implementation of SECP256k1 with View Tags -This EIP provides a foundation that is not tied to any specific cryptographic system through the `IERC5564Announcer` contract. In addition, it introduces the first implementation of a [stealth address scheme](../assets/eip-5564/scheme_ids.md) that utilizes the SECP256k1 elliptic curve and view tags. The SECP256k1 elliptic curve is defined with the equation $y^2 = x^3 + 7 \pmod{p}$, where $p = 2^{256} - 2^{32} - 977$. +This ERC provides a foundation that is not tied to any specific cryptographic system through the `IERC5564Announcer` contract. In addition, it introduces the first implementation of a [stealth address scheme](../assets/erc-5564/scheme_ids.md) that utilizes the SECP256k1 elliptic curve and view tags. The SECP256k1 elliptic curve is defined with the equation $y^2 = x^3 + 7 \pmod{p}$, where $p = 2^{256} - 2^{32} - 977$. The following reference is divided into three sections: @@ -246,7 +244,7 @@ The view tags approach is introduced to reduce the parsing time by around 6x. Us ## Rationale -This EIP emerged from the need for privacy-preserving ways to transfer ownership without disclosing any information about the recipients' identities. Token ownership can expose sensitive personal information. While individuals may wish to donate to a specific organization or country, they might prefer not to disclose a link between themselves and the recipient simultaneously. Standardizing stealth address generation represents a significant step towards unlinkable interactions, since such privacy-enhancing solutions require standards to achieve widespread adoption. Consequently, it is crucial to focus on developing generalizable approaches for implementing related solutions. +This ERC emerged from the need for privacy-preserving ways to transfer ownership without disclosing any information about the recipients' identities. Token ownership can expose sensitive personal information. While individuals may wish to donate to a specific organization or country, they might prefer not to disclose a link between themselves and the recipient simultaneously. Standardizing stealth address generation represents a significant step towards unlinkable interactions, since such privacy-enhancing solutions require standards to achieve widespread adoption. Consequently, it is crucial to focus on developing generalizable approaches for implementing related solutions. The stealth address specification standardizes a protocol for generating and locating stealth addresses, facilitating the transfer of assets without requiring prior interaction with the recipient. This enables recipients to verify the receipt of a transfer without the need to interact with the blockchain and query account balances. Importantly, stealth addresses enable token transfer recipients to verify receipt while maintaining their privacy, as only the recipient can recognize themselves as the recipient of the transfer. @@ -256,7 +254,7 @@ The recipient's address and the `viewTag` MUST be included in the announcement e ## Backwards Compatibility -This EIP is fully backward compatible. +This ERC is fully backward compatible. ## Reference Implementation @@ -270,7 +268,7 @@ There are potential denial of service (DoS) attack vectors that are not mitigate We consider the incentives to carry out such an attack to be low because **no monetary benefit can be obtained** However, to tackle potential spam, parsing providers may adopt their own anti-DoS attack methods. These may include ignoring the spamming users when serving announcements to users or, less harsh, de-prioritizing them when ordering the announcements. The indexed `caller` keyword may help parsing providers to effectively filter known spammers. -Furthermore, parsing providers have a few options to counter spam, such as introducing staking mechanisms or requiring senders to pay a `toll` before including their `Announcement`. Moreover, a Staking mechanism may allow users to stake an unslashable amount of ETH (similarly to [ERC-4337](./eip-4337)), to help mitigate potential spam through *sybil attacks* and enable parsing providers filtering spam more effectively. +Furthermore, parsing providers have a few options to counter spam, such as introducing staking mechanisms or requiring senders to pay a `toll` before including their `Announcement`. Moreover, a Staking mechanism may allow users to stake an unslashable amount of ETH (similarly to [ERC-4337](./erc-4337)), to help mitigate potential spam through *sybil attacks* and enable parsing providers filtering spam more effectively. Introducing a `toll`, paid by sending users, would simply put a cost on each stealth address transaction, making spamming economically unattractive. ### Recipients' transaction costs @@ -282,4 +280,3 @@ Thus, the sender may attach a small amount of ETH to each stealth address transa ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md). -