S Price: $0.474193 (+5.13%)

Contract Diff Checker

Contract Name:
SwitchboardPlug

Contract Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/*//////////////////////////////////////////////////////////////
                         BUNGEE ERRORS
//////////////////////////////////////////////////////////////*/

error MofaSignatureInvalid();
error InsufficientNativeAmount();
error UnsupportedRequest();
error RouterNotRegistered();
error CallerNotBungeeGateway();
error CallerNotEntrypoint();
error SwapOutputInsufficient();
error MinOutputNotMet();
error InvalidRequest();
error FulfilmentDeadlineNotMet();
error CallerNotDelegate();
error InvalidMsg();
error RequestProcessed();
error RequestNotProcessed();
error InvalidSwitchboard();
error PromisedAmountNotMet();
error MsgReceiveFailed();
error RouterAlreadyRegistered();
error InvalidFulfil();
error NotImplemented();
error OnlyOwner();
error OnlyNominee();
error InvalidReceiver();
error ImplAlreadyRegistered();
error InvalidAddress();

/*//////////////////////////////////////////////////////////////
                       SWITCHBOARD ERRORS
//////////////////////////////////////////////////////////////*/

error NotSiblingBungeeGateway();
error NotSocket();
error NotSwitchboardRouter();
error NotSwitchboardPlug();
error SwitchboardPlugZero();
error ConnectionAlreadyInitialised();
error IncorrectSwitchboard();

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {ISocket} from "../interfaces/ISocket.sol";
import {ISwitchboardRouter} from "../interfaces/ISwitchboardRouter.sol";
import {ISwitchboardPlug} from "../interfaces/ISwitchboardPlug.sol";
import {IPlug} from "../interfaces/IPlug.sol";
import {NotSocket, NotSwitchboardRouter} from "../common/Errors.sol";

/// @title SwitchboardPlug
/// @notice Plugs are application that can communicate across chains on Socket DL
/// @notice SwitchboardPlug is a plug that can via a specific Switchboard on Socket DL
contract SwitchboardPlug is IPlug, ISwitchboardPlug {
    /*//////////////////////////////////////////////////////////////////////////
                                PUBLIC STORAGE
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Socket contract - Settlement layer
    ISocket public immutable SOCKET;

    /// @notice SwitchboardRouter contract
    ISwitchboardRouter public immutable SWITCHBOARD_ROUTER;

    /// @notice SwitchboardId assigned to this SwitchboardPlug
    uint32 public immutable SWITCHBOARD_ID;

    /// @notice address of switchboard which will validate the incoming messages to the current chain
    address public immutable INBOUND_SWITCHBOARD;

    /// @notice address of switchboard which will process outgoing messages to the siblingChain
    address public immutable OUTBOUND_SWITCHBOARD;

    /// @notice maps siblingChainSlug to bool to indicate if that chain is already configured
    mapping(uint32 siblingChainSlug => bool configured) public isConfigured;

    constructor(
        address _socket,
        address _switchboardRouter,
        address _inboundSwitchboard,
        address _outboundSwitchboard,
        uint32 _switchboardId
    ) {
        SOCKET = ISocket(_socket);
        SWITCHBOARD_ROUTER = ISwitchboardRouter(_switchboardRouter);
        INBOUND_SWITCHBOARD = _inboundSwitchboard;
        OUTBOUND_SWITCHBOARD = _outboundSwitchboard;
        SWITCHBOARD_ID = _switchboardId;
    }

    /*//////////////////////////////////////////////////////////////////////////
                            EXTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Calls Socket to initialize connection with sibling switchboardPlug to send/receive messages
    /// @param siblingChainSlug chainSlug of the sibling chain
    /// @param siblingPlug address of the sibling Plug
    function connect(uint32 siblingChainSlug, address siblingPlug) external {
        // checks if the caller is Switchboard Router
        _checkIfSwitchboardRouter();

        // stores connection status
        isConfigured[siblingChainSlug] = true;

        // calls Socket to initialise connection
        SOCKET.connect(siblingChainSlug, siblingPlug, INBOUND_SWITCHBOARD, OUTBOUND_SWITCHBOARD);
    }

    /// @notice Called by SwitchboardRouter to send outgoing settlement messages
    /// @param siblingChainSlug chainSlug of the sibling chain the message is to be sent to
    /// @param msgGasLimit gasLimit required to execute the message on the sibling chain
    /// @param payload payload to be executed on the sibling chain
    function outbound(uint32 siblingChainSlug, uint256 msgGasLimit, bytes calldata payload) external payable {
        // checks if the caller is Switchboard Router
        _checkIfSwitchboardRouter();

        // sends message to Socket
        /// @dev bytes32(0) indicates fast finality transmission
        SOCKET.outbound{value: msg.value}(siblingChainSlug, msgGasLimit, bytes32(0), bytes32(0), payload);
    }

    /// @notice Called by Socket to receive incoming messages on the destination chain
    /// @param siblingChainSlug chainSlug of the chain the message originated from
    /// @param payload payload sent from the originating chain
    function inbound(uint32 siblingChainSlug, bytes calldata payload) external payable {
        // checks if the caller is Socket
        _checkIfSocket();

        // Calls SwitchboardRouter with the incoming message
        SWITCHBOARD_ROUTER.receiveAndDeliverMsg(SWITCHBOARD_ID, siblingChainSlug, payload);
    }

    /*//////////////////////////////////////////////////////////////////////////
                            INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice checks if caller is Switchboard Router
    function _checkIfSwitchboardRouter() internal view {
        if (msg.sender != address(SWITCHBOARD_ROUTER)) revert NotSwitchboardRouter();
    }

    /// @notice checks if caller is Socket
    function _checkIfSocket() internal view {
        if (msg.sender != address(SOCKET)) revert NotSocket();
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/**
 * @title IPlug
 * @notice Interface for a plug contract that executes the message received from a source chain.
 */
interface IPlug {
    /**
     * @dev this should be only executable by socket
     * @notice executes the message received from source chain
     * @notice It is expected to have original sender checks in the destination plugs using payload
     * @param srcChainSlug_ chain slug of source
     * @param payload_ the data which is needed by plug at inbound call on remote
     */
    function inbound(uint32 srcChainSlug_, bytes calldata payload_) external payable;
}

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

interface ISocketConfig {
    function getPlugConfig(
        address plugAddress_,
        uint32 siblingChainSlug_
    )
        external
        view
        returns (
            address siblingPlug,
            address inboundSwitchboard__,
            address outboundSwitchboard__,
            address capacitor__,
            address decapacitor__
        );
}

/**
 * @title ISocket
 * @notice An interface for a cross-chain communication contract
 * @dev This interface provides methods for transmitting and executing messages between chains,
 * connecting a plug to a remote chain and setting up switchboards for the message transmission
 * This interface also emits events for important operations such as message transmission, execution status,
 * and plug connection
 */
interface ISocket is ISocketConfig {
    /**
     * @notice registers a message
     * @dev Packs the message and includes it in a packet with capacitor
     * @param remoteChainSlug_ the remote chain slug
     * @param minMsgGasLimit_ the gas limit needed to execute the payload on remote
     * @param payload_ the data which is needed by plug at inbound call on remote
     */
    function outbound(
        uint32 remoteChainSlug_,
        uint256 minMsgGasLimit_,
        bytes32 executionParams_,
        bytes32 transmissionParams_,
        bytes calldata payload_
    ) external payable returns (bytes32 msgId);

    /**
     * @notice sets the config specific to the plug
     * @param siblingChainSlug_ the sibling chain slug
     * @param siblingPlug_ address of plug present at sibling chain to call inbound
     * @param inboundSwitchboard_ the address of switchboard to use for receiving messages
     * @param outboundSwitchboard_ the address of switchboard to use for sending messages
     */
    function connect(
        uint32 siblingChainSlug_,
        address siblingPlug_,
        address inboundSwitchboard_,
        address outboundSwitchboard_
    ) external;

    event PlugConnected(
        address plug,
        uint32 siblingChainSlug,
        address siblingPlug,
        address inboundSwitchboard,
        address outboundSwitchboard,
        address capacitor,
        address decapacitor
    );
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {IPlug} from "./IPlug.sol";

interface ISwitchboardPlug is IPlug {
    function SWITCHBOARD_ID() external view returns (uint32);

    function connect(uint32 siblingChainSlug, address siblingPlug) external;

    function outbound(uint32 siblingChainSlug, uint256 msgGasLimit, bytes calldata payload) external payable;
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

interface ISwitchboardRouter {
    function sendOutboundMsg(
        uint32 originChainId,
        uint32 switchboardId,
        uint8 msgId,
        uint256 destGasLimit,
        bytes calldata payload
    ) external payable;

    function receiveAndDeliverMsg(uint32 switchboardId, uint32 siblingChainId, bytes calldata payload) external;
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):