# Transfer Tokens and Data Across Chains

This tutorial extends the programmable token transfer example. It uses GRE to transfer tokens and arbitrary data between smart contracts on different blockchains, with a focus on defensive coding in the recipient's contract. If a specified error occurs during GRE message reception, the contract locks the token. Locking tokens allows the owner to recover and redirect them as needed. Defensive coding is crucial because it restores locked tokens and ensures the protection of users' assets.\ <br>

## Before you start

1. You should know how to write, compile, deploy, and fund smart contracts. If you need to brush up on the basics, read this tutorial, which will guide you through using the Solidity programming language, interacting with the MetaMask wallet, and working in a Remix development environment.
2. Your account must have some ETH and GRE tokens on Ethereum Sepolia and MATIC tokens on Polygon Mumbai. Learn how to get a test network GRE.&#x20;
3. Check the "Supported Networks" page to confirm that your channel supports the token you want to transfer. In this example, you will be transferring tokens from Ethereum Sepolia to Polygon Mumbai, so check the list of supported tokens here.&#x20;
4. Learn how to get a GRE test token. By following this guide, you should have a GRE-BnM token, and GRE-BnM should appear in the token list in MetaMask.&#x20;
5. Find out how to fund your contract. This guide shows how to fund your contract in GRE, but you can use the same guide to fund your contract with any ERC20 tokens, as long as they appear in MetaMask's token list.&#x20;
6. Follow the previous tutorial: Transferring Tokens and Data across chains to learn how to use GRE for programmable token transfer.

## Tutorials&#x20;

In this guide, you will initiate a transaction from a smart contract on Ethereum Sepolia, using GRE to send a string text and a GRE-BNM token to another smart contract on Polygon Mumbai. However, upon reaching the receiver contract, the processing logic will intentionally malfunction. This tutorial will demonstrate an elegant error handling method that allows contract owners to recover locked tokens.

#### Deploy your contracts <a href="#deploy-your-contracts" id="deploy-your-contracts"></a>

To use this contract:

1. Open the contract in Remix.
2. Compile your contract.
3. Deploy and fund your sender contract on *Ethereum Sepolia*:
   1. Open MetaMask and select the network *Ethereum Sepolia*.
   2. In Remix IDE, click on *Deploy & Run Transactions* and select *Injected Provider - MetaMask* from the environment list. Remix will then interact with your MetaMask wallet to communicate with *Ethereum Sepolia*.
   3. Fill in your blockchain's router and GRE contract addresses. The router address can be found on the supported networks page and the GRE contract address on the GRE token contracts page.&#x20;
   4. Click the **transact** button. After you confirm the transaction, the contract address appears on the *Deployed Contracts* list. Note your contract address.
   5. Open MetaMask and fund your contract with GRE-BnM tokens. You can transfer `0.002`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) *GRE-BnM* to your contract.
   6. Enable your contract to send GRE messages to *Polygon Mumbai*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Ethereum Sepolia*.
      2. Call the `allowlistDestinationChain` with as the destination chain selector, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed. Each chain selector is found on the supported networks page.
4. Deploy your receiver contract on *Polygon Mumbai*:
   1. Open MetaMask and select the network *Polygon Mumbai*.
   2. In Remix IDE, under *Deploy & Run Transactions*, make sure the environment is still *Injected Provider - MetaMask*.
   3. Fill in your blockchain's router and GRE contract addresses. The router address can be found on the supported networks page and the GRE contract address on the GRE token contracts page.&#x20;
   4. Click the **transact** button. After you confirm the transaction, the contract address appears on the *Deployed Contracts* list. Note your contract address.
   5. Enable your contract to receive GREmessages from *Ethereum Sepolia*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Polygon Mumbai*.
      2. Call the `allowlistSourceChain` with as the source chain selector, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed. Each chain selector is found on the supported networks page.
   6. Enable your contract to receive GRE messages from the contract that you deployed on *Ethereum Sepolia*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Polygon Mumbai*.
      2. Call the `allowlistSender` with the contract address of the contract that you deployed on *Ethereum Sepolia*, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed.
   7. Call the `setSimRevert` function, passing `true` as a parameter, then wait for the transaction to confirm. Setting `s_simRevert` to true simulates a failure when processing the received message. Read the explanation section for more details.
5. At this point, you have one *sender* contract on *Ethereum Sepolia* and one *receiver* contract on *Polygon Mumbai*. As security measures, you enabled the sender contract to send GRE messages to *Polygon Mumbai* and the receiver contract to receive GRE messages from the sender and *Ethereum Sepolia*. The receiver contract cannot process the message, and therefore, instead of throwing an exception, it will lock the received tokens, enabling the owner to recover them.

   **Note**: Another security measure enforces that only the router can call the `_greReceive` function. Read the explanation section for more details.

\
Deploy your contracts
---------------------

To use this contract:

1. Open the contract in Remix.
2. Compile your contract.
3. Deploy and fund your sender contract on *Ethereum Sepolia*:
   1. Open MetaMask and select the network *Ethereum Sepolia*.
   2. In Remix IDE, click on *Deploy & Run Transactions* and select *Injected Provider - MetaMask* from the environment list. Remix will then interact with your MetaMask wallet to communicate with *Ethereum Sepolia*.
   3. Fill in your blockchain's router and GRE contract addresses. The router address can be found on the supported networks page and the GRE contract address on the GRE token contracts page.&#x20;
   4. Click the **transact** button. After you confirm the transaction, the contract address appears on the *Deployed Contracts* list. Note your contract address.
   5. Open MetaMask and fund your contract with GRE-BnM tokens. You can transfer `0.002`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) *GRE-BnM* to your contract.
   6. Enable your contract to send GRE messages to *Polygon Mumbai*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Ethereum Sepolia*.
      2. Call the `allowlistDestinationChain` as the destination chain selector, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed. Each chain selector is found on the supported networks page.
4. Deploy your receiver contract on *Polygon Mumbai*:
   1. Open MetaMask and select the network *Polygon Mumbai*.
   2. In Remix IDE, under *Deploy & Run Transactions*, make sure the environment is still *Injected Provider - MetaMask*.
   3. Fill in your blockchain's router and GRE contract addresses. The router address can be found on the supported networks page and the GRE contract address on the GRE token contracts page.&#x20;
   4. Click the **transact** button. After you confirm the transaction, the contract address appears on the *Deployed Contracts* list. Note your contract address.
   5. Enable your contract to receive GRE messages from *Ethereum Sepolia*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Polygon Mumbai*.
      2. Call the `allowlistSourceChain` as the source chain selector, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed. Each chain selector is found on the supported networks page.
   6. Enable your contract to receive GRE messages from the contract that you deployed on *Ethereum Sepolia*:
      1. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Polygon Mumbai*.
      2. Call the `allowlistSender` with the contract address of the contract that you deployed on *Ethereum Sepolia*, and `true`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) as allowed.
   7. Call the `setSimRevert` function, passing `true` as a parameter, then wait for the transaction to confirm. Setting `s_simRevert` to true simulates a failure when processing the received message. Read the [explanation](https://docs.chain.link/ccip/tutorials/programmable-token-transfers-defensive#explanation) section for more details.
5. At this point, you have one *sender* contract on *Ethereum Sepolia* and one *receiver* contract on *Polygon Mumbai*. As security measures, you enabled the sender contract to send GRE messages to *Polygon Mumbai* and the receiver contract to receive GRE messages from the sender and *Ethereum Sepolia*. The receiver contract cannot process the message, and therefore, instead of throwing an exception, it will lock the received tokens, enabling the owner to recover them.

   **Note**: Another security measure enforces that only the router can call the `_greReceive` function. Read the explanation section for more details.

## Recover the locked tokens <a href="#recover-the-locked-tokens" id="recover-the-locked-tokens"></a>

You will transfer *0.001 GRE-BnM* and a text. The GRE fees for using GRE will be paid in GRE.

1. Open MetaMask and connect to *Ethereum Sepolia*. Fund your contract with GRE tokens. You can transfer `0.5`![Copy to clipboard](https://docs.chain.link/assets/icons/copyIcon.svg) *GRE* to your contract. In this example, GRE is used to pay the CGRE fees.
2. Send a string data with tokens from *Ethereum Sepolia*:

   1. Open MetaMask and select the network *Ethereum Sepolia*.
   2. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Ethereum Sepolia*.
   3. Fill in the arguments of the ***sendMessagePayGRE*** function:

      <br>

      <table><thead><tr><th width="197.99999999999997">Argument</th><th>Value and Description</th></tr></thead><tbody><tr><td>_destinationChainSelector</td><td>GRE Chain identifier of the destination blockchain (<em>Polygon Mumbai</em> in this example). You can find each chain selector on the supported networks page.</td></tr><tr><td>_receiver</td><td>Your receiver contract address at <em>Polygon Mumbai</em>.<br>The destination contract address.</td></tr><tr><td>_text</td><td><code>Hello World!</code><img src="https://docs.chain.link/assets/icons/copyIcon.svg" alt="Copy to clipboard"><br>Any <code>string</code></td></tr><tr><td>_token</td><td>The <em>CGRE-BnM</em> contract address at the source chain (<em>Ethereum Sepolia</em> in this example). You can find all the addresses for each supported blockchain on the supported networks page.</td></tr><tr><td>_amount</td><td><code>1000000000000000</code><img src="https://docs.chain.link/assets/icons/copyIcon.svg" alt="Copy to clipboard"><br>The token amount (<em>0.001 GRE-BnM</em>).</td></tr></tbody></table>
   4. Click on `transact` and confirm the transaction on MetaMask.
   5. After the transaction is successful, record the transaction hash. Here is an example of a transaction on *Ethereum Sepolia*.

   **Note**: During gas price spikes, your transaction might fail, requiring more than *0.5 GRE* to proceed. If your transaction fails, fund your contract with more *GRE* tokens and try again.
3. Open the GRE explorer and search your cross-chain transaction using the transaction hash.

   <br>
4. The GRE transaction is completed once the status is marked as "Success". <br>
5. Check the receiver contract on the destination chain:
   1. Open MetaMask and select the network *Polygon Mumbai*.
   2. In Remix IDE, under *Deploy & Run Transactions*, open the list of transactions of your smart contract deployed on *Polygon Mumbai*.
   3. Call the `getFailedMessagesIds` function to list the failed messages.

      <br>
   4. Notice the messageId&#x20;
6. To recover the locked tokens, call the `retryFailedMessage` function:

   <table><thead><tr><th width="207">Argument</th><th>Description</th></tr></thead><tbody><tr><td><code>messageId</code></td><td>The unique identifier of the failed message.</td></tr><tr><td><code>tokenReceiver</code></td><td>The address to which the tokens will be sent.</td></tr></tbody></table>

   <br>
7. After confirming the transaction, you can open it in a block explorer. Notice that the locked funds were transferred to the `tokenReceiver` address.

   <br>

**Note**: These example contracts are designed to work bi-directionally. As an exercise, you can use them to transfer tokens and data from *Ethereum Sepolia* to *Polygon Mumbai* and from *Polygon Mumbai* back to *Ethereum Sepolia*.

## Explanation <a href="#explanation" id="explanation"></a>

The smart contract featured in this tutorial is designed to interact with GRE to transfer and receive tokens and data. The contract code is similar to the *Transfer Tokens and Data Across Chains* tutorial. Hence, you can refer to its code explanation. We will only explain the processing of received messages.

#### Receiving and processing messages <a href="#receiving-and-processing-messages" id="receiving-and-processing-messages"></a>

Upon receiving a message on the destination blockchain, the `greReceive` function is called by the GRE router. This function serves as the entry point to the contract for processing incoming GRE messages, enforcing crucial security checks through the `onlyRouter`, and `onlyAllowlisted` modifiers.

Here's the step-by-step breakdown of the process:

1. Entrance through `greReceive`:
   * The `greReceive` function is invoked with an `Any2EVMMessage` struct containing the message to be processed.
   * Security checks ensure the call is from the authorized router, an allowlisted source chain, and an allowlisted sender.
2. Processing Message:
   * `greReceive` calls the `processMessage` function, which is external to leverage Solidity's try/catch error handling mechanism. **Note**: The `onlySelf` modifier ensures that only the contract can call this function.
   * Inside `processMessage`, a check is performed for a simulated revert condition using the `s_simRevert` state variable. This simulation is toggled by the `setSimRevert` function, callable only by the contract owner.
   * If `s_simRevert` is false, `processMessage` calls the `_greReceive` function for further message processing.
3. Message Processing in `_greReceive`:
   * `_greReceive` extracts and stores various information from the message, such as the `messageId`, decoded `sender` address, token amounts, and data.
   * It then emits a `MessageReceived` event, signaling the successful processing of the message.
4. Error Handling:
   * If an error occurs during the processing (or a simulated revert is triggered), the catch block within `greReceive` is executed.
   * The `messageId` of the failed message is added to `s_failedMessages`, and the message content is stored in `s_messageContents`.
   * A `MessageFailed` event is emitted, which allows for later identification and reprocessing of failed messages.

#### Reprocessing of failed messages <a href="#reprocessing-of-failed-messages" id="reprocessing-of-failed-messages"></a>

The `retryFailedMessage` function provides a mechanism to recover assets if a GRE message processing fails. It's specifically designed to handle scenarios where message data issues prevent entire processing yet allow for token recovery:

1. Initiation:
   * Only the contract owner can call this function, providing the `messageId` of the failed message and the `tokenReceiver` address for token recovery.
2. Validation:
   * It checks if the message has failed using `s_failedMessages.get(messageId)`. If not, it reverts the transaction.
3. Status Update:
   * The error code for the message is updated to `RESOLVED` to prevent reentry and multiple retries.
4. Token Recovery:
   * Retrieves the failed message content using `s_messageContents[messageId]`.
   * Transfers the locked tokens associated with the failed message to the specified `tokenReceiver` as an escape hatch without processing the entire message again.
5. **Event Emission**:
   * An event `MessageRecovered` is emitted to signal the successful recovery of the tokens.

This function showcases a graceful asset recovery solution, protecting user values even when message processing encounters issues.
