Closed albert-llimos closed 1 year ago
We already do something similar to option 3: the validators estimate gas, which involves (I believe) executing the tx in a sandboxed environment. This is enough to detect, for example, signature errors before submitting the transaction.
As long as we can reliably and independently witness that a tx reverted (and this seems to be the case given the links you posted above), then I think this is the correct long-term solution.
Great, that's music to my ears. :smile:
Let's see what you think about this other one to make sure we are aligned.
We have the executeActions()
function that is used by the StateChain to execute arbitrary actions such as CheapChain related stuff (move USDC between chains).
This is not CCM paid by the user, so reversion due to gas is irrelevant. Reversion due to logic can happen. If that happens, it might be a good idea to catch the reversion so the transaction doesn't revert. This is because if the transaction reverts, then the nonce won't be consumed so anyone can try to execute that later on. It might happen that at some point in the future the transaction passes.
We'd rather have it not revert and consume the nonce, assuming I can nicely do that in the smart contracts. Then on the Statechain we can react to a fail event (similar to TransferFailed event). Do you agree?
Hmmm hard to say without specifics... generally speaking though I'd prefer to maintain the current assumption that transactions always succeed. I think this is what you're proposing.
Closing this as the item left regarding executeActions
is in #338
My understanding is that the StateChain currently expect all transactions signed by the AggKey to not revert aka successfully execute. That's why currently we sign a transaction and hand it to a validator to broadcast it. If after some time we have not witnessed the
SignatureAccepted
event we appoint another validator to do it, and it keeps going.However, there is an issue with cross-chain message calls - these transactions can revert, as the user/DEX-Agg can be doing any action. In fact, my view is that we should expect reversions as anything can happen when calling external contracts. Reversions can happen due to the logic reverting or due to not having enough gas. This second scenario will happen from time to time as the user is the one paying for the gas and we will somehow set a limit. The issue becomes that we are no longer expecting all transactions to pass, and in case of cross-chain messaging transactions we should not be retrying every time, as most likely a transaction that fails once will continue to fail indefinitely. The problem is that we currently don't have a way to know if a transaction has reverted or if the validator has decided to not send it, and we must therefore appoint another validator to do that task after a timeout. As mentioned, for normal transactions we want to keep retrying, but for CCM we want to try once and if it fails either allow the user to top-up gas (future feature) or just allow the user to broadcast it themselves. We don't want to keep trying as the validators will just waste gas retrying transactions that fail.
So far I have come up with two solutions:
1- Ensure at the smart contract level that transactions don't revert neither due to gas nor logic. Then emit an event e.g. "CCMCallFailure". I initially thought this was the best solution, but then I realized that it has problems:
2- Trying to witness a reverted transaction. A reverted transaction won't emit any events, so we can't really witness that. But if we could witness the reverted transaction and the reason (gas vs other) then we can just then allow the users to top-up or to send the TX themselves with any amount of gas. Then not make any validator try again. Since the nonce has not been consumed, they can send it as is.
3- A twist to option two would be that if the validator expects a reversion when it's about to send it, it can signal back to the SC that the transaction is not valid. You can get the reversion reason even before sending it. Some libraries/tools, by default, don't even let you send the transaction. Then if enough validators do that, we consider that the transaction "has reverted".
While any of the two last solutions mean work on the SC/CFE side, I think these are the best options at the moment. I have checked Axelar and I do believe they do something similar to option 2 or 3. https://docs.axelar.dev/dev/general-message-passing/debug/error-debugging
Just fyi, here's an example of a reverted TX due to gas and due to logic: https://etherscan.io/tx/0xda8c0b80d8e240a83c8f6b067c4656babeb13e8e0ece4fd4292aa06252f1285c https://etherscan.io/tx/0x310efedeea02d9232ba36a2f8499f83c1934d6b2068d4726778c1f7da59e66b9
I'd be happy to make a fix in the smart contracts, but as I described I'm not sure that is the way to solve the problem. Also happy to listen to more ideas.
Also, fwiw, I'd say that in the long term witnessing reverted transactions is probably the way to go. Eventually there will be a failed transaction that we expect to succeed and we probably want the SC to react to it appropriately.