-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Replace transfer (deprecated) occurrences with call in smt tests
#16291
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
base: deprecation_warnings
Are you sure you want to change the base?
Conversation
c55108b to
d97549f
Compare
50bc5f0 to
3b6fdc2
Compare
cameel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a look from @blishko.
Looks like some of the balance tests actually do depend on properties of transfer() and SMTChecker is not able to prove the same things with call(). We'd need something else to replace it.
Also, some of the CLI tests for specific targets have empty output for those targets, which means we're not actually testing that the things works.
I'm not sure how much of it is actually worth fixing. We plan to deprecate BMC in 0.9 anyway. Some of these apply to CMC though.
| --> input.sol:13:3: | ||
| a.call{value: x}("") -- untrusted external call | ||
| --> input.sol:14:3: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... so transfer() was not treated as an untrusted external call but call() is? Perhaps SMTChecker should treat call() with empty payload and a gas limit specially?
| Note: Callstack: | ||
| Note: | ||
|
|
||
| Warning: BMC: Insufficient funds happens here. | ||
| --> input.sol:10:3: | ||
| | | ||
| 10 | a.transfer(x); | ||
| | ^^^^^^^^^^^^^ | ||
| Note: Counterexample: | ||
| a = 0 | ||
| x = 0 | ||
|
|
||
| Note: Callstack: | ||
| Note: | ||
| Note: | ||
| Note that external function calls are not inlined, even if the source code of the function is available. This is due to the possibility that the actual called contract has the same ABI but implements the function differently. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently SMTChecker can figure this out with transfer() but not with call()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like SMTChecker can no longer detect insufficient balance when we use call(). Since this is the point of the test, we should replace it with something that actually does trigger this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, we could also keep transfer() in this particular test. There's a chance we'll drop BMC before we drop transfer() and send() anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, but we're not dropping CHC, so this one needs an actual fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like SMTChecker fails to detect the constant condition here (though it was like this already before this PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another case where the target is not actually reported.
| "component": "general", | ||
| "errorCode": "9207", | ||
| "formattedMessage": "Warning: 'transfer' is deprecated and scheduled for removal in the next breaking version (0.9). Use 'call{value: <amount>}(\"\")' instead. | ||
| --> A:11:7: | ||
| | | ||
| 11 | \t\t\t\t\t\ta.transfer(x); | ||
| | \t\t\t\t\t\t^^^^^^^^^^ | ||
|
|
||
| ", | ||
| "message": "'transfer' is deprecated and scheduled for removal in the next breaking version (0.9). Use 'call{value: <amount>}(\"\")' instead.", | ||
| "severity": "warning", | ||
| "sourceLocation": { | ||
| "end": 234, | ||
| "file": "A", | ||
| "start": 224 | ||
| }, | ||
| "type": "Warning" | ||
| }, | ||
| { | ||
| "component": "general", | ||
| "errorCode": "4661", | ||
| "formattedMessage": "Warning: BMC: Assertion violation happens here. | ||
| --> A:12:7: | ||
| | | ||
| 12 | \t\t\t\t\t\tassert(x > 0); | ||
| | \t\t\t\t\t\t^^^^^^^^^^^^^ | ||
| Note: Counterexample: | ||
| a = 0 | ||
| x = 0 | ||
|
|
||
| Note: Callstack: | ||
| Note: | ||
|
|
||
| ", | ||
| "message": "BMC: Assertion violation happens here.", | ||
| "secondarySourceLocations": [ | ||
| { | ||
| "message": "Counterexample: | ||
| a = 0 | ||
| x = 0 | ||
| " | ||
| }, | ||
| { | ||
| "message": "Callstack:" | ||
| }, | ||
| { | ||
| "message": "" | ||
| } | ||
| ], | ||
| "severity": "warning", | ||
| "sourceLocation": { | ||
| "end": 258, | ||
| "file": "A", | ||
| "start": 245 | ||
| }, | ||
| "type": "Warning" | ||
| } | ||
| ], | ||
| "sources": { | ||
| "A": { | ||
| "id": 0 | ||
| "formattedMessage": "parse error at line 7, column 458: syntax error while parsing object - unexpected string literal; expected '}'", | ||
| "message": "parse error at line 7, column 458: syntax error while parsing object - unexpected string literal; expected '}'", | ||
| "severity": "error", | ||
| "type": "JSONError" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the expected output here. I think you broke it by not escaping the quotes in JSON.
| function shouldHold() public { | ||
| uint tempAmount = address(this).balance; | ||
| recipient.transfer(tempAmount); | ||
| recipient.transfer(amount); | ||
| (bool success, ) = recipient.call{value: tempAmount}(""); | ||
| require(success); | ||
| (success, ) = recipient.call{value: amount}(""); | ||
| require(success); | ||
| } | ||
| } | ||
| // ==== | ||
| // SMTEngine: chc | ||
| // ---- | ||
| // Warning 9207: (133-151): 'transfer' is deprecated and scheduled for removal in the next breaking version (0.9). Use 'call{value: <amount>}("")' instead. | ||
| // Warning 9207: (167-185): 'transfer' is deprecated and scheduled for removal in the next breaking version (0.9). Use 'call{value: <amount>}("")' instead. | ||
| // Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test no longer is proved safe with call().
|
How important is this right now? |
We will have to deal with it in some way eventually, because
Another option is also to wait for the PAY opcode and replace it with that. If it gets into Glamsterdam it could even happen before 0.9 ships :) Maybe just leaving it as is and going back to it when the bultins are actually removed is the best course of action here. But I was just wondering whether you'd still plan to address this properly or if we should rather assume that this will just become irrelevant at some point due to changing plans (deprecations, move to Core Solidity, new tool for verification at Yul level, etc.). |
|
I believe it will eventually become irrelevant, but we might need to fix it properly before that. So I would wait with this a bit to see if the situation is clearer in the future (e.g., the PAY opcode). |
|
ok. In that case in this PR we'll just replace the simple cases that cause no issues and leave the ones that do (e.g. the ones that are related to balance or specifically test |
transferis deprecated and will be removed in the next breaking release.depends on #16174.