Cross-chain execution

How to do more with less
In order to save gas, we don't run the full battle engine at the Ethereum layer. We use it as an interface to a cheaper L2, in our case, Arbitrum, which also provides us with extra security due to their rollups.
We still do perform some crucial checks in the L1, like NFT ownership, but we offload as much as possible to the L2.
To achieve that, we use Axelar to send messages from L1 to L2 and vice versa. That means that our flows (like join Battle Royale queue and execute Battle Royale) are asynchronous. The full process is as follows:
  1. 1.
    A transaction is sent to the Ethereum network
The transaction will require a small amount of ETH apart from the transaction gas fee that will be used by Axelar to pay for the gas of executing the transaction at the destination L2. Since this is the cost for a L2 transaction execution, it translates to a negligible overhead.
  1. 2.
    Axelar propagates the message from L1 to L2
Axelar uses the ether provided in the 1st step to execute the desired message at the destination chain, after the message has reached the Axelar network. See Monitor cross-chain actions for more details.
  1. 3.
    The operation is executed at the target L2
Here is where we execute expensive operations, like running the battle engine to resolve a Battle Royale, saving users hundreds of dollars in gas cost. This also allows for way more complex mechanics to be run, as the costs would increase exponentially on L1, but not on the L2.
  1. 4.
    In some cases, another message is sent back to L1 - for example, to execute the prize payment to the game mode winner
In some flows, like when a Battle Royale is fully executed, we need to use the L1 smart contract again to perform a final transfer of the total Battle Royale prize to the winner. This finishes the flow and cleans up the state.