Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: clean readme #28

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 15 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,29 @@
# ERC1155A - SuperForm's ERC-1155 Extension
# Overview

SuperForm implementation of ERC-1155 with extended approval logic. Allows token owners to execute single id approvals in place of mass approving all of the ERC-1155 ids to the spender.
ERC1155A is an extension of ERC-1155 with extended approval and transmute logic, used in SuperPositions. This allows token owners to execute single id or multiple id approvals in place of mass approving all of the ERC1155 ids to the spender and to transmute ERC1155 ids to and from registered ERC20's.

You need foundry/forge to run repository.

`forge install`

`forge test`

Two set of tests are run. `ERC1155A` specific and general `ERC1155` tests forked from solmate's implementation of the standard. SuperForm's `ERC1155A` has exactly the same interface as standard `ERC1155` and expected behavior of functions follow EIP documentation.

# Rationale

ERC1155 `setApprovalForAll` function gives full spending permissions over all currently exisiting and future Ids. Addition of single Id approve, allows this token standard to improve composability through more better allowance control of funds. If external contract is an expected to spend only a single ERC1155 id there is no reason it should have access to all the user owned ids.

# Implementation Details

Main change is how `ERC1155A` implements `safeTransferFrom()` function. Standard ERC-1155 implementations are checking only if caller `isApprovedForAll` or an owner of token ids. We propose `setApprovalForOne()` function allowing approvals for specific id in any amount. Therefore, id owner is no longer required to mass approve all of his token ids. The side effect of it is requirement of additional validation logic inside of `safeTransferFrom()` function.
Read more about ERC1155 here: https://docs.superform.xyz/periphery-contracts/superpositions/erc1155a

With gas effiency in mind and preservation of expected ERC1155 behavior, ERC1155A still prioritizes `isApprovedForAll` over `setApprovalForOne()`. Only `safeTransferFrom()` function works with single allowances, `safeBatchTransferFrom()` function requires owner to grant `setApprovalForAll()` to the operator. Decision is dictated by a significant gas costs overhead when required to decrease (or reset, in case of an overflow) allowances for each id in array. Moreover, if owner has `setApprovalForAll()` set to `true`, ERC1155A contract will not modify existing single allowances during `safeTransferFrom()` and `safeBatchTransferFrom()` - assuming that owner has full trust in _operator_ for granting mass approve. Therefore, ERC1155A requires owners to manage their allowances individually and be mindfull of enabling `setApprovalForAll()` for external contracts.
## Rationale

# Allowances Flow of Execution
ERC1155 `setApprovalForAll` function gives full spending permissions over all currently exisiting and future Ids. Addition a of single Id approve allows this token standard to improve composability through more better allowance control of funds. If external contract is an expected to spend only a single ERC1155 id there is no reason it should have access to all the user owned ids.

Case 1: AllApproval + NO SingleApproval (standard 1155)
ERC1155s additionally do not provide large composability with the DeFi ecosystem, so we provide the ability to transmute individual token ids via `transmuteToaERC20` to an ERC20 token. This may be reversed via `transmuteToERC1155A`.

Case 2: AllApproval + SingleApproval _(smaller than amount requested for transfer)_
## Implementation Details

Case 3: SingleApproval _(bigger than amount requested for transfer)_ + AllApproval
The main change in approval logic is how ERC1155A implements the `safeTransferFrom()` function. Standard ERC1155 implementations only check if the caller in `isApprovedForAll` is an owner of token ids. We propose `setApprovalForOne()` or `setApprovalForMany()` function allowing approvals for specific id in any amount. Therefore, id owner is no longer required to mass approve all of his token ids. The side effect of it is requirement of additional validation logic inside of `safeTransferFrom()` function.

Case 4: SingleApproval + NO AllApproval _(ERC20-like)_
With gas effiency in mind and preservation of expected ERC1155 behavior, ERC1155A still prioritizes `isApprovedForAll` over `setApprovalForOne()`. Only `safeTransferFrom()` function works with single allowances, `safeBatchTransferFrom()` function requires owner to grant `setApprovalForAll()` to the operator. Decision is dictated by a significant gas costs overhead when required to decrease (or reset, in case of an overflow) allowances for each id in array. Moreover, if owner has `setApprovalForAll()` set to `true`, ERC1155A contract will not modify existing single allowances during `safeTransferFrom()` and `safeBatchTransferFrom()` - assuming that owner has full trust in _operator_ for granting mass approve. Therefore, ERC1155A requires owners to manage their allowances individually and be mindful of enabling `setApprovalForAll()` for external contracts.

Therefore, the possible execution flow with two independent set of approvals is as follows:
ERC1155A token ids may also be transmuted into ERC20's, and transmuted back from the ERC20 through `transmute` functions after `registeraERC20` has been called to create the ERC20 token representation on the chain.

If caller is owner of ids, transfer just executes.
### Testing

If caller `singleApproved > transferAmount`, function executes and reduces allowance (even if setApproveForAll is true)

If caller `singleApproved < transferAmount && isApprovedForAll`, function executes without reducing allowance (full trust assumed)

If caller only approvedForAll, function executes without reducing allowance (full trust assumed)

### Gas Overhead

Additional approval logic validation makes SOME transfer operations more expensive. Here's how it looks by comparison to solmate ERC1155 standard implementation:

ERC1155A

```
| safeBatchTransferFrom | 79432 | 79432 | 79432 | 79432 | 1 |
| safeTransferFrom | 27614 | 31069 | 31801 | 34517 | 5 |
| setApprovalForAll | 24574 | 24574 | 24574 | 24574 | 3 |
| setApprovalForOne | 24920 | 24920 | 24920 | 24920 | 4 |
```

ERC-1155
You need foundry/forge to run repository.

```
| safeBatchTransferFrom | 1247 | 896149 | 124953 | 8597031 | 15 |
| safeTransferFrom | 1072 | 34106 | 27191 | 183333 | 18 |
| setApprovalForAll | 4581 | 23615 | 24481 | 24481 | 23 |
```
`forge install`

# Future Work
`forge test`

TODO: https://eips.ethereum.org/EIPS/eip-1761 (suggested by 1155) - range-based approvals
Two set of tests are run. `ERC1155A` specific and general `ERC1155` tests forked from solmate's implementation of the standard. SuperForm's `ERC1155A` has exactly the same interface as standard `ERC1155` and expected behavior of functions follow EIP documentation.