Transaction status is 1, but last opcode is REVERT
See original GitHub issueI have a project that uses brownie and ganache-cli --fork against a geth node. (Geth is running according to these steps).
A few of my tests check the return_value of my transactions. Most succeed, but one has no return value despite not reverting.
- I asked about this on gitter: [X]
- Link to my question on gitter: https://gitter.im/ConsenSys/truffle?at=5ed03f164412600ccd7497f0
Expected Behavior
A transaction with a status of 1 should have a return value.
Current Behavior
- eth_getTransactionReceipt.status is 1
- debug_traceTransaction final instruction is REVERT
Steps to Reproduce
- git clone https://github.com/SatoshiAndKin/argobytes-contracts-brownie (at ecf07c4)
- Follow the readme
./scripts/test.sh tests/test_uniswap_v1_arbitrage.py -I
./scripts/test.sh tests/test_uniswap_v1_arbitrage.py -I
+ [ -z /home/ski/code/argobytes-contracts-brownie/venv ]
+ brownie test --network mainnet-fork tests/test_uniswap_v1_arbitrage.py -I
Brownie v1.8.9 - Python development framework for Ethereum
===================================================================================== test session starts =====================================================================================
platform linux -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /home/ski/code/argobytes-contracts-brownie
plugins: eth-brownie-1.8.9, forked-1.1.3, web3-5.10.0, hypothesis-5.15.0, xdist-1.32.0
collecting ... Attached to local RPC client listening at '127.0.0.1:8575'...
collected 1 item
tests/test_uniswap_v1_arbitrage.py F
address_zero = '0x0000000000000000000000000000000000000000', argobytes_atomic_trade = <ArgobytesAtomicTrade Contract '0xF024fE5EF0b1Bf88caf9B1222E49d1A5CC312a71'>
dai_erc20 = <Dai Contract '0x6B175474E89094C44Da98b954EedeAC495271d0F'>, argobytes_owned_vault = <ArgobytesOwnedVault Contract '0xb66F46436fa703237A9Fd26f4DA63919D3cc943D'>
example_action = <ExampleAction Contract '0xDb43EFA90874d427e38Ff1e5F08572c0a2619930'>, chi = <ChiToken Contract '0x0000000000004946c0e9F43F4Dee607b0eF1fA1c'>
uniswap_v1_factory = <Vyper_contract Contract '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'>, uniswap_v1_action = <UniswapV1Action Contract '0x006ba56B025c63aE46c510a904422945F2389d6F'>
usdc_erc20 = <FiatTokenProxy Contract '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'>
def test_uniswap_arbitrage(address_zero, argobytes_atomic_trade, dai_erc20, argobytes_owned_vault, example_action, chi, uniswap_v1_factory, uniswap_v1_action, usdc_erc20):
assert argobytes_owned_vault.balance() == 0
assert example_action.balance() == 0
value = 1e18
# send some ETH into the vault
accounts[0].transfer(argobytes_owned_vault, value)
# send some ETH into the sweep contract to simulate arbitrage profits
accounts[0].transfer(example_action, value)
# mint some gas token
# TODO: how much should we make?
argobytes_owned_vault.mintGasToken(chi, 26, {"from": accounts[0]})
# make sure balances match what we expect
assert argobytes_owned_vault.balance() == value
assert example_action.balance() == value
usdc_exchange = uniswap_v1_action.getExchange(uniswap_v1_factory, usdc_erc20)
dai_exchange = uniswap_v1_action.getExchange(uniswap_v1_factory, dai_erc20)
# sweep a bunch of times to use up gas
encoded_actions = argobytes_atomic_trade.encodeActions(
[
example_action,
uniswap_v1_action,
uniswap_v1_action,
uniswap_v1_action,
],
[
# add some faked profits
example_action.sweep.encode_input(uniswap_v1_action, address_zero),
# trade ETH to USDC
# uniswap_v1_action.tradeEtherToToken(address to, address exchange, address dest_token, uint dest_min_tokens, uint trade_gas)
uniswap_v1_action.tradeEtherToToken.encode_input(uniswap_v1_action, usdc_exchange, usdc_erc20, 1, 0),
# trade USDC to DAI
# uniswap_v1_action.tradeTokenToToken(address to, address exchange, address src_token, address dest_token, uint dest_min_tokens, uint trade_gas)
uniswap_v1_action.tradeTokenToToken.encode_input(
uniswap_v1_action, usdc_exchange, usdc_erc20, dai_erc20, 1, 0),
# trade DAI to ETH
# uniswap_v1_action.tradeTokenToEther(address to, address exchange, address src_token, uint dest_min_tokens, uint trade_gas)
uniswap_v1_action.tradeTokenToEther.encode_input(address_zero, dai_exchange, dai_erc20, 1, 0),
],
)
arbitrage_tx = argobytes_owned_vault.atomicArbitrage(
chi, argobytes_atomic_trade, address_zero, [address_zero], value, encoded_actions, {'from': accounts[1]})
assert argobytes_owned_vault.balance() > value
# make sure the transaction succeeded
# there should be a revert above if status == 0, but something is wrong
assert arbitrage_tx.status == 1
> assert arbitrage_tx.return_value is not None
E AssertionError: assert None is not None
E + where None = <Transaction '0x903f37e1596487075620d2c83dea892287b553c0147d97fb8bf4642a2083e177'>.return_value
tests/test_uniswap_v1_arbitrage.py:67: AssertionError
Interactive mode enabled. Use quit() to continue running tests.
>>> arbitrage_tx.trace[-1]['op']
'REVERT'
>>> arbitrage_tx._trace[-1]['op']
'REVERT'
>>>
Context
Due to previous issues with reverting traces pointing to incorrect lines, I’ve disabled solc’s runs, so that shouldn’t be the problem.
I suspected that gastoken2/chi might be related to the issue, but removing that code didn’t change anything.
I’m sure the transaction isn’t actually reverting because my test balance increases after the transaction is completed. If the transaction had reverted, the balance would not increase.
I don’t think Brownie is the problem here. Brownie just gets the trace from ganache.
Your Environment
- Version used: ganache-cli 6.9.1 and 6.10.0-beta.1
- Version of Truffle/Remix/Other tools used: eth-brownie-1.8.9
- NodeJS Version: [ ] 6.x, [ ] 7.x (unsupported), [ ] 8.x, [ ] 9.x, [x] v12.16.3
- Operating System and version (include distro if Linux): Ubuntu 20.04
- Link to your project or repro gist: https://github.com/SatoshiAndKin/argobytes-contracts-brownie
- Commit hash to use with above link for reproduction: ecf07c4
- I intend to submit a pull request to fix this issue: [ ]
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:27 (18 by maintainers)
Top GitHub Comments
Quick update here: I’ve figured out the root cause of @WyseNynja’s bug (at least the next hurdle haha). I can reproduce it in a test, and hoping to get over this one soon!
Yes! My tests so far are much better. I haven’t had time to finish them all (been working on proxy contracts instead), but the ones that were failing are passing now. Thank you!