Sepolia Testnet

Contract

0x6e8d1138e05a67c3D1B9811bb73a89CCB69Db2f6

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CCIPAdapter

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 13 : CCIPAdapter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {BaseAdapter, IBaseAdapter} from '../BaseAdapter.sol';
import {ICCIPAdapter, IRouterClient} from './ICCIPAdapter.sol';
import {IAny2EVMMessageReceiver, Client} from './interfaces/IAny2EVMMessageReceiver.sol';
import {IERC165} from './interfaces/IERC165.sol';
import {MainnetChainIds, TestnetChainIds} from '../../libs/ChainIds.sol';
import {Errors} from '../../libs/Errors.sol';

/**
 * @title CCIPAdapter
 * @author BGD Labs
 * @notice CCIP bridge adapter. Used to send and receive messages cross chain
 * @dev it uses the eth balance of CrossChainController contract to pay for message bridging as the method to bridge
        is called via delegate call
 */
contract CCIPAdapter is ICCIPAdapter, BaseAdapter, IAny2EVMMessageReceiver, IERC165 {
  /// @inheritdoc ICCIPAdapter
  IRouterClient public immutable CCIP_ROUTER;

  // (chain -> origin forwarder address) saves for every chain the address that can forward messages to this adapter
  mapping(uint256 => address) internal _trustedRemotes;

  /**
   * @notice only calls from the set router are accepted.
   */
  modifier onlyRouter() {
    require(msg.sender == address(CCIP_ROUTER), Errors.CALLER_NOT_CCIP_ROUTER);
    _;
  }

  /**
   * @param crossChainController address of the cross chain controller that will use this bridge adapter
   * @param ccipRouter ccip entry point address
   * @param trustedRemotes list of remote configurations to set as trusted
   */
  constructor(
    address crossChainController,
    address ccipRouter,
    TrustedRemotesConfig[] memory trustedRemotes
  ) BaseAdapter(crossChainController) {
    require(ccipRouter != address(0), Errors.CCIP_ROUTER_CANT_BE_ADDRESS_0);
    CCIP_ROUTER = IRouterClient(ccipRouter);

    _updateTrustedRemotes(trustedRemotes);
  }

  /// @inheritdoc ICCIPAdapter
  function getTrustedRemoteByChainId(uint256 chainId) external view returns (address) {
    return _trustedRemotes[chainId];
  }

  /// @inheritdoc IERC165
  function supportsInterface(bytes4 interfaceId) public pure override returns (bool) {
    return
      interfaceId == type(IAny2EVMMessageReceiver).interfaceId ||
      interfaceId == type(IERC165).interfaceId;
  }

  /// @inheritdoc IBaseAdapter
  function forwardMessage(
    address receiver,
    uint256 gasLimit,
    uint256 destinationChainId,
    bytes memory message
  ) external {
    uint64 nativeDestinationChainId = infraToNativeChainId(destinationChainId);

    require(
      CCIP_ROUTER.isChainSupported(nativeDestinationChainId),
      Errors.DESTINATION_CHAIN_ID_NOT_SUPPORTED
    );
    require(receiver != address(0), Errors.RECEIVER_NOT_SET);

    Client.EVMExtraArgsV1 memory evmExtraArgs = Client.EVMExtraArgsV1({
      gasLimit: gasLimit,
      strict: false
    });

    bytes memory extraArgs = Client._argsToBytes(evmExtraArgs);

    Client.EVM2AnyMessage memory payload = Client.EVM2AnyMessage({
      receiver: abi.encode(receiver),
      data: message,
      tokenAmounts: new Client.EVMTokenAmount[](0),
      feeToken: address(0), // We leave the feeToken empty indicating we'll pay with native gas tokens.,
      extraArgs: extraArgs
    });

    uint256 clFee = CCIP_ROUTER.getFee(nativeDestinationChainId, payload);

    require(address(this).balance >= clFee, Errors.NOT_ENOUGH_VALUE_TO_PAY_BRIDGE_FEES);

    bytes32 messageId = CCIP_ROUTER.ccipSend{value: clFee}(nativeDestinationChainId, payload);

    emit MessageForwarded(receiver, nativeDestinationChainId, messageId, message);
  }

  /// @inheritdoc IAny2EVMMessageReceiver
  function ccipReceive(Client.Any2EVMMessage calldata message) external onlyRouter {
    address srcAddress = abi.decode(message.sender, (address));

    uint256 originChainId = nativeToInfraChainId(message.sourceChainId);

    require(originChainId != 0, Errors.INCORRECT_ORIGIN_CHAIN_ID);

    require(_trustedRemotes[originChainId] == srcAddress, Errors.REMOTE_NOT_TRUSTED);

    _registerReceivedMessage(message.data, originChainId);
    emit CCIPPayloadProcessed(originChainId, srcAddress, message.data);
  }

  /// @inheritdoc ICCIPAdapter
  function nativeToInfraChainId(uint64 nativeChainId) public pure returns (uint256) {
    if (nativeChainId == uint64(MainnetChainIds.ETHEREUM)) {
      return MainnetChainIds.ETHEREUM;
    } else if (nativeChainId == uint64(MainnetChainIds.AVALANCHE)) {
      return MainnetChainIds.AVALANCHE;
    } else if (nativeChainId == uint64(MainnetChainIds.POLYGON)) {
      return MainnetChainIds.POLYGON;
    } else if (nativeChainId == uint64(MainnetChainIds.ARBITRUM)) {
      return MainnetChainIds.ARBITRUM;
    } else if (nativeChainId == uint64(MainnetChainIds.OPTIMISM)) {
      return MainnetChainIds.OPTIMISM;
    } else if (nativeChainId == uint64(MainnetChainIds.FANTOM)) {
      return MainnetChainIds.FANTOM;
    } else if (nativeChainId == uint64(MainnetChainIds.HARMONY)) {
      return MainnetChainIds.HARMONY;
    } else if (nativeChainId == uint64(TestnetChainIds.ETHEREUM_GOERLI)) {
      return TestnetChainIds.ETHEREUM_GOERLI;
    } else if (nativeChainId == uint64(TestnetChainIds.AVALANCHE_FUJI)) {
      return TestnetChainIds.AVALANCHE_FUJI;
    } else if (nativeChainId == uint64(TestnetChainIds.OPTIMISM_GOERLI)) {
      return TestnetChainIds.OPTIMISM_GOERLI;
    } else if (nativeChainId == uint64(TestnetChainIds.POLYGON_MUMBAI)) {
      return TestnetChainIds.POLYGON_MUMBAI;
    } else if (nativeChainId == uint64(TestnetChainIds.ETHEREUM_SEPOLIA)) {
      return TestnetChainIds.ETHEREUM_SEPOLIA;
    } else {
      return 0;
    }
  }

  /// @inheritdoc ICCIPAdapter
  function infraToNativeChainId(uint256 infraChainId) public pure returns (uint64) {
    if (infraChainId == MainnetChainIds.ETHEREUM) {
      return uint64(MainnetChainIds.ETHEREUM);
    } else if (infraChainId == MainnetChainIds.AVALANCHE) {
      return uint64(MainnetChainIds.AVALANCHE);
    } else if (infraChainId == MainnetChainIds.POLYGON) {
      return uint64(MainnetChainIds.POLYGON);
    } else if (infraChainId == MainnetChainIds.ARBITRUM) {
      return uint64(MainnetChainIds.ARBITRUM);
    } else if (infraChainId == MainnetChainIds.OPTIMISM) {
      return uint64(MainnetChainIds.OPTIMISM);
    } else if (infraChainId == MainnetChainIds.FANTOM) {
      return uint64(MainnetChainIds.FANTOM);
    } else if (infraChainId == MainnetChainIds.HARMONY) {
      return uint64(MainnetChainIds.HARMONY);
    } else if (infraChainId == TestnetChainIds.ETHEREUM_GOERLI) {
      return uint64(TestnetChainIds.ETHEREUM_GOERLI);
    } else if (infraChainId == TestnetChainIds.AVALANCHE_FUJI) {
      return uint64(TestnetChainIds.AVALANCHE_FUJI);
    } else if (infraChainId == TestnetChainIds.OPTIMISM_GOERLI) {
      return uint64(TestnetChainIds.OPTIMISM_GOERLI);
    } else if (infraChainId == TestnetChainIds.POLYGON_MUMBAI) {
      return uint64(TestnetChainIds.POLYGON_MUMBAI);
    } else if (infraChainId == TestnetChainIds.ETHEREUM_SEPOLIA) {
      return uint64(TestnetChainIds.ETHEREUM_SEPOLIA);
    } else {
      return uint64(0);
    }
  }

  /**
   * @notice method to set trusted remotes. These are addresses that are allowed to receive messages from
   * @param trustedRemotes list of objects with the trusted remotes configurations
   **/
  function _updateTrustedRemotes(TrustedRemotesConfig[] memory trustedRemotes) internal {
    for (uint256 i = 0; i < trustedRemotes.length; i++) {
      _trustedRemotes[trustedRemotes[i].originChainId] = trustedRemotes[i].originForwarder;
      emit SetTrustedRemote(trustedRemotes[i].originChainId, trustedRemotes[i].originForwarder);
    }
  }
}

File 2 of 13 : BaseAdapter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IBaseAdapter} from './IBaseAdapter.sol';
import {ICrossChainController} from '../interfaces/ICrossChainController.sol';

/**
 * @title BaseAdapter
 * @author BGD Labs
 * @notice base contract implementing the method to route a bridged message to the CrossChainController contract.
 * @dev All bridge adapters must implement this contract
 */
abstract contract BaseAdapter is IBaseAdapter {
  ICrossChainController public immutable CROSS_CHAIN_CONTROLLER;

  /**
   * @param crossChainController address of the CrossChainController the bridged messages will be routed to
   */
  constructor(address crossChainController) {
    CROSS_CHAIN_CONTROLLER = ICrossChainController(crossChainController);
  }

  /**
   * @notice calls CrossChainController to register the bridged payload
   * @param _payload bytes containing the bridged message
   * @param originChainId id of the chain where the message originated
   */
  function _registerReceivedMessage(bytes memory _payload, uint256 originChainId) internal {
    CROSS_CHAIN_CONTROLLER.receiveCrossChainMessage(_payload, originChainId);
  }
}

File 3 of 13 : IBaseAdapter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title IBaseAdapter
 * @author BGD Labs
 * @notice interface containing the event and method used in all bridge adapters
 */
interface IBaseAdapter {
  /**
   * @notice method that will bridge the payload to the chain specified
   * @param receiver address of the receiver contract on destination chain
   * @param gasLimit amount of the gas limit in wei to use for bridging on receiver side. Each adapter will manage this
            as needed
   * @param destinationChainId id of the destination chain in the bridge notation
   * @param message to send to the specified chain
   */
  function forwardMessage(
    address receiver, // TODO: this should be renamed as is the bridge adapter on receiving side
    uint256 gasLimit,
    uint256 destinationChainId,
    bytes memory message
  ) external;
}

File 4 of 13 : ICCIPAdapter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IRouterClient} from './interfaces/IRouterClient.sol';

/**
 * @title ICCIPAdapter
 * @author BGD Labs
 * @notice interface containing the events, objects and method definitions used in the CCIP bridge adapter
 */
interface ICCIPAdapter {
  /**
   * @notice pair of origin address and origin chain
   * @param originForwarder address of the contract that will send the messages
   * @param originChainId id of the chain where the trusted remote is from
   */
  struct TrustedRemotesConfig {
    address originForwarder;
    uint256 originChainId;
  }

  /**
   * @notice emitted when a payload is forwarded
   * @param receiver address that will receive the payload
   * @param destinationChainId id of the chain to bridge the payload
   * @param messageId CCIP id of the message forwarded
   * @param message object to be bridged
   */
  event MessageForwarded(
    address indexed receiver,
    uint64 indexed destinationChainId,
    bytes32 indexed messageId,
    bytes message
  );

  /**
   * @notice emitted when a message is received and has been correctly processed
   * @param srcChainId id of the chain where the message originated from
   * @param srcAddress address that sent the message (origin CrossChainContract)
   * @param data bridged message
   */
  event CCIPPayloadProcessed(uint256 indexed srcChainId, address indexed srcAddress, bytes data);

  /**
   * @notice emitted when a trusted remote is set
   * @param originChainId id of the chain where the trusted remote is from
   * @param originForwarder address of the contract that will send the messages
   */
  event SetTrustedRemote(uint256 indexed originChainId, address indexed originForwarder);

  /**
   * @notice method to get the CCIP router address
   * @return adddress of the CCIP router
   */
  function CCIP_ROUTER() external view returns (IRouterClient);

  /**
   * @notice method to get the trusted remote address from a specified chain id
   * @param chainId id of the chain from where to get the trusted remote
   * @return address of the trusted remote
   */
  function getTrustedRemoteByChainId(uint256 chainId) external view returns (address);

  /**
   * @notice method to get infrastructure chain id from bridge native chain id
   * @param nativeChainId bridge native chain id
   */
  function nativeToInfraChainId(uint64 nativeChainId) external pure returns (uint256);

  /**
   * @notice method to get bridge native chain id from native bridge chain id
   * @param infraChainId infrastructure chain id
   */
  function infraToNativeChainId(uint256 infraChainId) external pure returns (uint64);
}

File 5 of 13 : IAny2EVMMessageReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Client} from '../lib/Client.sol';

/// @notice Application contracts that intend to receive messages from
/// the router should implement this interface.
interface IAny2EVMMessageReceiver {
  /// @notice Router calls this to deliver a message.
  /// If this reverts, any token transfers also revert. The message
  /// will move to a FAILED state and become available for manual execution
  /// as a retry. Fees already paid are NOT currently refunded (may change).
  /// @param message CCIP Message
  /// @dev Note ensure you check the msg.sender is the router
  function ccipReceive(Client.Any2EVMMessage calldata message) external;
}

File 6 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC165 {
  // @dev Should indicate whether the contract implements IAny2EVMMessageReceiver
  // e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId
  // This allows CCIP to check if ccipReceive is available before calling it.
  // If this returns false, only tokens are transferred to the receiver.
  // If this returns true, tokens are transferred and ccipReceive is called atomically.
  // Additionally, if the receiver address does not have code associated with
  // it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred.
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 7 of 13 : IRouterClient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Client library above
import {Client} from '../lib/Client.sol';

interface IRouterClient {
  error UnsupportedDestinationChain(uint64 destinationChainId);
  /// @dev Sender is not whitelisted
  error SenderNotAllowed(address sender);
  error InsufficientFeeTokenAmount();
  /// @dev Sent msg.value with a non-empty feeToken
  error InvalidMsgValue();

  /// @notice Checks if the given chain ID is supported for sending/receiving.
  /// @param chainId The chain to check
  /// @return supported is true if it is supported, false if not
  function isChainSupported(uint64 chainId) external view returns (bool supported);

  /// @notice Gets a list of all supported tokens which can be sent or received
  /// to/from a given chain id.
  /// @param chainId The chainId.
  /// @return tokens The addresses of all tokens that are supported.
  function getSupportedTokens(uint64 chainId) external view returns (address[] memory tokens);

  /// @param destinationChainId The destination chain ID
  /// @param message The cross-chain CCIP message including data and/or tokens
  /// @return fee returns guaranteed execution fee for the specified message
  /// delivery to destination chain
  /// @dev returns 0 fee on invalid message.
  function getFee(
    uint64 destinationChainId,
    Client.EVM2AnyMessage memory message
  ) external view returns (uint256 fee);

  /// @notice Request a message to be sent to the destination chain
  /// @param destinationChainId The destination chain ID
  /// @param message The cross-chain CCIP message including data and/or tokens
  /// @return messageId The message ID
  /// @dev Note if msg.value is larger than the required fee (from getFee) we accept
  /// the overpayment with no refund.
  function ccipSend(
    uint64 destinationChainId,
    Client.EVM2AnyMessage calldata message
  ) external payable returns (bytes32 messageId);
}

File 8 of 13 : Client.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Client {
  struct EVMTokenAmount {
    address token; // token address on the local chain
    uint256 amount;
  }

  struct Any2EVMMessage {
    bytes32 messageId; // MessageId corresponding to ccipSend on source
    uint64 sourceChainId;
    bytes sender; // abi.decode(sender) if coming from an EVM chain
    bytes data; // payload sent in original message
    EVMTokenAmount[] tokenAmounts;
  }

  struct EVM2AnyMessage {
    bytes receiver; // abi.encode(receiver address) for dest EVM chains
    bytes data; // Data payload
    EVMTokenAmount[] tokenAmounts; // Token transfers
    address feeToken; // Address of feeToken. address(0) means you will send msg.value.
    bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)
  }

  // extraArgs will evolve to support new features
  // bytes4(keccak256("CCIP EVMExtraArgsV1"));
  bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;
  struct EVMExtraArgsV1 {
    uint256 gasLimit; // ATTENTION!!! MAX GAS LIMIT 4M FOR ALPHA TESTING
    bool strict; // See strict sequencing details below.
  }
  function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
    return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
  }
}

File 9 of 13 : ICrossChainController.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './ICrossChainForwarder.sol';
import './ICrossChainReceiver.sol';

/**
 * @title ICrossChainController
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the CrossChainController contract
 */
interface ICrossChainController is ICrossChainForwarder, ICrossChainReceiver {
  /**
   * @notice method called to initialize the proxy
   * @param owner address of the owner of the cross chain controller
   * @param guardian address of the guardian of the cross chain controller
   * @param clEmergencyOracle address of the chainlink emergency oracle
   * @param initialRequiredConfirmations number of confirmations the messages need to be accepted as valid
   * @param receiverBridgeAdaptersToAllow array of addresses of the bridge adapters that can receive messages
   * @param forwarderBridgeAdaptersToEnable array specifying for every bridgeAdapter, the destinations it can have
   * @param sendersToApprove array of addresses to allow as forwarders
   */
  function initialize(
    address owner,
    address guardian,
    address clEmergencyOracle,
    uint256 initialRequiredConfirmations,
    address[] memory receiverBridgeAdaptersToAllow,
    BridgeAdapterConfigInput[] memory forwarderBridgeAdaptersToEnable,
    address[] memory sendersToApprove
  ) external;

  /**
   * @notice method called to rescue tokens sent erroneously to the contract. Only callable by owner
   * @param erc20Token address of the token to rescue
   * @param to address to send the tokens
   * @param amount of tokens to rescue
   */
  function emergencyTokenTransfer(address erc20Token, address to, uint256 amount) external;

  /**
   * @notice method called to rescue ether sent erroneously to the contract. Only callable by owner
   * @param to address to send the eth
   * @param amount of eth to rescue
   */
  function emergencyEtherTransfer(address to, uint256 amount) external;

  /**
  * @notice method to check if there is a new emergency state, indicated by chainlink emergency oracle.
         This method is callable by anyone as a new emergency will be determined by the oracle, and this way
         it will be easier / faster to enter into emergency.
  * @param newConfirmations number of confirmations necessary for a message to be routed to destination
  * @param newValidityTimestamp timestamp in seconds indicating the point to where not confirmed messages will be
  *        invalidated.
  * @param receiverBridgeAdaptersToAllow list of bridge adapter addresses to be allowed to receive messages
  * @param receiverBridgeAdaptersToDisallow list of bridge adapter addresses to be disallowed
  * @param sendersToApprove list of addresses to be approved as senders
  * @param sendersToRemove list of sender addresses to be removed
  * @param forwarderBridgeAdaptersToEnable list of bridge adapters to be enabled to send messages
  * @param forwarderBridgeAdaptersToDisable list of bridge adapters to be disabled
  */
  function solveEmergency(
    uint256 newConfirmations,
    uint120 newValidityTimestamp,
    address[] memory receiverBridgeAdaptersToAllow,
    address[] memory receiverBridgeAdaptersToDisallow,
    address[] memory sendersToApprove,
    address[] memory sendersToRemove,
    BridgeAdapterConfigInput[] memory forwarderBridgeAdaptersToEnable,
    BridgeAdapterToDisable[] memory forwarderBridgeAdaptersToDisable
  ) external;
}

File 10 of 13 : ICrossChainForwarder.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/**
 * @title ICrossChainForwarder
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the CrossChainForwarder contract
 */
interface ICrossChainForwarder {
  /**
   * @notice object storing the connected pair of bridge adapters, on current and destination chain
   * @param destinationBridgeAdapter address of the bridge adapter on the destination chain
   * @param currentChainBridgeAdapter address of the bridge adapter deployed on current network
   */
  struct ChainIdBridgeConfig {
    address destinationBridgeAdapter;
    address currentChainBridgeAdapter;
  }

  /**
   * @notice object with the necessary information to remove bridge adapters
   * @param bridgeAdapter address of the bridge adapter to remove
   * @param chainIds array of chain ids where the bridge adapter connects
   */
  struct BridgeAdapterToDisable {
    address bridgeAdapter;
    uint256[] chainIds;
  }

  /**
   * @notice object storing the pair bridgeAdapter (current deployed chain) destination chain bridge adapter configuration
   * @param currentChainBridgeAdapter address of the bridge adapter deployed on current chain
   * @param destinationBridgeAdapter address of the bridge adapter on the destination chain
   * @param dstChainId id of the destination chain using our own nomenclature
   */
  struct BridgeAdapterConfigInput {
    address currentChainBridgeAdapter;
    address destinationBridgeAdapter;
    uint256 destinationChainId;
  }

  /**
   * @notice emitted when a bridge adapter failed to send a message
   * @param destinationChainId id of the destination chain in our notation
   * @param bridgeAdapter address of the bridge adapter that failed (deployed on current network)
   * @param destinationBridgeAdapter address of the connected bridge adapter on destination chain
   * @param destinationChainId id of destination chain
   * @param message bytes intended to be bridged
   * @param returndata bytes with error information
   */
  event AdapterFailed(
    uint256 indexed destinationChainId,
    address indexed bridgeAdapter,
    address indexed destinationBridgeAdapter,
    bytes message,
    bytes returndata
  );

  /**
   * @notice emitted when a message is successfully forwarded through a bridge adapter
   * @param destinationChainId id of the destination chain in our notation
   * @param bridgeAdapter address of the bridge adapter that failed (deployed on current network)
   * @param destinationBridgeAdapter address of the connected bridge adapter on destination chain
   * @param destinationChainId id of destination chain
   * @param message bytes intended to be bridged
   */
  event MessageForwarded(
    uint256 indexed destinationChainId,
    address indexed bridgeAdapter,
    address indexed destinationBridgeAdapter,
    bytes message
  );

  /**
   * @notice emitted when a bridge adapter has been added to the allowed list
   * @param destinationChainId id of the destination chain in our notation
   * @param bridgeAdapter address of the bridge adapter added (deployed on current network)
   * @param destinationBridgeAdapter address of the connected bridge adapter on destination chain
   * @param allowed boolean indicating if the bridge adapter is allowed or disallowed
   */
  event BridgeAdapterUpdated(
    uint256 indexed destinationChainId,
    address indexed bridgeAdapter,
    address destinationBridgeAdapter,
    bool indexed allowed
  );

  /**
   * @notice emitted when a sender has been updated
   * @param sender address of the updated sender
   * @param isApproved boolean that indicates if the sender has been approved or removed
   */
  event SenderUpdated(address indexed sender, bool indexed isApproved);

  /**
   * @notice method to get the current sent message nonce
   * @return the current nonce
   */
  function getCurrentNonce() external view returns (uint256);

  /**
   * @notice method to check if a message has been previously forwarded.
   * @param destinationChainId id of the destination chain where the message needs to be bridged
   * @param origin address where the message originates from
   * @param destination address where the message is intended for
   * @param message bytes that need to be bridged
   * @return boolean indicating if the message has been forwarded
   */
  function isMessageForwarded(
    uint256 destinationChainId,
    address origin,
    address destination,
    bytes memory message
  ) external view returns (bool);

  /**
   * @notice method called to initiate message forwarding to other networks.
   * @param destinationChainId id of the destination chain where the message needs to be bridged
   * @param destination address where the message is intended for
   * @param gasLimit gas cost on receiving side of the message
   * @param message bytes that need to be bridged
   */
  function forwardMessage(
    uint256 destinationChainId,
    address destination,
    uint256 gasLimit,
    bytes memory message
  ) external;

  /**
   * @notice method called to re forward a previously sent message.
   * @param destinationChainId id of the destination chain where the message needs to be bridged
   * @param origin address where the message originates from
   * @param destination address where the message is intended for
   * @param gasLimit gas cost on receiving side of the message
   * @param message bytes that need to be bridged
   */
  function retryMessage(
    uint256 destinationChainId,
    address origin,
    address destination,
    uint256 gasLimit,
    bytes memory message
  ) external;

  /**
   * @notice method to enable bridge adapters
   * @param bridgeAdapters array of new bridge adapter configurations
   */
  function enableBridgeAdapters(BridgeAdapterConfigInput[] memory bridgeAdapters) external;

  /**
   * @notice method to disable bridge adapters
   * @param bridgeAdapters array of bridge adapter addresses to disable
   */
  function disableBridgeAdapters(BridgeAdapterToDisable[] memory bridgeAdapters) external;

  /**
   * @notice method to remove sender addresses
   * @param senders list of addresses to remove
   */
  function removeSenders(address[] memory senders) external;

  /**
   * @notice method to approve new sender addresses
   * @param senders list of addresses to approve
   */
  function approveSenders(address[] memory senders) external;

  /**
   * @notice method to get all the bridge adapters of a chain
   * @param chainId id of the chain we want to get the adateprs from
   * @return an array of chain configurations where the bridge adapter can communicate
   */
  function getBridgeAdaptersByChain(
    uint256 chainId
  ) external view returns (ChainIdBridgeConfig[] memory);

  /**
   * @notice method to get if a sender is approved
   * @param sender address that we want to check if approved
   * @return boolean indicating if the address has been approved as sender
   */
  function isSenderApproved(address sender) external view returns (bool);
}

File 11 of 13 : ICrossChainReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/**
 * @title ICrossChainReceiver
 * @author BGD Labs
 * @notice interface containing the objects, events and methods definitions of the CrossChainReceiver contract
 */
interface ICrossChainReceiver {
  /**
   * @notice object that stores the internal information of the message
   * @param confirmations number of times that this message has been bridged
   * @param bridgedByAdapterNonce stores the nonce of when the message has been bridged by a determined bridge adapter
   * @param delivered boolean indicating if the bridged message has been delivered to the destination
   */
  struct InternalBridgedMessageStateWithoutAdapters {
    uint120 confirmations;
    uint120 firstBridgedAt;
    bool delivered;
  }
  /**
   * @notice object that stores the internal information of the message
   * @param confirmations number of times that this message has been bridged
   * @param bridgedByAdapterNonce stores the nonce of when the message has been bridged by a determined bridge adapter
   * @param delivered boolean indicating if the bridged message has been delivered to the destination
   * @param bridgedByAdapter list of bridge adapters that have bridged the message
   */
  struct InternalBridgedMessage {
    uint120 confirmations;
    uint120 firstBridgedAt;
    bool delivered;
    mapping(address => bool) bridgedByAdapter;
  }

  /**
   * @notice emitted when a message has reached the necessary number of confirmations
   * @param msgDestination address of consumer of the message
   * @param msgOrigin address where the message originated
   * @param message bytes confirmed
   */
  event MessageConfirmed(address indexed msgDestination, address indexed msgOrigin, bytes message);

  /**
   * @notice emitted when a message has been received successfully
   * @param internalId message id assigned on the controller, used for internal purposes: hash(to, from, message)
   * @param bridgeAdapter address of the bridge adapter who received the message (deployed on current network)
   * @param msgDestination address of consumer of the message
   * @param msgOrigin address where the message originated (CrossChainController on origin chain)
   * @param message bytes bridged
   * @param confirmations number of current confirmations for this message
   */
  event MessageReceived(
    bytes32 internalId,
    address indexed bridgeAdapter,
    address indexed msgDestination,
    address indexed msgOrigin,
    bytes message,
    uint256 confirmations
  );

  /**
   * @notice emitted when a bridge adapter gets disallowed
   * @param brigeAdapter address of the disallowed bridge adapter
   * @param allowed boolean indicating if the bridge adapter has been allowed or disallowed
   */
  event ReceiverBridgeAdaptersUpdated(address indexed brigeAdapter, bool indexed allowed);

  /**
   * @notice emitted when number of confirmations needed to validate a message changes
   * @param newConfirmations number of new confirmations needed for a message to be valid
   */
  event ConfirmationsUpdated(uint256 newConfirmations);

  /**
   * @notice emitted when a new timestamp for invalidations gets set
   * @param invalidTimestamp timestamp to invalidate previous messages
   */
  event NewInvalidation(uint256 invalidTimestamp);

  /**
   * @notice method to get the needed confirmations for a message to be accepted as valid
   * @return the number of required bridged message confirmations (how many bridges have bridged the message correctly)
   *         for a message to be sent to destination
   */
  function getRequiredConfirmations() external view returns (uint256);

  /**
   * @notice method to get the timestamp from where the messages will be valid
   * @return timestamp indicating the point from where the messages are valid.
   */
  function getValidityTimestamp() external view returns (uint120);

  /**
   * @notice method to get if a bridge adapter is allowed
   * @param bridgeAdapter address of the brige adapter to check
   * @return boolean indicating if brige adapter is allowed
   */
  function isReceiverBridgeAdapterAllowed(address bridgeAdapter) external view returns (bool);

  /**
   * @notice  method to get the internal message information
   * @param internalId hash(originChain + payload) identifying the message internally
   * @return number of confirmations of internal message identified by internalId and the updated timestamp
   */
  function getInternalMessageState(
    bytes32 internalId
  ) external view returns (InternalBridgedMessageStateWithoutAdapters memory);

  /**
   * @notice method to get if message has been received by bridge adapter
   * @param internalId id of the message as stored internally
   * @param bridgeAdapter address of the bridge adapter to check if it has bridged the message
   * @return boolean indicating if the message has been received
   */
  function isInternalMessageReceivedByAdapter(
    bytes32 internalId,
    address bridgeAdapter
  ) external view returns (bool);

  /**
   * @notice method to set a new timestamp from where the messages will be valid.
   * @param newValidityTimestamp timestamp where all the previous unconfirmed messages must be invalidated.
   */
  function updateMessagesValidityTimestamp(uint120 newValidityTimestamp) external;

  /**
   * @notice method to update the number of confirmations necessary for the messages to be accepted as valid
   * @param newConfirmations new number of needed confirmations
   */
  function updateConfirmations(uint256 newConfirmations) external;

  /**
   * @notice method that registers a received message, updates the confirmations, and sets it as valid if number
   of confirmations has been reached.
   * @param payload bytes of the payload, containing the information to operate with it
   */
  function receiveCrossChainMessage(bytes memory payload, uint256 originChainId) external;

  /**
   * @notice method to add bridge adapters to the allowed list
   * @param bridgeAdapters array of new bridge adapter configurations
   */
  function allowReceiverBridgeAdapters(address[] memory bridgeAdapters) external;

  /**
   * @notice method to remove bridge adapters from the allowed list
   * @param bridgeAdapters array of bridge adapter addresses to remove from the allow list
   */
  function disallowReceiverBridgeAdapters(address[] memory bridgeAdapters) external;
}

File 12 of 13 : ChainIds.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library MainnetChainIds {
  uint256 constant ETHEREUM = 1;
  uint256 constant POLYGON = 137;
  uint256 constant AVALANCHE = 43114;
  uint256 constant ARBITRUM = 42161;
  uint256 constant OPTIMISM = 10;
  uint256 constant FANTOM = 250;
  uint256 constant HARMONY = 1666600000;
}

library TestnetChainIds {
  uint256 constant ETHEREUM_GOERLI = 5;
  uint256 constant POLYGON_MUMBAI = 80001;
  uint256 constant AVALANCHE_FUJI = 43113;
  uint256 constant ARBITRUM_GOERLI = 421613;
  uint256 constant OPTIMISM_GOERLI = 420;
  uint256 constant FANTOM_TESTNET = 4002;
  uint256 constant HARMONY_TESTNET = 1666700000;
  uint256 constant ETHEREUM_SEPOLIA = 11155111;
}

File 13 of 13 : Errors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
 * @title Errors library
 * @author BGD Labs
 * @notice Defines the error messages emitted by the different contracts of the Aave Governance V3
 */
library Errors {
  string public constant ETH_TRANSFER_FAILED = '1'; // failed to transfer eth to destination
  string public constant CALLER_IS_NOT_APPROVED_SENDER = '2'; // caller must be an approved message sender
  string public constant MESSAGE_REQUIRED_TO_HAVE_BEEN_PREVIOUSLY_FORWARDED = '3'; // message can only be retried if it has been previously forwarded
  string public constant NO_MESSAGE_FORWARDED_SUCCESSFULLY = '4'; // message was not able to be forwarded
  string public constant CURRENT_OR_DESTINATION_CHAIN_ADAPTER_NOT_SET = '5'; // can not enable bridge adapter if the current or destination chain adapter is 0 address
  string public constant CALLER_NOT_APPROVED_BRIDGE = '6'; // caller must be an approved bridge
  string public constant TIMESTAMP_ALREADY_PASSED = '7'; // timestamp is older than current timestamp (in the past)
  string public constant CALLER_NOT_CCIP_ROUTER = '8'; // caller must be bridge provider contract
  string public constant CCIP_ROUTER_CANT_BE_ADDRESS_0 = '9'; // CCIP bridge adapters needs a CCIP Router
  string public constant RECEIVER_NOT_SET = '10'; // receiver address on destination chain can not be 0
  string public constant DESTINATION_CHAIN_ID_NOT_SUPPORTED = '11'; // destination chain id must be supported by bridge provider
  string public constant NOT_ENOUGH_VALUE_TO_PAY_BRIDGE_FEES = '12'; // cross chain controller does not have enough funds to forward the message
  string public constant INCORRECT_ORIGIN_CHAIN_ID = '13'; // message origination chain id is not from a supported chain
  string public constant REMOTE_NOT_TRUSTED = '14'; // remote address has not been registered as a trusted origin
  string public constant CALLER_NOT_HL_MAILBOX = '15'; // caller must be the HyperLane Mailbox contract
}

Settings
{
  "remappings": [
    "@aave/core-v3/=lib/aave-a-token-with-delegation/lib/aave-address-book/lib/aave-v3-core/",
    "@aave/periphery-v3/=lib/aave-a-token-with-delegation/lib/aave-address-book/lib/aave-v3-periphery/",
    "@openzeppelin/=lib/aave-crosschain-infra/lib/openzeppelin-contracts/",
    "aave-a-token-with-delegation/=lib/aave-a-token-with-delegation/src/",
    "aave-address-book/=lib/aave-a-token-with-delegation/lib/aave-address-book/src/",
    "aave-crosschain-infra/=lib/aave-crosschain-infra/src/",
    "aave-helpers/=lib/aave-stk-gov-v3/lib/aave-helpers/",
    "aave-stk-gov-v3/=lib/aave-stk-gov-v3/src/",
    "aave-stk-slashing-mgmt/=lib/aave-stk-slashing-mgmt/src/",
    "aave-token-v2/=lib/aave-token-v3/lib/aave-token-v2/contracts/",
    "aave-token-v3/=lib/aave-token-v3/src/",
    "aave-v3-core/=lib/aave-a-token-with-delegation/lib/aave-v3-core/",
    "aave-v3-periphery/=lib/aave-a-token-with-delegation/lib/aave-address-book/lib/aave-v3-periphery/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "emergency-exit/=lib/emergency-exit/src/",
    "erc4626-tests/=lib/aave-stk-gov-v3/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "hyperlane-monorepo/=lib/aave-crosschain-infra/lib/hyperlane-monorepo/solidity/",
    "openzeppelin-contracts/=lib/aave-crosschain-infra/lib/openzeppelin-contracts/",
    "solidity-examples/=lib/aave-crosschain-infra/lib/solidity-examples/contracts/",
    "solidity-utils/=lib/solidity-utils/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"crossChainController","type":"address"},{"internalType":"address","name":"ccipRouter","type":"address"},{"components":[{"internalType":"address","name":"originForwarder","type":"address"},{"internalType":"uint256","name":"originChainId","type":"uint256"}],"internalType":"struct ICCIPAdapter.TrustedRemotesConfig[]","name":"trustedRemotes","type":"tuple[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"srcAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"CCIPPayloadProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint64","name":"destinationChainId","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"MessageForwarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"originChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"originForwarder","type":"address"}],"name":"SetTrustedRemote","type":"event"},{"inputs":[],"name":"CCIP_ROUTER","outputs":[{"internalType":"contract IRouterClient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CROSS_CHAIN_CONTROLLER","outputs":[{"internalType":"contract ICrossChainController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainId","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"tokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"forwardMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"getTrustedRemoteByChainId","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"infraChainId","type":"uint256"}],"name":"infraToNativeChainId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"nativeChainId","type":"uint64"}],"name":"nativeToInfraChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]

60c06040523480156200001157600080fd5b506040516200128b3803806200128b83398101604081905262000034916200024d565b6001600160a01b038084166080526040805180820190915260018152603960f81b6020820152908316620000865760405162461bcd60e51b81526004016200007d919062000358565b60405180910390fd5b506001600160a01b03821660a0526200009f81620000a8565b505050620003f0565b60005b8151811015620001b857818181518110620000ca57620000ca620003b0565b602002602001015160000151600080848481518110620000ee57620000ee620003b0565b602002602001015160200151815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550818181518110620001415762000141620003b0565b6020026020010151600001516001600160a01b03168282815181106200016b576200016b620003b0565b6020026020010151602001517fa214744f665691ef0eb9e4277cfa3c9198106c8925d6fa6880b6813f705c1aab60405160405180910390a380620001af81620003c6565b915050620000ab565b5050565b80516001600160a01b0381168114620001d457600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620002145762000214620001d9565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620002455762000245620001d9565b604052919050565b6000806000606084860312156200026357600080fd5b6200026e84620001bc565b925060206200027f818601620001bc565b604086810151919450906001600160401b03808211156200029f57600080fd5b818801915088601f830112620002b457600080fd5b815181811115620002c957620002c9620001d9565b620002d9858260051b016200021a565b818152858101925060069190911b83018501908a821115620002fa57600080fd5b928501925b81841015620003485784848c031215620003195760008081fd5b62000323620001ef565b6200032e85620001bc565b8152848701518782015283529284019291850191620002ff565b8096505050505050509250925092565b600060208083528351808285015260005b81811015620003875785810183015185820160400152820162000369565b818111156200039a576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620003e957634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051610e5262000439600039600081816101960152818161021b015281816103fb015281816104cc01526105d901526000818161014401526109cf0152610e526000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063bf7decbf1161005b578063bf7decbf1461011e578063c49563661461013f578063d688758114610166578063fe5f42ca1461019157600080fd5b806301ffc9a71461008d57806336da7a06146100b557806385572ffb146100ca578063b86a6161146100dd575b600080fd5b6100a061009b366004610a3c565b6101b8565b60405190151581526020015b60405180910390f35b6100c86100c3366004610a9b565b6101ef565b005b6100c86100d8366004610b71565b6105b6565b6101066100eb366004610bab565b6000908152602081905260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016100ac565b61013161012c366004610bc4565b61077c565b6040519081526020016100ac565b6101067f000000000000000000000000000000000000000000000000000000000000000081565b610179610174366004610bab565b6108d4565b6040516001600160401b0390911681526020016100ac565b6101067f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b031982166385572ffb60e01b14806101e957506001600160e01b031982166301ffc9a760e01b145b92915050565b60006101fa836108d4565b604051631491520b60e31b81526001600160401b03821660048201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a48a905890602401602060405180830381865afa15801561026a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028e9190610bed565b60405180604001604052806002815260200161313160f01b815250906102d05760405162461bcd60e51b81526004016102c79190610c5c565b60405180910390fd5b50604080518082019091526002815261031360f41b60208201526001600160a01b0386166103115760405162461bcd60e51b81526004016102c79190610c5c565b50604080518082018252858152600060208083018281528451602481018a905290511515604480830191909152855180830390910181526064909101855280820180516001600160e01b03166397a657c960e01b179052845160a0810186526001600160a01b038b1660c0808301919091528651808303909101815260e082018752815280830188905285518481529283018652939490939190820190836103db565b60408051808201909152600080825260208201528152602001906001900390816103b45790505b50815260200160006001600160a01b0316815260200183815250905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320487ded86846040518363ffffffff1660e01b8152600401610447929190610c6f565b602060405180830381865afa158015610464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104889190610d48565b90508047101560405180604001604052806002815260200161189960f11b815250906104c75760405162461bcd60e51b81526004016102c79190610c5c565b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166396f4e9f98388866040518463ffffffff1660e01b8152600401610519929190610c6f565b60206040518083038185885af1158015610537573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061055c9190610d48565b905080866001600160401b03168b6001600160a01b03167f4a9408cab2f56e376c439be33e07d1248efa2ec3336b1c26f6fa178d54df0b0c8a6040516105a29190610c5c565b60405180910390a450505050505050505050565b6040805180820190915260018152600760fb1b6020820152336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106175760405162461bcd60e51b81526004016102c79190610c5c565b5060006106276040830183610d61565b8101906106349190610dae565b9050600061064b61012c6040850160208601610bc4565b604080518082019091526002815261313360f01b6020820152909150816106855760405162461bcd60e51b81526004016102c79190610c5c565b506000818152602081815260409182902054825180840190935260028352610c4d60f21b918301919091526001600160a01b038481169116146106db5760405162461bcd60e51b81526004016102c79190610c5c565b506107286106ec6060850185610d61565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508592506109b8915050565b6001600160a01b038216817f9fb3f8b434b095acfff7d47cc0daadc9670bf8a385e1b38351aa92b2edfd730d6107616060870187610d61565b60405161076f929190610dcb565b60405180910390a3505050565b60006001600160401b0382166001141561079857506001919050565b6001600160401b03821661a86a14156107b4575061a86a919050565b6001600160401b038216608914156107ce57506089919050565b6001600160401b03821661a4b114156107ea575061a4b1919050565b6001600160401b038216600a14156108045750600a919050565b6001600160401b03821660fa141561081e575060fa919050565b6001600160401b0382166363564c40141561083e57506363564c40919050565b6001600160401b0382166005141561085857506005919050565b6001600160401b03821661a8691415610874575061a869919050565b6001600160401b0382166101a4141561089057506101a4919050565b6001600160401b0382166201388114156108ae575062013881919050565b6001600160401b03821662aa36a714156108cc575062aa36a7919050565b506000919050565b600060018214156108e757506001919050565b61a86a8214156108fa575061a86a919050565b608982141561090b57506089919050565b61a4b182141561091e575061a4b1919050565b600a82141561092f5750600a919050565b60fa821415610940575060fa919050565b6363564c4082141561095757506363564c40919050565b600582141561096857506005919050565b61a86982141561097b575061a869919050565b6101a482141561098e57506101a4919050565b620138818214156109a3575062013881919050565b62aa36a78214156108cc575062aa36a7919050565b6040516376b42cad60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ed68595a90610a069085908590600401610dfa565b600060405180830381600087803b158015610a2057600080fd5b505af1158015610a34573d6000803e3d6000fd5b505050505050565b600060208284031215610a4e57600080fd5b81356001600160e01b031981168114610a6657600080fd5b9392505050565b6001600160a01b0381168114610a8257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215610ab157600080fd5b8435610abc81610a6d565b9350602085013592506040850135915060608501356001600160401b0380821115610ae657600080fd5b818701915087601f830112610afa57600080fd5b813581811115610b0c57610b0c610a85565b604051601f8201601f19908116603f01168101908382118183101715610b3457610b34610a85565b816040528281528a6020848701011115610b4d57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600060208284031215610b8357600080fd5b81356001600160401b03811115610b9957600080fd5b820160a08185031215610a6657600080fd5b600060208284031215610bbd57600080fd5b5035919050565b600060208284031215610bd657600080fd5b81356001600160401b0381168114610a6657600080fd5b600060208284031215610bff57600080fd5b81518015158114610a6657600080fd5b6000815180845260005b81811015610c3557602081850181015186830182015201610c19565b81811115610c47576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610a666020830184610c0f565b600060406001600160401b038516835260208181850152845160a083860152610c9b60e0860182610c0f565b905081860151603f1980878403016060880152610cb88383610c0f565b88860151888203830160808a01528051808352908601945060009350908501905b80841015610d0b57845180516001600160a01b0316835286015186830152938501936001939093019290860190610cd9565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550610d3a8187610c0f565b9a9950505050505050505050565b600060208284031215610d5a57600080fd5b5051919050565b6000808335601e19843603018112610d7857600080fd5b8301803591506001600160401b03821115610d9257600080fd5b602001915036819003821315610da757600080fd5b9250929050565b600060208284031215610dc057600080fd5b8135610a6681610a6d565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b604081526000610e0d6040830185610c0f565b9050826020830152939250505056fea26469706673582212203cff96e9ddabdd379e85fcbc430838a3dded52be555fc22a7b2d5456b460c5a664736f6c634300080a00330000000000000000000000004d2f1c99bce324b9ba486d704a0235a754d188a20000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f640cea278e94708c358d79e5872afda5601011700000000000000000000000000000000000000000000000000000000000001a40000000000000000000000004a5d71f7027684d473a1110a412b510354af33e7000000000000000000000000000000000000000000000000000000000000a869

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063bf7decbf1161005b578063bf7decbf1461011e578063c49563661461013f578063d688758114610166578063fe5f42ca1461019157600080fd5b806301ffc9a71461008d57806336da7a06146100b557806385572ffb146100ca578063b86a6161146100dd575b600080fd5b6100a061009b366004610a3c565b6101b8565b60405190151581526020015b60405180910390f35b6100c86100c3366004610a9b565b6101ef565b005b6100c86100d8366004610b71565b6105b6565b6101066100eb366004610bab565b6000908152602081905260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016100ac565b61013161012c366004610bc4565b61077c565b6040519081526020016100ac565b6101067f0000000000000000000000004d2f1c99bce324b9ba486d704a0235a754d188a281565b610179610174366004610bab565b6108d4565b6040516001600160401b0390911681526020016100ac565b6101067f0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b81565b60006001600160e01b031982166385572ffb60e01b14806101e957506001600160e01b031982166301ffc9a760e01b145b92915050565b60006101fa836108d4565b604051631491520b60e31b81526001600160401b03821660048201529091507f0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b6001600160a01b03169063a48a905890602401602060405180830381865afa15801561026a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028e9190610bed565b60405180604001604052806002815260200161313160f01b815250906102d05760405162461bcd60e51b81526004016102c79190610c5c565b60405180910390fd5b50604080518082019091526002815261031360f41b60208201526001600160a01b0386166103115760405162461bcd60e51b81526004016102c79190610c5c565b50604080518082018252858152600060208083018281528451602481018a905290511515604480830191909152855180830390910181526064909101855280820180516001600160e01b03166397a657c960e01b179052845160a0810186526001600160a01b038b1660c0808301919091528651808303909101815260e082018752815280830188905285518481529283018652939490939190820190836103db565b60408051808201909152600080825260208201528152602001906001900390816103b45790505b50815260200160006001600160a01b0316815260200183815250905060007f0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b6001600160a01b03166320487ded86846040518363ffffffff1660e01b8152600401610447929190610c6f565b602060405180830381865afa158015610464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104889190610d48565b90508047101560405180604001604052806002815260200161189960f11b815250906104c75760405162461bcd60e51b81526004016102c79190610c5c565b5060007f0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b6001600160a01b03166396f4e9f98388866040518463ffffffff1660e01b8152600401610519929190610c6f565b60206040518083038185885af1158015610537573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061055c9190610d48565b905080866001600160401b03168b6001600160a01b03167f4a9408cab2f56e376c439be33e07d1248efa2ec3336b1c26f6fa178d54df0b0c8a6040516105a29190610c5c565b60405180910390a450505050505050505050565b6040805180820190915260018152600760fb1b6020820152336001600160a01b037f0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b16146106175760405162461bcd60e51b81526004016102c79190610c5c565b5060006106276040830183610d61565b8101906106349190610dae565b9050600061064b61012c6040850160208601610bc4565b604080518082019091526002815261313360f01b6020820152909150816106855760405162461bcd60e51b81526004016102c79190610c5c565b506000818152602081815260409182902054825180840190935260028352610c4d60f21b918301919091526001600160a01b038481169116146106db5760405162461bcd60e51b81526004016102c79190610c5c565b506107286106ec6060850185610d61565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508592506109b8915050565b6001600160a01b038216817f9fb3f8b434b095acfff7d47cc0daadc9670bf8a385e1b38351aa92b2edfd730d6107616060870187610d61565b60405161076f929190610dcb565b60405180910390a3505050565b60006001600160401b0382166001141561079857506001919050565b6001600160401b03821661a86a14156107b4575061a86a919050565b6001600160401b038216608914156107ce57506089919050565b6001600160401b03821661a4b114156107ea575061a4b1919050565b6001600160401b038216600a14156108045750600a919050565b6001600160401b03821660fa141561081e575060fa919050565b6001600160401b0382166363564c40141561083e57506363564c40919050565b6001600160401b0382166005141561085857506005919050565b6001600160401b03821661a8691415610874575061a869919050565b6001600160401b0382166101a4141561089057506101a4919050565b6001600160401b0382166201388114156108ae575062013881919050565b6001600160401b03821662aa36a714156108cc575062aa36a7919050565b506000919050565b600060018214156108e757506001919050565b61a86a8214156108fa575061a86a919050565b608982141561090b57506089919050565b61a4b182141561091e575061a4b1919050565b600a82141561092f5750600a919050565b60fa821415610940575060fa919050565b6363564c4082141561095757506363564c40919050565b600582141561096857506005919050565b61a86982141561097b575061a869919050565b6101a482141561098e57506101a4919050565b620138818214156109a3575062013881919050565b62aa36a78214156108cc575062aa36a7919050565b6040516376b42cad60e11b81526001600160a01b037f0000000000000000000000004d2f1c99bce324b9ba486d704a0235a754d188a2169063ed68595a90610a069085908590600401610dfa565b600060405180830381600087803b158015610a2057600080fd5b505af1158015610a34573d6000803e3d6000fd5b505050505050565b600060208284031215610a4e57600080fd5b81356001600160e01b031981168114610a6657600080fd5b9392505050565b6001600160a01b0381168114610a8257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215610ab157600080fd5b8435610abc81610a6d565b9350602085013592506040850135915060608501356001600160401b0380821115610ae657600080fd5b818701915087601f830112610afa57600080fd5b813581811115610b0c57610b0c610a85565b604051601f8201601f19908116603f01168101908382118183101715610b3457610b34610a85565b816040528281528a6020848701011115610b4d57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600060208284031215610b8357600080fd5b81356001600160401b03811115610b9957600080fd5b820160a08185031215610a6657600080fd5b600060208284031215610bbd57600080fd5b5035919050565b600060208284031215610bd657600080fd5b81356001600160401b0381168114610a6657600080fd5b600060208284031215610bff57600080fd5b81518015158114610a6657600080fd5b6000815180845260005b81811015610c3557602081850181015186830182015201610c19565b81811115610c47576000602083870101525b50601f01601f19169290920160200192915050565b602081526000610a666020830184610c0f565b600060406001600160401b038516835260208181850152845160a083860152610c9b60e0860182610c0f565b905081860151603f1980878403016060880152610cb88383610c0f565b88860151888203830160808a01528051808352908601945060009350908501905b80841015610d0b57845180516001600160a01b0316835286015186830152938501936001939093019290860190610cd9565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550610d3a8187610c0f565b9a9950505050505050505050565b600060208284031215610d5a57600080fd5b5051919050565b6000808335601e19843603018112610d7857600080fd5b8301803591506001600160401b03821115610d9257600080fd5b602001915036819003821315610da757600080fd5b9250929050565b600060208284031215610dc057600080fd5b8135610a6681610a6d565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b604081526000610e0d6040830185610c0f565b9050826020830152939250505056fea26469706673582212203cff96e9ddabdd379e85fcbc430838a3dded52be555fc22a7b2d5456b460c5a664736f6c634300080a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000004d2f1c99bce324b9ba486d704a0235a754d188a20000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000f640cea278e94708c358d79e5872afda5601011700000000000000000000000000000000000000000000000000000000000001a40000000000000000000000004a5d71f7027684d473a1110a412b510354af33e7000000000000000000000000000000000000000000000000000000000000a869

-----Decoded View---------------
Arg [0] : crossChainController (address): 0x4d2F1C99BCE324B9Ba486d704A0235A754D188a2
Arg [1] : ccipRouter (address): 0x0A36795B3006f50088c11ea45b960A1b0406f03b
Arg [2] : trustedRemotes (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000004d2f1c99bce324b9ba486d704a0235a754d188a2
Arg [1] : 0000000000000000000000000a36795b3006f50088c11ea45b960a1b0406f03b
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [4] : 000000000000000000000000f640cea278e94708c358d79e5872afda56010117
Arg [5] : 00000000000000000000000000000000000000000000000000000000000001a4
Arg [6] : 0000000000000000000000004a5d71f7027684d473a1110a412b510354af33e7
Arg [7] : 000000000000000000000000000000000000000000000000000000000000a869


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.