Analog-Labs / analog-gmp-examples

Gateway smart contract and GMP testing suites
MIT License
24 stars 34 forks source link

Arithmetic underflow/overflow when calling `relayMessages()` #15

Open Nlferu opened 2 weeks ago

Nlferu commented 2 weeks ago

Hi Team,

I have recently encounter below error: ← [Revert] panic: arithmetic underflow or overflow (0x11). I figured out that it is caused by calling GmpTestTools.relayMessages(); second time in same test.

What exactly I did to get this error?

  1. Created function test_teleportTokens() and everything I did below is under this single test.
  2. Prepared whole setup, deployed source and destination contracts on 2 different chins
  3. I minted some NFT tokens on source chain.
  4. I have sent cross-chain message to destination chain triggering mint same tokens on destination chain
  5. Called GmpTestTools.relayMessages(); to actually perform sent messages from source to dest chain
  6. Everything worked perfectly fine now we have same tokens minted on source and destination chain
  7. Now I called transfer tokens on destination chain to other user -> this triggered another cross-chain message from dest to source chain this time to update tokens ownership.
  8. Transaction passes, so I call GmpTestTools.relayMessages(); second time in same test to trigger proper function on source chain this time
  9. I receive mentioned Arithmetic underflow/overflow error
  10. I created second function test_teleportTokensBackward and I just recreated second part of 1st test, so sending tokens from dest to source chain and this test passes without any problem
  11. Conclusion -> my contracts and logic are built fine, but somehow relayMessage() function is bugging out while called 2nd time in one go.

So my question is, how do I avoid this issue? Do I need to somehow reset relayMessages before calling it 2nd time or do I need to do something else or this is currently unavoidable and only way to test things is to just use Arithmetic underflow/overflow when calling relayMessages() function just one time per test function?

Nlferu commented 1 week ago

Hi @Lohann

Thank you for taking a look into this. Let me know if you need more details or code examples.

There is also another thing I would like to ask about. In usual tests we use setUp() function to execute some code before every single test in our Test.t.sol, and if we put GmpTestTools.setup() in setUp() function and run tests one by one with foundry --mt flag everything works good. But if we run forge test, so all tests at once then this error pops up: [FAIL: setup failed: vm.createFork: Could not instantiate forked environment with fork url: https://evm.shibuya.astar.network] setUp() (gas: 0) or [FAIL: backend: failed while inspecting]. If you have any idea how to solve this one as well it would be great. Thank you in advance for your time and help

EDIT: Ok I have found workaround that we need to just switch network at the end of setUp() function or at the beginning of test(), but I cannot figure out, which approach is correct because one time only switching network at the end of setUp works and other time only switching network at the beginning of test works. If you could explain this to me that would be great :)

Lohann commented 1 week ago

Hi @Nlferu, thank you for reporting this issue, will investigate. Are you using the examples from this repo? is there a easy way to reproduce this issue?

Lohann commented 1 week ago

we put GmpTestTools.setup() in setUp() function and run tests one by one with foundry --mt flag everything works good. But if we run forge test, so all tests at once then this error pops up: [FAIL: setup failed: vm.createFork: Could not instantiate forked environment with fork url https://evm.shibuya.astar.network] setUp() (gas: 0) or [FAIL: backend: failed while inspecting].

I see, if you can provide some setup or way to reproduce the issue will be a great help, also make sure you are using the latest forge command line tool version, we found some issues in previous versions.

Nlferu commented 1 week ago

@Lohann

You can clone my repo: https://github.com/Nlferu/analog-cross-chain.

Now to reproduce arithmetic underflow or overflow error just go into test folder -> CrossChainTest.t.sol -> test_updateOwnershipOfTokensAfterTransferOnDestinationChain and just uncomment last line like below:

FROM:

        /// @dev TO BE FIXED AS 'REPLAY' CANNOT BE CALLED TWICE
        // Simulate this behavior by calling `GmpTestTools.relayMessages()`, this will relay all pending messages.
        // vm.expectEmit(true, true, true, true, address(source));
        // emit SourceNFT.InboundOwnershipChange(newMsgID, USER, DEVIL, dest_tokens);
        // GmpTestTools.relayMessages();

TO:

        /// @dev TO BE FIXED AS 'REPLAY' CANNOT BE CALLED TWICE
        // Simulate this behavior by calling `GmpTestTools.relayMessages()`, this will relay all pending messages.
        vm.expectEmit(true, true, true, true, address(source));
        emit SourceNFT.InboundOwnershipChange(newMsgID, USER, DEVIL, dest_tokens);
        GmpTestTools.relayMessages();

Now just run this test with: forge test --mt test_updateOwnershipOfTokensAfterTransferOnDestinationChain -vvvv and you will receive this error.

To reproduce 2nd error just go into test -> PrototypeTest.t.sol then in setUp() function at the end comment out below:

        /// @dev We need to end `setUp` with main network ([0]) in networks array
        GmpTestTools.switchNetwork(SEPOLIA_NETWORK, OWNER);

Then simply run forge test and you should receive [FAIL: backend: failed while inspecting]

Let me know in case you would need anything else