# XRPL (https://docs.axelar.dev/gmp/integrations/xrpl)



The XRP Ledger has no smart contracts, so Axelar has no gateway contract there. Instead, you send a message as a [Payment](https://xrpl.org/docs/references/protocol/transactions/types/payment) to Axelar's multisig account, with the message in the transaction's [memos](https://xrpl.org/docs/references/protocol/transactions/common-fields#memos-field). Axelar's verifiers check the payment, and Axelar routes the message through [Amplifier](https://docs.axelar.dev/llms.mdx/infrastructure/content.md#a-cross-chain-protocol-amplifier).

**XRPL can send GMP messages, but can't receive them**: there's no contract on XRPL to execute them. XRPL can receive tokens through the [Interchain Token Service](https://docs.axelar.dev/llms.mdx/its/integrations/xrpl/content.md), without a payload.

<Callout title="Using an AI agent?">
  Copy this page with **Copy Markdown** at the top and give it to your agent,
  with what you want to build or the app you want to make cross-chain. The
  copied page links to the Markdown of the other pages it refers to, so the
  agent can read them too. Review what it writes, and test on testnet before
  mainnet.
</Callout>

## Addresses [#addresses]

|                         | Mainnet                              | Testnet                               |
| ----------------------- | ------------------------------------ | ------------------------------------- |
| Chain name              | `xrpl`                               | `xrpl`                                |
| Axelar multisig account | `rfmS3zqrQrka8wVyhXifEeyTwe8AMz2Yhw` | `rNrjh1KGZk2jBR3wPfAQnoidtFFYQKbQn2`  |
| RPC                     | `wss://s1.ripple.com`                | `wss://s.altnet.rippletest.net:51233` |

The multisig account's signers are Axelar's XRPL verifiers. The deployment configs list it as `AxelarGateway`: [mainnet](https://github.com/axelarnetwork/axelar-contract-deployments/blob/main/axelar-chains-config/info/mainnet.json) | [testnet](https://github.com/axelarnetwork/axelar-contract-deployments/blob/main/axelar-chains-config/info/testnet.json). For a funded testnet account, use the [XRP faucet](https://xrpl.org/resources/dev-tools/xrp-faucets).

## Send a message [#send-a-message]

1. [Estimate the fee](https://docs.axelar.dev/llms.mdx/gmp/gas/estimate-and-pay/content.md#estimate-the-fee) with `xrpl` as the source chain. The result is in drops (1 XRP = 1,000,000 drops).
2. Send a Payment to the multisig account. The whole `Amount` pays gas; any unused part is [refunded](#refunds).
3. Follow the message on Axelarscan by the transaction hash.

With [xrpl.js](https://js.xrpl.org/), sending `"hello"` to a contract on XRPL EVM testnet:

```js
import { Client, Wallet, convertStringToHex } from 'xrpl';

const AXELAR_MULTISIG = 'rNrjh1KGZk2jBR3wPfAQnoidtFFYQKbQn2'; // testnet

const memo = (type, data) => ({
  Memo: { MemoType: convertStringToHex(type), MemoData: data },
});

const client = new Client('wss://s.altnet.rippletest.net:51233');
await client.connect();
const wallet = Wallet.fromSeed(process.env.XRPL_SEED);

// The payload, as hex without 0x. An EVM contract expects ABI-encoded data:
// cast abi-encode "f(string)" "hello"
const payload =
  '0000000000000000000000000000000000000000000000000000000000000020' +
  '0000000000000000000000000000000000000000000000000000000000000005' +
  '68656c6c6f000000000000000000000000000000000000000000000000000000';

const result = await client.submitAndWait(
  {
    TransactionType: 'Payment',
    Account: wallet.address,
    Destination: AXELAR_MULTISIG,
    Amount: '1000000', // 1 XRP in drops, all of it for gas
    Memos: [
      memo('type', convertStringToHex('call_contract')),
      memo('destination_chain', convertStringToHex('xrpl-evm')),
      memo('destination_address', convertStringToHex('0x0A90c0Af1B07f6AC34f3520348Dbfae73BDa358E')),
      memo('payload', payload),
    ],
  },
  { autofill: true, wallet },
);

console.log(result.result.hash);
await client.disconnect();
```

The [axelar-contract-deployments](https://github.com/axelarnetwork/axelar-contract-deployments/tree/main/xrpl) repository also has a script for this, `xrpl/call-contract.js`.

### What the destination receives [#what-the-destination-receives]

The message has:

* **source chain** `xrpl`;
* **source address**: your XRPL account (`r…`), as a string;
* **message ID**: `0x` followed by the transaction hash in lowercase;
* **payload**: exactly the bytes of the `payload` memo.

An EVM contract receives them in [`_execute`](https://docs.axelar.dev/llms.mdx/gmp/integrations/evm/gmp-messages/content.md#receive-a-message), with `sourceAddress` an `r…` address. Check it as a string, not with `toAddress()`.

## Memos [#memos]

Each memo has a `MemoType`, the field name, and a `MemoData`, the value. Both are hex:

* `MemoType` and `MemoData` are the hex of a UTF-8 string, e.g. `convertStringToHex('call_contract')`,
* except the `payload` memo, whose `MemoData` is the payload bytes themselves in hex, without `0x`.

To send a message:

| `MemoType`            | `MemoData`                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------------ |
| `type`                | `call_contract`                                                                            |
| `destination_chain`   | The destination's [chain name](https://axelarscan.io/resources/chains), e.g. `xrpl-evm`    |
| `destination_address` | The destination contract's address in its chain's format; for EVM chains, `0x` is optional |
| `payload`             | The payload, as raw bytes in hex. Required                                                 |

To add gas, see [Add gas](#add-gas). Token transfers use `interchain_transfer`; see [ITS on XRPL](https://docs.axelar.dev/llms.mdx/its/integrations/xrpl/content.md).

### Rules [#rules]

If a payment breaks any of these, the verifiers reject it. It never appears on Axelarscan, and there's no automatic refund:

* It's a `Payment` to the multisig account, and succeeded (`tesSUCCESS`).
* It sets no flags, so partial payments aren't allowed, and the full `Amount` is delivered.
* Each memo type appears once.
* The payload fits in the memos: XRPL limits all memos of a transaction to 1 KB together.

## Gas [#gas]

`Amount` can be XRP, in drops, or an IOU token registered with the Interchain Token Service on XRPL, as `{ currency, issuer, value }`.

### Add gas [#add-gas]

If the gas paid wasn't enough, send another Payment to the multisig account with these memos:

| `MemoType` | `MemoData`                                                               |
| ---------- | ------------------------------------------------------------------------ |
| `type`     | `add_gas`                                                                |
| `msg_id`   | The original transaction hash: 64 lowercase hex characters, without `0x` |

`msg_id` must be lowercase; explorers often show hashes in uppercase. The whole `Amount` of this payment is added as gas.

The AxelarJS SDK can build this payment with [`addGasToXrplChain`](https://docs.axelar.dev/llms.mdx/gmp/track-and-recover/recover-transactions/content.md#add-gas). It takes the amount in XRP, and returns an unsigned transaction for you to sign and submit.

### Refunds [#refunds]

Unused gas is refunded in XRP to the account that paid it, minus the XRP Ledger transaction fee. You can't choose another refund address. Refunds are sent from an account Axelar operates, not from the multisig account.


---

All pages of these docs, as Markdown: https://docs.axelar.dev/llms.txt