-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
--- | ||
eip: 5216 | ||
title: EIP-1155 Approval By Amount Extension | ||
description: Extension for EIP-1155 secure approvals | ||
author: Iván Mañús Murcia, Juan Carlos Cantó Martinez (@EscuelaCrypto in Telegram) | ||
discussions-to: https://ethereum-magicians.org/t/eip-erc1155-approval-by-amount/9898 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2022-07-11 | ||
requires: 20, 1155 | ||
--- | ||
|
||
## Abstract | ||
|
||
This specification defines standard functions for approving amounts of an [ERC-1155](./eip-1155.md). An implementation allows approve by id, different amounts both batch and individual. The proposal depends on and extends the existing [ERC-1155](./eip-1155.md). | ||
|
||
## Motivation | ||
|
||
[ERC-1155](./eip-1155.md) has created a scenario where multiple token management and transactions occur on a daily basis. Although it can be used as [ERC-721](./eip-721.md), the most common way to use it is to create collections through its `ids` in order to have an indefinite `amount` of tokens of one type. These tokens have been implemented in a wide variety of projects, but the most important are marketplaces. | ||
The nature of tokens is trading, transfer and use, so it is important that your peer-to-peer transactions are as secure as possible. | ||
|
||
The way the [ERC-1155](./eip-1155.md) standard approves tokens is with the `setApprovalForAll(address operator, bool approved)` function, which approves ALL tokens of an `id`. However, this is a standard that combines ideas from the [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) standards, and it is important to create a trust mechanism, where an owner can allow a third party, such as a marketplace, to approve a limited number of tokens of an `id` and not all at once. | ||
|
||
In turn, it is also necessary to subtract the amount of tokens approved once they have been successfully transferred to avoid the scenario that we have now, where ALL tokens of an `id` are approved without revoking that approval at any time. In our honest opinion, this is quite dangerous because if you don't revoke that approval with `setApprovalForAll(operatorAddress, false)`, you let that the operator do whateaver he wants whenever he wants with all your tokens. | ||
|
||
By having a way to approve and revoke as the [ERC-20](./eip-20.md) standard works, i.e. by amounts we reduce that security problem: | ||
|
||
- By `approve` function, we allow an operator to use an amount of tokens per id. | ||
- Through the function `allowance` you can see the amount of tokens that an approved account has per id. | ||
|
||
Both following the [ERC-20](./eip-20.md) standard name patterns. | ||
|
||
|
||
## Specification | ||
|
||
The keywords “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. | ||
|
||
Every contract compliant to the `ERC1155ApprovalByAmount` extension MUST implement the `IERC1155ApprovalByAmount` interface. The **approval by amount extension** is OPTIONAL for [ERC-1155](./eip-1155.md) contracts. | ||
|
||
### Interface implementation | ||
|
||
```solidity | ||
/** | ||
* @title ERC-1155 Approval By Amount Extension | ||
* Note: the ERC-165 identifier for this interface is 0x1be07d74 | ||
*/ | ||
interface IERC1155ApprovalByAmount is IERC1155 { | ||
/** | ||
* @notice Emmited when `account` grants or revokes permission to `operator` to transfer their tokens, according to | ||
* `id` and with an amount: `amount`. | ||
*/ | ||
event ApprovalByAmount(address indexed account, address indexed operator, uint256 id, uint256 amount); | ||
/** | ||
* @notice Grants permision to `operator` to transfer the caller's tokens, according to `id`, and an amount: `amount`. | ||
* Emits an {ApprovalByAmount} event. | ||
* | ||
* Requirements: | ||
* - `operator` cannot be the caller. | ||
*/ | ||
function approve(address operator, uint256 id, uint256 amount) external; | ||
/** | ||
* @notice Returns the amount allocated to `operator` approved to transfer ``account``'s tokens, according to `id`. | ||
*/ | ||
function allowance(address account, address operator, uint256 id) external view returns (uint256); | ||
} | ||
``` | ||
|
||
The `_allowances` mapping MAY be implemented as `internal` or `private`. | ||
|
||
The `approve(address operator, uint256 id, uint256 amount)` function MAY be implemented as `public` or `external` and it is RECOMMENDED implements `private` `_approve(address owner, address operator, uint256 id, uint256 amount)` function, which is responsible for performing the approval. | ||
|
||
The `allowance(address account, address operator, uint256 id)` function MAY be implemented as `public` or `external` for visibility and MUST be implemented as `view`. | ||
|
||
Every contract implementing the `ERC1155ApprovalByAmount` extension MUST implement `_checkApprovalForBatch(address from, address to, uint256[] memory ids, uint256[] memory amounts)` function in some way. This function is necessary to manage | ||
batch transfers subtracting the amount of tokens transferred. | ||
|
||
In same way, `safe(Batch)TrasferFrom` overrided function from `ERC1155` standard it is also important to change its implementation: | ||
|
||
- In `safeTransferFrom` MUST be added to require an extra condition: `|| allowance(from, _msgSender(), id)`. | ||
- In `safeTransferFrom` MUST be subtracted from `_allowances` mapping the transferred amount of tokens: `_allowances[from][_msgSender()][id] -= amount`. | ||
- In `safeBatchTransferFrom` MUST be added to require an extra condition that checks if the `allowance` of all `ids` have the approved `amounts` (See `_checkApprovalForBatch` function reference implementation) | ||
|
||
The `ApprovalByAmount` event MUST be emitted when a certain number of tokens are approved. | ||
|
||
The `supportsInterface` method MUST return `true` when called with `0x1be07d74`. | ||
|
||
## Rationale | ||
|
||
The chosen name resonates with the purpose of its existence. Users can approve their tokens by id and amounts to `operators`. | ||
|
||
The [ERC-20](./eip-20.md) standard name patterns, were used to simplify the understanding of how the interface works due to similarity with how [ERC-20](./eip-20.md) works with approvals. | ||
|
||
## Backwards Compatibility | ||
|
||
This standard is compatible with current [ERC-1155](./eip-1155.md) standards. | ||
|
||
## Test Cases | ||
|
||
Test cases are available in the reference implementation [here](../assets/eip-5216/test/erc1155approvalbyamount.js). | ||
|
||
## Reference Implementation | ||
|
||
The reference implementation can be found [here](../assets/eip-5216/contracts/ERC1155ApprovalByAmount.sol). | ||
|
||
## Security Considerations | ||
|
||
Implementors of the `ERC1155ApprovalByAmount` standard must consider thoroughly the amount of tokens they give permission to `operators`. They should also revoke the rest. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](https://eips.ethereum.org/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
node_modules | ||
|
||
node_modules | ||
.env | ||
coverage | ||
coverage.json | ||
typechain | ||
|
||
#Hardhat files | ||
cache | ||
artifacts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<div align="center"> | ||
|
||
# ERC1155 Approval By Amount Extension | ||
|
||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) | ||
|
||
</div> | ||
|
||
## Install | ||
|
||
In order to install the required dependencies you need to execute: | ||
```shell | ||
npm install | ||
``` | ||
|
||
## Compile | ||
|
||
In order to compile the solidity contracts you need to execute: | ||
```shell | ||
npx hardhat compile | ||
``` | ||
|
||
## Tests | ||
In order to test the contracts you need to execute: | ||
|
||
```shell | ||
npx hardhat test | ||
``` | ||
|
||
#### Results | ||
Here are the results: | ||
``` | ||
ERC1155ApprovalByAmount | ||
approve | ||
✔ Approve id 0 for U1 with an amount of 10 (141ms) | ||
✔ Should revert when owner try to approve himself (134ms) | ||
safeTransferFrom | ||
✔ Should revert when caller isn't the from param (63ms) | ||
✔ Should revert when id to transfer is not approved and caller != from (63ms) | ||
✔ Transfer 10 1155-0 to U2 by owner (116ms) | ||
✔ Transfer 10 1155-0 to U1 call by himself (136ms) | ||
✔ Should revert when U1 try to transfer 1 1155-0 to himself with allowance actual in 0 (60ms) | ||
safeBatchTransferFrom | ||
✔ Approve id 1 for U1 with an amount of 10 (122ms) | ||
✔ Should be reverted because Id 0 is not approved for U1 (70ms) | ||
✔ Transfer 10 of 0 and 1 from owner to U2 (153ms) | ||
✔ Approve for Id 0 and transfer 10 of 0 and 1 to U1 (239ms) | ||
12 passing (5s) | ||
``` |
Oops, something went wrong.