-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
EIP-3009: "Transfer With Authorization" - ERC20 meta-transactions #3010
Comments
transferWithAuthorization
: Gas-Abstracted ERC20 transactionstransferWithAuthorization
: Gas-Abstracted ERC20 transactions (from USDC v2)
transferWithAuthorization
: Gas-Abstracted ERC20 transactions (from USDC v2)
If you want to try it out, there is a fully gasless (free) demo that runs on Görli testnet: USDC L2 Demo. Click on "Give Me Some" to get tokens, again, gaslessly. |
Consider adding a method for |
@MicahZoltu what is the benefit of that method? looks like it will make it easier to attack relayers. @petejkim Glad to see more work towards standardization of token contract methods for gas less transactions. Unfortunatelly random nonces require extra storage. Sequential nonces to make sure calls are executed in order or not executed are a good feature IMO. I understand random nonces help relayers if transactions are mined out of order. But I don't think it is worth solving the sequential nonce reuse problem from the end users side this way. The user wallet could track what sequential nonces were used to avoid reusing them. If the users sign the same nonce on purpose, making relayers waste money then they can be punished. |
As a user, if I send a transaction out to take some action and for whatever reason it doesn't get picked up soon (perhaps I don't compensate the relayer enough in the transaction), I will forever have that particular transaction pending and available to be executed at any time in the future, potentially when it is profitable for someone else to have that transaction show up. As a user, I want the ability to "cancel" that transaction by invalidating a particular nonce so that no one can include it at an arbitrary point in time in the future. |
@MicahZoltu I agree with what you said. USDCv2 does have I will also address the rest of your feedback over the weekend, thanks for reviewing, really appreciate it. |
Keeping EIPs small and modular is certainly reasonable and I support it. Perhaps consider creating a second EIP that depends on this one which adds |
There are other options for concurrent nonce management that may be relevant here. They typically require a bit more work on the client side, but can reduce gas costs in the contract by not having to always use a new storage slot. Multinonce: A two dimensional nonce that allows the client to choose between concurrent and sequential behaviour. The nonce is both an index and a sequential nonce; the contract stores a mapping of index -> nonce. The client specifies both index and a nonce which is current nonce at that index + 1. For concurrency they use a new index, or a very old index for which they know no pending transactions exist. For 2 transactions that must be mined sequentially the client specifies the same index. BitFlip: The nonce is a single bit to be turned on. If the bit is already on that nonce has already been used. |
I suggest using |
Edit: Ah, I just saw this was also mentioned on the original PR as a comment to remove the internal state details as well. Ccould we simplify the requirement of a separate function name by simply using the auto-generated getter (as EIP-2612 also currently suggests)? So instead of:
It's just:
|
@sohkai Yep, that works! |
I think might be helpful add a security consideration to never use the An example of the attack: |
Seems it needs some msg.sender verification to reduce the front-running risk @invocamanman described. |
I think it's useful to support being able to send to EOAs, so I think there are two ways to address this:
|
Those are interesting ideas, but in absence of some off-chain nonce tracker, it doesn't solve the problem of not being able to reliably obtain an unused nonce, especially when multiple DApps are used simultaneously. Bitflip is certainly better than the conventional incremental nonce though. |
Dapps can do this by choosing a random index - the collision chance is negligible. Ofc each new dapp wold incur a 20k store instead of a 5k store for using a new rand. Other options for figuring out the currently used nonces are to ask the wallet for the next nonce, or to look in the pending pool for the Generally though I think @juli's |
A side note: I believe that there is a bug in the code listed in the EIP-3009. I fixed it in a pull request on the repo the actual code files are in: CoinbaseStablecoin/eip-3009#1 The USDCv2 code seems to be correct, however. Just not the reference implementation I see in the EIP-3009. |
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review. |
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment. |
Hi, |
@omidziaee Yeah, you are calling contract method. Here's the example in JS
|
I'm trying to use I'm using the eth-sig-util package for signing the typed data, and the web3dart package for creating and signing the transaction. My understanding of the flow so far
I'm currently getting stuck on step 4, with The only parameter that seems to be an Update
The latter two done with:
But now I get stuck on step 4, ethClient.signTransaction, with an invalid v value: Dart code for a function that should return a hash of the broadcast transaction:
|
I have an EIP which adds 13 lines of functionality to this EIP, would love your thoughts 😄 (from Circle engineering team!) #5987 @sohkai @invocamanman @leekt @ThomasRogg @danielnordh @omidziaee @jejopl @kbrizzle @DavidLKnott @juli @MiCh @yahgwai |
@danielnordh did you end up finding a way to get past step 4? |
Locking this issue, as it is no longer the discussion link. |
Pull Request: EIP-3009: transferWithAuthorization
This is the place to discuss EIP-3009 "Transfer With Authorization", implemented by the USD Coin (USDC) v2 smart contract alongside EIP-2612: permit.
eip: 3009
title: Transfer With Authorization
author: Peter Jihoon Kim (@petejkim), Kevin Britz (@kbrizzle), David Knott (@DavidLKnott)
discussions-to: #3010
status: Draft
type: Standards Track
category: ERC
created: 2020-09-28
requires: 20, 712
Simple Summary
A contract interface that enables transferring of fungible assets via a signed authorization.
Abstract
A set of functions to enable meta-transactions and atomic interactions with ERC-20 token contracts via signatures conforming to the EIP-712 typed message signing specification.
This enables the user to:
Motivation
There is an existing spec, EIP-2612, that also allows meta-transactions, and it is encouraged that a contract implements both for maximum compatibility. The two primary differences between this spec and EIP-2612 are that:
approve
/transferFrom
("ERC-20 allowance") pattern.The biggest issue with the use of sequential nonces is that it does not allow users to perform more than one transaction at time without risking their transactions failing, because:
This can be especially problematic if the gas prices are very high and transactions often get queued up and remain unconfirmed for a long time. Non-sequential nonces allow users to create as many transactions as they want at the same time.
The ERC-20 allowance mechanism is susceptible to the multiple withdrawal attack/SWC-114, and encourages antipatterns such as the use of the "infinite" allowance. The wide-prevalence of upgradeable contracts have made the conditions favorable for these attacks to happen in the wild.
The deficiencies of the ERC-20 allowance pattern brought about the development of alternative token standards such as the ERC-777 and ERC-677. However, they haven't been able to gain much adoption due to compatibility and potential security issues.
Specification
Event
Optional:
The arguments
v
,r
, ands
must be obtained using the EIP-712 typed message signing spec.Example:
With the domain separator, the typehash, which is used to identify the type of the EIP-712 message being used, and the values of the parameters, you are able to derive a Keccak-256 hash digest which can then be signed using the token holder's private key.
Example:
Smart contract functions that wrap
receiveWithAuthorization
call may choose to reduce the number of arguments by accepting the full ABI-encoded set of arguments for thereceiveWithAuthorization
call as a single argument of the typebytes
.Example:
Use with web3 providers
The signature for an authorization can be obtained using a web3 provider with the
eth_signTypedData{_v4}
method.Example:
Rationale
Unique Random Nonce, Instead of Sequential Nonce
One might say transaction ordering is one reason why sequential nonces are preferred. However, sequential nonces do not actually help achieve transaction ordering for meta transactions in practice:
Valid After and Valid Before
EIP-712
verifyingContract
andchainId
are included.Backwards Compatibility
New contracts benefit from being able to directly utilize EIP-3009 in order to create atomic transactions, but existing contracts may still rely on the conventional ERC-20 allowance pattern (
approve
/transferFrom
).In order to add support for EIP-3009 to existing contracts ("parent contract") that use the ERC-20 allowance pattern, a forwarding contract ("forwarder") can be constructed that takes an authorization and does the following:
receiveWithAuthorization
to transfer specified funds from the user to the forwarderExample:
Test Cases
See EIP3009.test.ts.
Implementation
EIP3009.sol
IERC20Transfer.sol
EIP712Domain.sol
EIP712.sol
A fully working implementation of EIP-3009 can be found in this repository. The repository also includes an implementation of EIP-2612 that uses the EIP-712 library code presented above.
Security Considerations
Use
receiveWithAuthorization
instead oftransferWithAuthorization
when calling from other smart contracts. It is possible for an attacker watching the transaction pool to extract the transfer authorization and front-run thetransferWithAuthorization
call to execute the transfer without invoking the wrapper function. This could potentially result in unprocessed, locked up deposits.receiveWithAuthorization
prevents this by performing an additional check that ensures that the caller is the payee. Additionally, if there are multiple contract functions accepting receive authorizations, the app developer could dedicate some leading bytes of the nonce could as the identifier to prevent cross-use.When submitting multiple transfers simultaneously, be mindful of the fact that relayers and miners will decide the order in which they are processed. This is generally not a problem if the transactions are not dependent on each other, but for transactions that are highly dependent on each other, it is recommended that the signed authorizations are submitted one at a time.
The zero address must be rejected when using
ecrecover
to prevent unauthorized transfers and approvals of funds from the zero address. The built-inecrecover
returns the zero address when a malformed signature is provided.Copyright
Copyright and related rights waived via CC0.
The text was updated successfully, but these errors were encountered: