.github
    workflows
        rust.yml
Cargo.toml
README.md
config.toml
integration_tests
    README.md
    __init__.py
    generate_rlp_evm_txn.py
    integration_test.py
    requirements.txt
src
    main.rs
    structs.rs
    util.rs
tests
    tests.rs

# multichain-relayer-server
Pagoda Implementation of Multichain Relayer Server facilitating cross chain transactions enabling Chain Abstraction.

NOTE: this is not production ready yet. Production ready version will be available by March 31. Feel free to experiment in the meantime. 

## Technical System Design
Below is a Design Diagram of the entire multichain relayer system.

- The [gas station contract](https://github.com/near/multichain-gas-station-contract) and the [mpc signing service contract](https://github.com/near/mpc-recovery/tree/main/contract) are in the green box which take place on NEAR.
- This multichain relayer server repo focuses on the purple/blue Multichain Relayer Core Backend Services Box in the middle and the connections to the XChain systems in the red box via RPCs.
- The XChain Settlement that's happening in the yellow box is currently manual and will be automated in the future.

![multichain_relayer_technical_design.png](multichain_relayer_technical_design.png)

## Technical System Description
1. The wallet sends a NEAR transaction to the gas station contract that contains 2 actions
   1. A transfer of NEAR (or FT Transfer in the future) to cover gas on the foreign chain
   2. A `create_transaction` function call to the gas station contract `canhazgas.testnet` containing the unsigned foreign chain transaction to be signed by the MPC signing service, assuming the unsigned transaction passes validation.
2. The Gas Station Contract calls the MPC signing service to sign both a funding transaction, which ensures the user's foreign chain account has sufficient gas to execute the desired transaction, and signs the unsigned foreign chain transaction.
3. Upon receipt of both the signed transactions, the Gas Station Contract emits an event which is picked up by the indexer, which then calls the `/send_funding_and_user_signed_txns` with the 2 signed transactions from the indexer.
4. The multichain relayer server sends the funding transaction to the foreign chain RPC to fund the user's account with gas.
5. After the gas funding transaction is confirmed, the multichain relayer server calls the foreign chain RPC again to send the signed transaction initiated by the user in step 1.
6. The Cross Chain Settlement takes care of selling the extra NEAR being sent to the gas station contract for gas tokens on foreign chains as well as bridging the tokens to the other chains. This process is currently manual, but will be automated in partnership with market makers in the future.

## Supported Chains
- BSC testnet
- BSC Mainnet 
- ETH Sepolia Testnet 
- ETH Mainnet 
- More chains coming soon!

## Multichain Relayer Description
- The main function of this server is interfacing with foreign chain RPCs sending both presigned funding transactions to cover gas and the actual presigned transaction once the funding is done. 
- The Multichain relayer is meant to be deployed alongside the [gas-station-event-indexer](https://github.com/near/gas-station-event-indexer) on the same server so that the gas station event indexer can call the multichain relayer server via IPC instead of having to send the request over the network introducing extra latency to the system.
- Although the multichain relayer is a server in current design of this system, the goal is to package this as a library that can be called on the client side of the wallet. This will make the system more decentralized.
 

## Functionality
1. `/send_funding_and_user_signed_txns` which handles both
   1. Funding the user's xchain account with gas from the paymaster treasury account, which is provided as a raw signed transaction
   2. Sending the user's raw signed transaction (in hexadecimal in EVM case) after the funding transaction has been confirmed on the foreign chain
2. (MVP only) `/get_balance_for_account` endpoint that gets the native gas token (BNB) balance for an account. AKA Poor man's indexing

## Total Time Expectations for the End User
It depends on the chain, but in our current estimation 50-90% of the time will be on NEAR calling and waiting for the signing to complete on the MPC service. 
The signing service will take 15-30 seconds. 
We assume that both the signing of the foreign chain transaction and the gas funding transaction happen in parallel. 
On BSC mainnet (not beaconchain which has 1 second finality) with 3 second blocktimes there should be 2 blocks for confirmation optimistically bringing the total to 6 seconds optimistically/transaction on BSC. 
We need to make 2 transactions, so that's 12-24 seconds on BSC assuming 2-4 blocks for finality. Add in some network overhead for each step in the process, especially the indexer picking up the emitted event (~5-7 seconds), and we're at 30-60 seconds/transaction on BSC. 
For Solana it would be closer to 20-30 seconds (0.4 second block time, 1 block confirmation). See table 1 of https://usa.visa.com/solutions/crypto/deep-dive-on-solana.html for more confirmation times. 

L2 real finality times can over a day for finality unless we trust a centralized sequencer for soft confirmations, which may be as fast as a few seconds as in the case of zksync era https://era.zksync.io/docs/reference/concepts/finality.html#instant-confirmations.

The difference between optimistic or soft confirmations vs real finality is something we should consider. We may get better finalized guarantees when the Eigenlayer-Near Partnership is live https://pages.near.org/blog/near-foundation-and-eigen-labs-partner-to-enable-faster-cheaper-web3-transactions-for-ethereum-rollups-via-eigenlayer/. 3-4 second finality for all ETH L2s is much more manageable.

## Future Directions
### Scale:
- Moar Chainzzz
- Better Capital Efficiency with ~real-time settlement using Orderly + professional Market Makers
### Decentralization:
- Replace Multichain Relayer Server with Client Side Libraries
- Multiple Market Makers running Relayer Servers
- Txn Trie Inclusion Proofs
### Broader Wallet Support:
- Provide Chain Abstraction Services to wallets that don’t implement MPC
### Intent Relayers
- AI is able to execute appropriate transactions on behalf of the user getting them the best price across all chains. 
  - This involves aggregating and indexing FT, NFT market dapps.
  - i.e. User has **_SWEAT_** they'd like to **_swap_** for **_BTC_**. From these keywords, AI calls multichain relayer services to execute this action on their behalf. The actual execution may look like the user's SWEAT is sold on Orderly on the NEAR chain and they end up receiving WBTC on SOL account.
Instructions on how to run end-to-end tests on the entire multichain relayer system.  
# Run
1. Update the transaction details of the EVM transaction you want to send in `generate_rlp_evm_txn.py` then run the script and save the RLP hex string output. 
   1. If that doesn't work, try running the `generate_eip1559_rlp_hex()` test in tests/tests.rs - python and rust output different hex rlp excoded txns :/  
   
2. Ensure the [gas station indexer](https://github.com/near/gas-station-event-indexer/tree/main) is running locally
3. Ensure the multichain server is configured correctly (`config.toml`) and running: `cargo run`

4. Construct the signed transaction using the [near-cli-rs](https://github.com/near/near-cli-rs).
   The receiver account ID should be the gas station contract.
   You will need 2 actions if you want the gas station to cover your gas cost on the foreign chain:
   1 to send the NEAR equivalent and 1 function call to the gas station.
   You should transfer the amount of NEAR that's needed to cover gas both on NEAR and on the foreign chain.
   You also need to paste in the RLP generated hex for the EVM transaction you want on the other chain generated in step 1.
   When it asks you to send or display, choose send.
   Example below:
```shell
near contract call-function as-transaction canhazgas.testnet create_transaction json-args '{"transaction_rlp_hex":"eb80851bf08eb000825208947b965bdb7f0464843572eb2b8c17bdf27b720b14872386f26fc1000080808080","use_paymaster":true}' prepaid-gas '100.000 TeraGas' attached-deposit '0.5 NEAR' sign-as nomnomnom.testnet network-config testnet sign-with-keychain send
```
5. Get the `"id"` from the receipts from the call in step 4, and use that to call `sign_next` twice:
- `near contract call-function as-transaction canhazgas.testnet sign_next json-args '{"id":"16"}' prepaid-gas '300.0 Tgas' attached-deposit '0 NEAR' sign-as nomnomnom.testnet network-config testnet sign-with-keychain send`

Optional for testing purposes:
- Instead of creating the signed txn and calling the gas station contract to sign the transaction, you can get the recently signed transactions by calling: 
  - `near contract call-function as-read-only canhazgas.testnet list_signed_transaction_sequences_after json-args '{"block_height":"157111000"}' network-config testnet now` replacing the blockheight with a more recent blockheight
  - This will return something like the output below. Take an individual entry in the list of jsons and send that as the payload of a POST request to the `/send_funding_and_user_signed_txns` endpoint:
```json
[
  {
    "created_by_account_id": "b807806adcb73f6aecb5ed98bb8bd7bbe7bbf8ed342596ab700ef6b050abc4c3",
    "foreign_chain_id": "97",
    "signed_transactions": [
      "0x02f873610385174876e80085174876e80082520894c89663ac6d169bc3e2e0a99d9fe96f2e82bcc307870eebe0b40e800080c080a0712d44ba4cd7567764231e21f054c5e7d008055222820e9d5ba148ede48755f7a06e8b812d37047593fc51fce7254ea7aef89927cada729bc903cd36fa9659dce4",
      "0x02f873618085174876e80085174876e80082520894ef55a8bdf4498ea0af88bc54efb29608bb25e130872aa1efb94e000080c080a017d7024fe9e32ad8da1181729fac7e6a45311c47bf59f2b5a8b5e9fe002c0617a04ad725b362cf12c6e066c5b0b7ecbbf08f5e4d0a240337e6ddc8076f0528e3e5"
    ]
  },
...
  {
    "created_by_account_id": "b807806adcb73f6aecb5ed98bb8bd7bbe7bbf8ed342596ab700ef6b050abc4c3",
    "foreign_chain_id": "97",
    "signed_transactions": [
      "0x02f873610185174876e80085174876e80082520894c89663ac6d169bc3e2e0a99d9fe96f2e82bcc307870eebe0b40e800080c001a0ff19fe769246de8483b986e5aeaa3360bfb74f238e2a91ea353dac9aad9e24a0a020485dcd2c64172b9bc058b7813646dafbf2f27d51aae388b074e514fdb6de05",
      "0x02f873618085174876e80085174876e80082520894ef55a8bdf4498ea0af88bc54efb29608bb25e130872e2f6e5e14800080c001a0dac67c383e8de3211f3c5d360cc2e9a21d160711fc3f80113ac525169317e2eca07140a1d0d1528b6eaf9fac4bb1bd44c1c4f63bb956292b0211a0dad1748e2eea"
    ]
  }
]
```
