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
Stack underflow in unreachable ERC20.transfer #1511
Comments
More generally, this seems to be an issue whenever I have something in the form of
And the condition evaluates to |
More simply, it looks like it might be: if condition:
external_call()
# else:
# nothing (stack underflow in this case) Can anyone confirm this with a MWE that's not a token? |
That seems to be correct. I've run the following example
with this Example.vy:
And as expected, calls to |
Note on this - if the external call only transfers ETH, i.e.:
I get no error. But, if using erc20:
and the else clause fires, I get stack underflow |
Perhaps a simpler repro: @public
@payable
def doit():
if False:
raw_call(msg.sender, b"", outsize=0, value=0, gas=msg.gas) |
the if statement translates to JUMPI
PUSH1 0
ISZERO
_sym_4
and _sym_4 is
_sym_4
JUMPDEST
POP # <-- this doesn't seem right ..
STOP this seems to be the source of that POP: |
@charles-cooper Why do you think the issue relates to I think the issue has to do with valency. The external call has a valency of 1 because it pushes the memory location of the output to the stack. So: if False:
# here we leave something on the stack
else: # implicit
# here we don't This line means we treat the entire I don't have much experience with the Vyper compiler, so it's hard for me to suggest or implement a fix. Intuitively, I think |
@smarx nice digging, that looks like you are on the right track. I don't have much time to look into this today but you could also take a look at |
I left out some of the debugging, sorry. This appears to be where the extra It's there because the valency of the sequence is 1 because the valency of the I was testing this Vyper: @public
@payable
def doit():
if False:
raw_call(msg.sender, b"", outsize=0, value=0, gas=msg.gas) which compiles to this IR:
|
@smarx I think your approach is good. If you wanted, I think (not at a keyboard so this is off the top of my head) you could change the valency of LLL |
(related: #1468 (comment)) |
I believe both branches are already wrapped in a |
also related: #1154 |
Version Information
vyper --version
): 0.1.0b10python --version
): 3.7.3pip freeze
):What's your issue about?
Transfer to an ERC20 token returns stack underflow if it is in an if clause that never gets executed, but works without the if clause.
Contract ERC20DummyToken.sol:
Contract vyperIssue.vy:
test.js:
Returns:
The test succeeds if I remove the if clause:
The text was updated successfully, but these errors were encountered: