Skip to main content

Speed Run DL

In this speed run tutorial, we'll be writing a contract to send/receive messages between chains. This is a code along tutorial, you can copy the code snippets into Remix or the dev environment of your choice. In case you are stuck, you can take peak at the entire code on GitHub. We'll be highlighting key functions and what they do throughout the tutorial. Some configuration variables have been hardcoded in the example.

We'll be deploying the same copy of the contract on Goerli and Mumbai testnet and sending the message "Hello World" from Goerli to Mumbai. You can also deploy it on any supported networks. Let's get started!

Step 1 : Boilerplate code

Below is the boilerplate code needed to get started. ISocket is the interface used by our contract to interact with Socket.

Hello World is the contract which we'll be writing to send/receive messages.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

interface ISocket {
function outbound(
uint32 remoteChainSlug_,
uint256 minMsgGasLimit_,
bytes32 executionParams_,
bytes32 transmissionParams_,
bytes calldata payload_
) external payable returns (bytes32 msgId);

function connect(
uint32 siblingChainSlug_,
address siblingPlug_,
address inboundSwitchboard_,
address outboundSwitchboard_
) external;

function getMinFees(
uint256 minMsgGasLimit_,
uint256 payloadSize_,
bytes32 executionParams_,
bytes32 transmissionParams_,
uint32 remoteChainSlug_,
address plug_
) external view returns (uint256 totalFees);

contract HelloWorld {


Step 2 : Initialise state variables, events, modifiers

State variables

message is the message which will be set on the remote plug

destGasLimit is the gas limit of setting the message on the destination chain, this value varies depending on the chain.

You can learn more about the other variables in Configuring Plugs


MessageSent is emitted when a message is sent from the source plug and MessageReceived is emitted when the message is received on the destination plug.

    string public message = "Hello World";
address owner;

* @dev Hardcoded values for Goerli
uint256 destGasLimit = 100000; // Gas cost of sending "Hello World" on Mumbai
uint32 public remoteChainSlug = 80001; // Mumbai testnet chain ID
address public socket = 0xe37D028a77B4e6fCb05FC75EBa845752cD62A0AA; // Socket Address on Goerli
address public inboundSwitchboard =
0xd59d596B7C7cB4593F61bbE4A82C1E943C64558D; // FAST Switchboard on Goerli
address public outboundSwitchboard =
0xd59d596B7C7cB4593F61bbE4A82C1E943C64558D; // FAST Switchboard on Goerli

event MessageSent(uint32 destChainSlug, string message);

event MessageReceived(uint32 srcChainSlug, string message);

modifier isOwner() {
require(msg.sender == owner, "Not owner");

modifier isSocket() {
require(msg.sender == socket, "Not Socket");

error InsufficientFees();

constructor() {
owner = msg.sender;

Step 3 : Config Functions

connectPlug function connects our Hello World Plug to its sibling Plug on another chain. This connection is required for the Plugs to send/receive messages from one another.

function connectPlug(address siblingPlug_) external isOwner {

Step 4 : Sending messages

sendMessage sends the "Hello World" message to the remote chain. This function calls Socket and initiates the outbound cross-chain message

_getMinimumFees fetches the fees for including messages in Packets & executing them. This can be used to verify sufficient fees are passed when sending the message. You can learn more about this in Fees.

    function sendMessage() external payable {
bytes memory payload = abi.encode(message);

uint256 totalFees = _getMinimumFees(destGasLimit, payload.length);

if (msg.value < totalFees) revert InsufficientFees();

ISocket(socket).outbound{value: msg.value}(

emit MessageSent(remoteChainSlug, message);

function _getMinimumFees(
uint256 minMsgGasLimit_,
uint256 payloadSize_
) internal view returns (uint256) {

Step 5 : Receiving Messages

inbound is called by Socket on the destination Plug for executing the message once it's verified. More in this in Lifecycle

_receiveMessage sets the value of the new message and emits the MessageReceived event

    function _receiveMessage(
uint32 _srcChainSlug,
string memory _message
) internal {
message = _message;
emit MessageReceived(_srcChainSlug, _message);

function inbound(
uint32 srcChainSlug_,
bytes calldata payload_
) external isSocket {
string memory _message = abi.decode(payload_, (string));
_receiveMessage(srcChainSlug_, _message);

Step 6 : Deploying contracts

We'll be deploying the same contract on Goerli and Mumbai testnets. However, to make it easier to send our first message, we've hardcoded some configuration variables specific to Goerli and Mumbai. Click the links below to deploy each of them


🚀 Deploy Goerli contract on Remix

📄 Goerli contract on GitHub


🚀 Deploy Mumbai contract on Remix

📄 Mumbai contract on GitHub

You can head over to Remix and compile the code for SpeedRunGoerli

Then, deploy it

You'll then have to deploy the SpeedRunMumbai contract following the same steps.

Step 7 : Configuration

Once you've deployed the contracts on Goerli and Mumbai, call the connectPlug function with the address of the contract deployed on the other chain. You need to do this on both contracts deployed on respective chains.

For instance, on Goerli you would call connectPlug with the address of the contract deployed on Mumbai and vice-versa. This establishes a connection between the two Plugs deployed and you can now send messages between them!

Step 8 : Hello World

To send your first message, call the sendMessage function on Goerli. You need to send a fee in ETH as value when calling sendMessage. This fee can be calculated using the Fee Estimate API

You can enter the totalFee returned by this API as value when sending the transaction

That's it! You can now track the status of your message using the Status Tracking API. Once your message is executed on Mumbai, you'll be able to see the message value set to "Hello World" on Mumbai.

You're Plugged!

You've successfully sent your first message via SocketDL. Explore more in Tutorials and Examples.