# Deploying Your Custom EVM Protocol

This guide provides step-by-step instructions on how to deploy your custom EVM protocol. By following these steps, you can successfully deploy your custom EVM protocol across multiple chains. If you encounter issues, refer to the [Troubleshooting](#troubleshooting) section of this guide and the [How to Debug Sent Messages](https://docs.entangle.fi/universal-interoperability-protocol/developer-guides/how-to-debug-sent-messages) guide or reach out to us through our [contact form](https://entangle.zendesk.com/hc/en-us/requests/new).

## Prerequisites

Before deployment, ensure you are familiar with payable functions in [Solidity](https://soliditylang.org/) and have initiated a [Hardhat](https://hardhat.org/) project.

## Package Installation

To streamline development, start by installing the Entangle Labs UIP Contracts [NPM](https://www.npmjs.com/package/@entangle-labs/uip-contracts) package. It includes ready-to-use code and interfaces for deployment.

```bash
npm install @entangle-labs/uip-contracts
```

## Deployment Steps

{% stepper %}
{% step %}

### Endpoint Contract Address

Obtain the endpoint contract address for the chain where you plan to deploy your protocol. You can find endpoint addresses for each connected chain in the Entangle Labs UIP Contracts NPM package.

For testnet, they are located in the following folder:

```
@entangle-labs/uip-contracts/addresses/testnet/
```

For mainnet, they are located in the following folder:

```
@entangle-labs/uip-contracts/addresses/mainnet/
```

{% endstep %}

{% step %}

### Interfaces and Libraries

Ensure the following imports are included in your contract:

```solidity
import {IEndpoint, TransmitterParams} from "@entangle-labs/uip-contracts/contracts/interfaces/endpoint/IEndpoint.sol";
import "@entangle-labs/uip-contracts/contracts/lib/SelectorLib.sol";
```

{% endstep %}

{% step %}

### Default Selector Variable

To interact with the Endpoint properly, you need to send message with the correct selector to call its "execute" function. Make sure it's included in your contract like so:

```solidity
bytes4 public constant DEFAULT_SELECTOR = bytes4(keccak256("execute(bytes calldata)"));
```

{% endstep %}

{% step %}

### Payable Function to Send Proposals

{% hint style="warning" %}
Read [this](https://docs.entangle.fi/universal-interoperability-protocol/customizable-message-transmission-options#encoded-parameter-option-definitions) section to learn more about the `propose` function, its parameters and the customizable message transmission options.
{% endhint %}

Develop a payable function that interacts with the endpoint. For example, sending a message to the endpoint requires calling the `propose` function using the `IEndpoint` interface:

```solidity
IEndpoint(endpoint).propose{value: msg.value}(
    chainID,
    SelectorLib.encodeDefaultSelector(DEFAULT_SELECTOR),
    encodedParams,
    destAddress,
    abi.encode(abi.encode(_msg), abi.encode(_msgSender()))
);
```

{% endstep %}

{% step %}

### Receive and Execute Messages

{% hint style="warning" %}
This step will only apply if your contract is designed to receive messages too.
{% endhint %}

The receiving contract must implement the `MessageReceiver` interface, which you can find in `@entagle-labs/uip-contracts` npm package — installed in the [Package Installation](#package-installation) step — specifically the `execute` function:

```solidity
function execute(bytes calldata data) external override payable
```

The `execute` function processes the received payload. Note that the Endpoint contract should have access control to this function. Make sure that your contract imports `MessageReceiver` and inherits from it, for example:

```solidity
import {MessageReceiver} from "@entangle-labs/uip-contracts/contracts/MessageReceiver.sol";
contract ExampleProtocol is MessageReceiver
```

Below, we provide the `MessageReceiver` code for convenience. Please refer to the package for the most up-to-date version.

<details>

<summary>MessageReceiver Code</summary>

```solidity
abstract contract MessageReceiver {
    /**
     * @dev Executes a function call from a specified source chain and address.
     *
     * This external function is intended to be used for executing cross-chain
     * calls with the provided payload. It requires to be overridden by child contracts to execute the command
     * @param data The data payload to be sent along with the function call.
     *
     */
    function execute(bytes calldata data) external payable virtual {}

    function _decode(
        bytes calldata data
    )
        internal
        virtual
        returns (
            uint256 sourceChainId,
            bytes memory senderAddr,
            bytes memory payload
        )
    {
        (sourceChainId, senderAddr, payload) = abi.decode(
            data,
            (uint256, bytes, bytes)
        );
    }
}
```

</details>
{% endstep %}
{% endstepper %}

## Troubleshooting & Notes

This section provides information, tips, and solutions for common issues you may encounter while deploying the protocol.

<details>

<summary>Deployment Failure</summary>

1. **Check the signer account balance**: Ensure the account has enough native currency on the target blockchain for deployment.
2. **Verify the credentials**: Double-check that you've correctly pasted the mnemonic phrase or private key in the `hardhat.config.ts` file under the appropriate chain section.
3. **Compile before deploying**: Run `npx hardhat compile` before deployment. If it fails, thoroughly check your contract for compilation errors.

</details>

<details>

<summary>Sending Message Failure</summary>

1. **Check the signer account balance**: Ensure the account has sufficient native currency for transactions.
2. **Verify the installed package version**: Make sure you have the latest version of the `@entangle-labs/uip-contracts` npm package installed. To check the latest version, visit the official [npm page](https://www.npmjs.com/package/@entangle-labs/uip-contracts).
3. **Confirm function signature compliance**: Ensure your contract correctly follows the `propose` function signature in the Endpoint contract:

   ```solidity
   function propose(
       uint256 destChainID, 
       bytes32 selectorSlot, 
       bytes calldata transmitterParams, 
       bytes calldata destAddress, 
       bytes calldata payload
   ) external payable;
   ```

</details>

<details>

<summary>Message Not Reaching Destination Contract</summary>

1. **Check destination chain support:** Ensure that the destination chain is currently supported.
2. **Retrieve message hash:** Use the following command to obtain the TEIB transaction hash for your message: [`npx hardhat getMsgHash`](https://docs.entangle.fi/universal-interoperability-protocol/how-to-debug-sent-messages#retrieving-proposal-and-message-hash)
3. **Check message status:** Once you have the hash, use: [`getMsgStatusByHash`](https://docs.entangle.fi/universal-interoperability-protocol/how-to-debug-sent-messages#check-message-status-by-hash)

**Message Status Explanations**

* **NOT\_INITIALIZED**: This indicates that the message was not proposed by the Endpoint on the source chain. Verify that the Endpoint address in your contract matches the official Endpoint address for your source chain.
* **PROTOCOL\_FAILED**: This occurs when the destination protocol is incompatible with the destination Endpoint. Ensure that the destination protocol implements the `MessageReceiver` interface (as described in the [Receiver Contract Requirements](#receiver-contract-requirements) section).
* **UNDERESTIMATED**: This status means that the source transaction’s `msg.value` was too low to cover gas costs on the destination chain. Try resending the message with a higher `msg.value`.
* **OUT\_OF\_GAS**: This means that the `customGasLimit` in the source transaction was too low, causing the execution on the destination chain to consume more gas than provided. Try resending the message with a higher `customGasLimit`.

</details>

<details>

<summary>Transaction Delivery Fee and Currency</summary>

All transactions use the native currency of the chain you're working on. The`msg.value` sent during the `propose` call is considered the combined delivery fee.

</details>

<details>

<summary>Package Referencing Issues</summary>

Ensure all configurations adhere to the latest documentation and libraries provided in the `@entangle-labs/uip-contracts` package.

</details>
