-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Resolution on the EIP20 API Approve / TransferFrom multiple withdrawal attack #738
Comments
I know of two possible alternative approaches, one of which is used in the wild:
|
It seems that the approach of adding: require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
|
@Qqwy I like your safeApprove approach. All approaches are non backward compatible with ERC20 AFAICT. I probably should tag some previously involved people: @mikhail-vladimirov @frozeman @chriseth @Dexaran @GriffGreen @yupasik @koeppelmann @PeterBorah @jbaylina @khovratovich @brudaswen @paberr |
If you just add new (safeApprove) method, this is backward compatible because all existing code will still be able to use your smart contract. |
@mikhail-vladimirov I think what @HaleTom meant by backwards compatible was that adding a new method means that contracts that interact with ERC20 tokens wouldn't be able to use this safety feature without being replaced. @HaleTom I get your issue here, and a valid solution to that is to store another bool with each allowance keeping track if any of the allowance has been used since the owner last set allowance. Here's a quick example. I believe this offers a few benefits over the other solutions:
Please give feedback, I'm sure I've missed something. |
The idea with boolean variable looks odd for me because it makes possible the situation when Also this does not solve original problem. Lets assume the following scenario:
So Bob got 201 tokens from Alice in total while Alice never intended to give him more than 101 token. |
Yeah, as I pointed out, my one concern was the expectations around returning true/false from approve. I suppose you could just return true no matter what. Preferably, in any other programming language, I'd update the Can Alice not listen to the event emitted from her first tx? There's 3 possible scenarios in that case:
Edit: An alternative is to just involve the |
Came here from your email to consensys-diligence @HaleTom. Thanks for addressing this safety issue.
It seems we're going to need to start adapting that to multiple token standards. We'll monitor, and if something resembling consensys is reached be happy to provide an implementation alongside our EIP20 implementation. |
Has anyone written a truffle (or other) test which illustrates this issue? |
Hello,
This approach would still require the allowance to be set to zero prior to setting it to a new value. |
I think the fix mentioned here might be helpful. Just FYI. |
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. |
This comment was marked as off-topic.
This comment was marked as off-topic.
<p>This PR was automatically created by Snyk using the credentials of a real user.</p><br /><h3>Snyk has created this PR to fix one or more vulnerable packages in the `npm` dependencies of this project.</h3> #### Changes included in this PR - Changes to the following files to upgrade the vulnerable dependencies to a fixed version: - assets/eip-4675/package.json #### Vulnerabilities that will be fixed ##### With an upgrade: Severity | Issue | Breaking Change | Exploit Maturity :-------------------------:|:-------------------------|:-------------------------|:------------------------- ![medium severity](https://res.cloudinary.com/snyk/image/upload/w_20,h_20/v1561977819/icon/m.png "medium severity") | Open Redirect <br/>[SNYK-JS-GOT-2932019](https://snyk.io/vuln/SNYK-JS-GOT-2932019) | No | No Known Exploit <details> <summary><b>Commit messages</b></summary> </br> <details> <summary>Package name: <b>solidity-coverage</b></summary> The new version differs by 41 commits.</br> <ul> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/0a33e13b166651bf8ce94d425d0abf590fed784c">0a33e13</a> 0.8.0</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/4c63612f83f6b230810f5728f4c1315cfe28cef2">4c63612</a> Add hardhat to peerDependencies (ethereum#722)</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/9ce20ff4bbc3c7e015ac0a5574cc1ab61cfc216b">9ce20ff</a> Typo / Grammar fix. (ethereum#738)</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/204a5ebaa4be69fd420f9d3851dd518d9072ece9">204a5eb</a> Added a section for the report location. (ethereum#739)</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/ed3d5041764e1b6a2270d0b910a3bfaf1a9d3c01">ed3d504</a> Fix README for v0.8 release</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/05ab320fbccb7bc607d9e5ada4a3261c46a273e8">05ab320</a> Fixes for Hardhat 2.11.0 (ethereum#740)</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/bc7d07623ec4bd71a2ce4c8ecb4a872af613c8ef">bc7d076</a> 0.8.0 Additional Coverage Measurements & Restructure (Merge)</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/a7db2fedc447f318da0424a162e58a2475072dc1">a7db2fe</a> More README changes</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/16367d15389ade4f8cc5d9c17ccac2cfd0962e14">16367d1</a> Remove truffle files from project</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/26898c1ad9f81ae089953fa0a824ab01b7caef08">26898c1</a> Remove Builder-E2E test</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/8ea8ec93d923a9722a3549e5788d5aaa81b3a41a">8ea8ec9</a> Fix true/false scoped method definition function visibilities</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/21ca46e2de3e1fe27d120b38fe7383a0a90792b1">21ca46e</a> Temporarily skip truffle integration tests</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/22992e1c19825d27de665762ffb8798a6b3195fe">22992e1</a> Fix constructor test</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/cf126ea7311145214fde7f7538bf4428e168b834">cf126ea</a> Fix assert tests</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/0ba3f11701097693674dab8cf831fac9af113fb0">0ba3f11</a> Remove more buildler things</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/d57a1315ec73ee0f0a26a2e64212a6055d51c3ab">d57a131</a> Remove buidler</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/3bcec941ecbeac2fd385c3e17886e7e02c66c2ad">3bcec94</a> Fix rebase errors & regenerate yarn.lock</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/88c1d0039033cfbb38311c6430ebdc41d5480c03">88c1d00</a> Fix loops, modifiers, options and statements tests</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/0deb0013cbf9e552a133c18d46e4b6536700982f">0deb001</a> Fix if/else tests</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/29c0fdda7fcc438861bcbb4ad1c0cb26ffbd08fb">29c0fdd</a> Fix constructor keyword test</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/d4e8536aa3087f40853f2b4c168dfa2b4e9c6e7a">d4e8536</a> Update tests for adjusted statement coverage</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/3edfd2537180e0f78ba769b077664a3159ba0b2a">3edfd25</a> Stop injecting statement coverage into conditionals</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/7eb94a93f3b2a2c68535051758c688470de9a1e2">7eb94a9</a> Update @ solidity-parser/parser to 0.14.1</li> <li><a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/commit/e9133d719ca3969b63ffa777a13a3424f886fbc8">e9133d7</a> Generate mocha JSON output with --matrix (ethereum#601)</li> </ul> <a href="https://snyk.io/redirect/github/sc-forks/solidity-coverage/compare/0e17f18e80e46c598097ab89e32379cb6ffd7e33...0a33e13b166651bf8ce94d425d0abf590fed784c">See the full diff</a> </details> </details> Check the changes in this PR to ensure they won't cause issues with your project. ------------ **Note:** *You are seeing this because you or someone else with access to this repository has authorized Snyk to open fix PRs.* For more information: <img src="https://api.segment.io/v1/pixel/track?data=eyJ3cml0ZUtleSI6InJyWmxZcEdHY2RyTHZsb0lYd0dUcVg4WkFRTnNCOUEwIiwiYW5vbnltb3VzSWQiOiI5MjU1NWU1OC1iZGQ2LTQ5MjctOWVlMy1hZDlkMTE1NDFmNWIiLCJldmVudCI6IlBSIHZpZXdlZCIsInByb3BlcnRpZXMiOnsicHJJZCI6IjkyNTU1ZTU4LWJkZDYtNDkyNy05ZWUzLWFkOWQxMTU0MWY1YiJ9fQ==" width="0" height="0"/> 🧐 [View latest project report](https://app.snyk.io/org/woodpile37/project/f0dcf1c9-ecf1-445b-bc07-e8f73c595f54?utm_source=github&utm_medium=referral&page=fix-pr) 🛠 [Adjust project settings](https://app.snyk.io/org/woodpile37/project/f0dcf1c9-ecf1-445b-bc07-e8f73c595f54?utm_source=github&utm_medium=referral&page=fix-pr/settings) 📚 [Read more about Snyk's upgrade and patch logic](https://support.snyk.io/hc/en-us/articles/360003891078-Snyk-patches-to-fix-vulnerabilities) [//]: # (snyk:metadata:{"prId":"92555e58-bdd6-4927-9ee3-ad9d11541f5b","prPublicId":"92555e58-bdd6-4927-9ee3-ad9d11541f5b","dependencies":[{"name":"solidity-coverage","from":"0.7.22","to":"0.8.0"}],"packageManager":"npm","projectPublicId":"f0dcf1c9-ecf1-445b-bc07-e8f73c595f54","projectUrl":"https://app.snyk.io/org/woodpile37/project/f0dcf1c9-ecf1-445b-bc07-e8f73c595f54?utm_source=github&utm_medium=referral&page=fix-pr","type":"auto","patch":[],"vulns":["SNYK-JS-GOT-2932019"],"upgrade":["SNYK-JS-GOT-2932019"],"isBreakingChange":false,"env":"prod","prType":"fix","templateVariants":["updated-fix-title"],"priorityScoreList":[null],"remediationStrategy":"vuln"}) --- **Learn how to fix vulnerabilities with free interactive lessons:** 🦉 [Open Redirect](https://learn.snyk.io/lesson/open-redirect/?loc=fix-pr)
#I raise this as a separate issue as I can't see a definitive resolution after it was initially posted here. The thread of the issue is hard to follow because of the intermingled comments about non-related parts of the ERC20 standard.
Please close this issue if you believe that it should be posted as a comment on EIP20 itself and I will take that as a hint to move the discussion there.
But perhaps keeping separate issues for security related issues is warranted so that a single thread can be followed, months down the track. For example, the issue was raised on 29 Nov 2016, and the latest comment is on 17 June 2017 -- it's nigh on impossible to follow the thread between those two dates with the interspersed other comments and references.
Prevent EIP20 API Approve / TransferFrom multiple withdrawal attack
I seek clarity on how to effectively prevent the double withdrawal attack described in ERC20 API: An Attack Vector on Approve/TransferFrom Methods
Summary / example of the attack:
EIP20 says concerning
approve()
:I'm confused as to why this check should be passed to the UI, and the contract shouldn't enforce it.
How is the UI to know that the
approve(spender, 0)
transaction will be processed before the subsequent non-zero approval, and not the other way around? It seems it is not possible to do this check via the Web3 API.If the contract doesn't enforce this, then isn't anyone not using a UI still able to effect the attack?
I also note the lowercase
shouldn't
in "[t]he contract itself shouldn't enforce it", from which one may infer a different meaning to an RFC2119 "SHOULD NOT". I've raised my issues with the wording of this paragraph here.EIP20 refers readers to the MiniMeToken implementation regarding this issue which works around it by adding the line:
Interestingly the nimiq-exchange-token breaks the standard with this line:
This prevents fully cancelling an allowance after it is established (the only way would be via a
transferFrom()
of the total allowance amount)EIP20 refers readers to two example token implementations (I've linked to the relevant line numbers):
The MiniMeToken function comment says:
Given this is the reference implementation, I would like to be a lot more confident than "a little bit safer".
I'm also a bit confused as to why a contract implementation is given as an exemplar when the text of EIP20 says that this should be implemented in the UI. This seems inconsistent.
Regarding ERC223, @Dexaran asked:
I hope that the lack of reply (AFACT) means that fallback and the current ERC223 recommended implementation resolves this issue, but frankly I don't know enough about RFC223.
Questions:
approve()
MAY / SHOULD / MUST return false are not currently mentioned. Does this issue necessitate the return value to be specified?Please note that I am looking for Ethereum related work starting January 2018.
The text was updated successfully, but these errors were encountered: