> For the complete documentation index, see [llms.txt](https://docs.vea.ninja/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vea.ninja/build-xchain-dapps/getting-started.md).

# Getting Started

### Integrating Vea

For each sending and receiving chain pair supported by Vea, there is a separate set of Vea contract [deployments](/introduction/deployment-addresses.md). For each chain and network, there is exactly one deployed contract.

* Sending Chain: [VeaInbox](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/arbitrumToEth/VeaInboxArbToEth.sol) - Manages state of all messages sent through Vea.
* Receiving Chain: [VeaOutbox](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/arbitrumToEth/VeaOutboxArbToEth.sol) - Manages optimistic game over inbox state

To integrate Vea, sender and receiver gateway contracts need to be deployed to interface with the Vea inbox and outbox.

<figure><img src="/files/jgNFSuA55VOzc4d9aTZi" alt=""><figcaption><p>Vea Integration with Gateways</p></figcaption></figure>

### 1. Sender Gateway

For each sending, receiving chain pair supported by Vea, there is a 'Vea Inbox' contract [deployed](/introduction/deployment-addresses.md) on the sending chain. Contracts send messages through Vea by calling the 'sendMessage(...)' function in the Vea Inbox.

```solidity
function sendMessage(address _to, bytes memory _data) 
```

* `_to` The address on the receiving chain to call
* `_data` The abi encoded calldata to pass with the function call.
  * e.g. abi.encode(arg1, arg2, arg3. . .)

The sender gateway can implement the ISenderGateway [interface](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/interfaces/gateways/ISenderGateway.sol).

```solidity
interface ISenderGateway {
    function veaInbox() external view returns (IVeaInbox);

    function receiverGateway() external view returns (address);
}
```

where the IVeaInbox [interface](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/interfaces/inboxes/IVeaInbox.sol) includes the function stub to send messages through Vea.

```solidity
interface IVeaInbox {
    /// @dev Sends an arbitrary message to receiving chain.
    /// Note: Calls authenticated by receiving gateway checking the sender argument.
    /// @param _to The cross-domain contract address which receives the calldata.
    /// @param _data The message calldata, abi.encode(...)
    /// @return msgId The index of the message in the inbox, as a message Id, needed to relay the message.
    function sendMessage(
        address _to,
        bytes memory _data
    ) external returns (uint64 msgId);
}
```

To send a message through Vea, the sending gateway should implement a function to call sendMessage(...) in the Vea Inbox. Here is an example [mock implementation](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/test/gateways/SenderGatewayMock.sol).

```solidity

pragma solidity 0.8.18;

import "ISenderGateway.sol";

/// Sender Gateway
/// Counterpart of `ReceiverGatewayMock`
contract SenderGatewayMock is ISenderGateway {
    IVeaInbox public immutable override veaInbox;
    address public immutable override receiverGateway;

    event VeaMessageSent(uint64 msgId);

    constructor(IVeaInbox _veaInbox, address _receiverGateway) {
        veaInbox = _veaInbox;
        receiverGateway = _receiverGateway;
    }

    function sendMessage(uint256 _data) external {
        bytes memory data = abi.encode(_data);
        uint64 msgId = veaInbox.sendMessage(receiverGateway, data);
        emit VeaMessageSent(msgId);
    }
}
```

Notice that the sendMessage(...) call in the Vea Inbox returns a uint64 message id. This id is used to relay the message on the receiving chain. Your dapp will probably want to index these messages with an event like below to later relay the message.

```solidity
emit VeaMessageSent(msgId);
```

In this example, the sender gateway is sending some uint256 \_data. The Vea Inbox contract expects a bytes array encoding the calldata to be passed with the cross-chain call.

```solidity
bytes memory data = abi.encode(_data);
```

The data which you include in the cross-chain message depends on your specific application.&#x20;

### 2. Receiver Gateway

For each sending, receiving chain pair supported by Vea, there is a 'Vea Outbox' contract [deployed](/introduction/deployment-addresses.md) on the receiving chain. Receiver gateways receive messages from Vea by receiving calls in '[receiveMessage](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/interfaces/gateways/IReceiverGateway.sol#L16)(...)' from the '[sendMessage](https://github.com/kleros/vea/blob/add723da87c885a4d939da396279daa5fd688677/contracts/src/arbitrumToEth/VeaOutboxArbToEth.sol#L243)(...)' function in the Vea Outbox.

```solidity
function sendMessage(
    bytes32[] calldata _proof,
    uint64 _msgId,
    address _to,
    address _from,
    bytes calldata _message)
```

* `_proof` The merkle inclusion proof
* `_msgId` The message id to relay
* `_to` The address to call
* `_from` The sender address  from the Vea Inbox chain
* `_data` The message data to relay

The [Vea SDK](broken://pages/LTEwjQIUWNsDD4GYQ23E) provides utility functions to calculate proofs and fetch message data to relay.

#### IReceiverGateway Function Specification

In order to implement a cross-chain call, you need to implement the `receiveMessage` of IReceiverGateway [interface](https://github.com/kleros/vea/blob/571a1ebbf897fdc29790f4737b70661f292b7aa5/contracts/src/interfaces/gateways/IReceiverGateway.sol).  Here's an example where we define the function `receiveMessage`.

```solidity
contract ReceiverGatewayMock is IReceiverGateway {
    /// Receive the message from the sender gateway.
    function receiveMessage(address msgSender, bytes _data) external override{
        (bool success, ) = address(this).call(data);
        require(success, "Internal call failed");
    }
}

interface IReceiverGateway {
    function veaOutbox() external view returns (address);
    
    function receiveMessage(address msgSender, bytes _data) external;
    
    function senderGateway() external view returns (address);
}
```

Note that Vea passes the msg.sender who called the sendMessage(...) function on the sending chain as the first argument and message `data` in second argument in `receiveMessage` function call. So the receiver must implement the `receiveMessage` function of IReceiverGateway.&#x20;

<pre class="language-solidity"><code class="lang-solidity">interface IReceiverGatewayMock is IReceiverGateway {
    /// Receive the message from the sender gateway.
<strong>    function receiveMessage(address msgSender, bytes _data) external;
</strong><strong>}
</strong></code></pre>

Here's a complete example of a ReceiverGateway.

```solidity
pragma solidity 0.8.18;

import "./IReceiverGatewayMock.sol";

/// Receiver Gateway Mock
/// Counterpart of `SenderGatewayMock`
contract ReceiverGatewayMock is IReceiverGatewayMock {
    address public immutable override veaOutbox;
    address public immutable override senderGateway;

    bytes public data;

    constructor(address _veaOutbox, address _senderGateway) {
        veaOutbox = _veaOutbox;
        senderGateway = _senderGateway;
    }

    modifier onlyFromAuthenticatedVeaSender(address messageSender) {
        require(veaOutbox == msg.sender, "Vea Bridge only.");
        require(messageSender == senderGateway, "Only the sender gateway is allowed.");
        _;
    }

    /// Receive the message from the sender gateway.
    function receiveMessage(
        address messageSender,
        bytes _data
    ) external onlyFromAuthenticatedVeaSender(messageSender) {
        data = _data;
    }
}

```

#### Message Sender Authentication

The message sender of a cross-chain call is always the first argument of calldata passed to any receiver gateways.&#x20;

```solidity
modifier onlyFromAuthenticatedVeaSender(address messageSender) {
    require(veaOutbox == msg.sender, "Vea Bridge only.");
    require(messageSender == senderGateway, "Only the sender gateway is allowed.");
    _;
}

function receiveMessage(
    address messageSender,
    bytes _data
) external onlyFromAuthenticatedVeaSender(messageSender) {...}
```

Cross-chain call authentication requires checking that the msg.sender on the sending chain is the Vea Outbox contract, and checking the first argument of the call is equal to the sender gateway like shown in the modifier `onlyFromAuthenticatedVeaSender`.&#x20;

#### Customizing the data types sent between gateways

To support transfer of data types other than uint256 as shown in this example, simply encode those data types into a bytes array to pass in the SenderGateway when calling `sendMessage(...)` in the Vea Inbox.

For example, to support a call passing data of a string, uint64, and a bytes array, the ISenderGateway would instead implement&#x20;

```solidity
function sendMessage(string memory _data1, uint64 _data2, bytes memory _data3) external {
    bytes memory data = abi.encode(_data1, _data2, _data3);
    uint64 msgId = veaInbox.sendMessage(receiverGateway, data);
    emit VeaMessageSent(msgId);
}
```

and the IReceiverGateway interface would appropriately implement the `receiveMessage` function selector to decode the data types string, uint64, and bytes.

```solidity
contract ReceiverGatewayMock is IReceiverGateway {
    /// Receive the message from the sender gateway.
    function receiveMessage(
        address msgSender,
        bytes calldata _data
    ) external override {
        (string memory decoded1, uint64 decoded2, bytes memory decoded3) = 
        abi.decode(data, (string, uint64, bytes));
    }
}
```

### 3. Relaying your message

Once messages are bridged by Vea, which can take hours to days depending on the sending and receiving chain pairs, the messages can be relayed by providing a merkle proof of message inclusion in the Vea Outbox contract.
