FastSwitchboard | Address 0x0391086Ae0fc3bd579342850553e0d84e6bDe5b0 | Etherscan (2023)

FastSwitchboard | Address 0x0391086Ae0fc3bd579342850553e0d84e6bDe5b0 | Etherscan (1)

0x0391086Ae0fc3bd579342850553e0d84e6bDe5b0

Source Code

    Check Previous Balance

Overview

ETH Balance

0 ETH

More Info

ContractCreator

0x752B38...b7e040Aa at txn 0xedc4f6ba6338118cdf01e6c0097720aaf8dd199c51c0905095e5000b101e7971

Multi Chain

Multichain Addresses

1 address found via Blockscan

  • Transactions
  • Token Transfers (ERC-20)
  • Contract
  • Events

Latest 1 from a total of 1 transactions

  • View Completed Txns
  • View Pending Txns
  • View Failed Txns
  • View Outgoing Txns
  • View Incoming Txns
  • View Contract Creation
Transaction Hash

Method

Block

From

To

Value

0xedc4f6ba6338118cdf01e6c0097720aaf8dd199c51c0905095e5000b101e7971

0x60c06040885962941 days 13 hrs ago

0x752B38...b7e040Aa

IN

Create: FastSwitchboard

0 ETH0.00433907

Advanced mode:

(Video) Etherscan Wallet Alerts Tutorial - No Code Needed! Monitor Any Crypto Wallet For New Transaction
Parent Txn HashBlockFromToValue

View All Internal Transactions

Loading...

Loading

  • Code
  • Read Contract
  • Write Contract

Contract Source Code Verified (Exact Match)

Contract Name:

FastSwitchboard

Compiler Version

v0.8.7+commit.e28d00a7

Optimization Enabled:

Yes with 999999 runs

Other Settings:

default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

  • Similar
  • Sol2Uml
  • Submit Audit
  • Compare

File 1 of 65 : CapacitorFactory.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./interfaces/ICapacitorFactory.sol";import "./capacitors/SingleCapacitor.sol";import "./capacitors/HashChainCapacitor.sol";import "./decapacitors/SingleDecapacitor.sol";import "./decapacitors/HashChainDecapacitor.sol";import "./libraries/RescueFundsLib.sol";import "./utils/AccessControlExtended.sol";import {RESCUE_ROLE} from "./utils/AccessRoles.sol";contract CapacitorFactory is ICapacitorFactory, AccessControlExtended { uint256 private constant SINGLE_CAPACITOR = 1; uint256 private constant HASH_CHAIN_CAPACITOR = 2; constructor(address owner_) AccessControlExtended(owner_) { _grantRole(RESCUE_ROLE, owner_); } function deploy( uint256 capacitorType_, uint256 /** siblingChainSlug */, uint256 /** maxPacketLength */ ) external override returns (ICapacitor, IDecapacitor) { address owner = this.owner(); if (capacitorType_ == SINGLE_CAPACITOR) { return ( new SingleCapacitor(msg.sender, owner), new SingleDecapacitor(owner) ); } if (capacitorType_ == HASH_CHAIN_CAPACITOR) { return ( new HashChainCapacitor(msg.sender, owner), new HashChainDecapacitor(owner) ); } revert InvalidCapacitorType(); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 2 of 65 : BaseCapacitor.sol

(Video) 🔴ETHERSCAN: How to Find Your Tokens | Step-by-Step Instructions

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/ICapacitor.sol";import "../utils/AccessControlExtended.sol";import "../libraries/RescueFundsLib.sol";import {RESCUE_ROLE} from "../utils/AccessRoles.sol";abstract contract BaseCapacitor is ICapacitor, AccessControlExtended { /// an incrementing id for each new packet created uint64 internal _nextPacketCount; uint64 internal _nextSealCount; address public immutable socket; /// maps the packet id with the root hash generated while adding message mapping(uint64 => bytes32) internal _roots; error NoPendingPacket(); error OnlySocket(); modifier onlySocket() { if (msg.sender != socket) revert OnlySocket(); _; } /** * @notice initialises the contract with socket address */ constructor(address socket_, address owner_) AccessControlExtended(owner_) { socket = socket_; } function sealPacket( uint256 ) external virtual override onlySocket returns (bytes32, uint64) { uint64 packetCount = _nextSealCount++; if (_roots[packetCount] == bytes32(0)) revert NoPendingPacket(); bytes32 root = _roots[packetCount]; return (root, packetCount); } /// returns the latest packet details to be sealed /// @inheritdoc ICapacitor function getNextPacketToBeSealed() external view virtual override returns (bytes32, uint64) { uint64 toSeal = _nextSealCount; return (_roots[toSeal], toSeal); } /// returns the root of packet for given id /// @inheritdoc ICapacitor function getRootByCount( uint64 id_ ) external view virtual override returns (bytes32) { return _roots[id_]; } function getLatestPacketCount() external view returns (uint256) { return _nextPacketCount == 0 ? 0 : _nextPacketCount - 1; } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 3 of 65 : HashChainCapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./BaseCapacitor.sol";contract HashChainCapacitor is BaseCapacitor { uint256 private _chainLength; uint256 private constant _MAX_LEN = 10; /** * @notice initialises the contract with socket address */ constructor( address socket_, address owner_ ) BaseCapacitor(socket_, owner_) { _grantRole(RESCUE_ROLE, owner_); } /// adds the packed message to a packet /// @inheritdoc ICapacitor function addPackedMessage( bytes32 packedMessage_ ) external override onlySocket { uint64 packetCount = _nextPacketCount; _roots[packetCount] = keccak256( abi.encode(_roots[packetCount], packedMessage_) ); _chainLength++; if (_chainLength == _MAX_LEN) { _nextPacketCount++; _chainLength = 0; } emit MessageAdded(packedMessage_, packetCount, _roots[packetCount]); }}

File 4 of 65 : SingleCapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./BaseCapacitor.sol";contract SingleCapacitor is BaseCapacitor { /** * @notice initialises the contract with socket address */ constructor( address socket_, address owner_ ) BaseCapacitor(socket_, owner_) { _grantRole(RESCUE_ROLE, owner_); } /// adds the packed message to a packet /// @inheritdoc ICapacitor function addPackedMessage( bytes32 packedMessage_ ) external override onlySocket { uint64 packetCount = _nextPacketCount; _roots[packetCount] = packedMessage_; _nextPacketCount++; emit MessageAdded(packedMessage_, packetCount, packedMessage_); }}

File 5 of 65 : HashChainDecapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IDecapacitor.sol";import "../libraries/RescueFundsLib.sol";import "../utils/AccessControlExtended.sol";import {RESCUE_ROLE} from "../utils/AccessRoles.sol";contract HashChainDecapacitor is IDecapacitor, AccessControlExtended { /** * @notice initialises the contract with owner address */ constructor(address owner_) AccessControlExtended(owner_) { _grantRole(RESCUE_ROLE, owner_); } /// returns if the packed message is the part of a merkle tree or not /// @inheritdoc IDecapacitor function verifyMessageInclusion( bytes32 root_, bytes32 packedMessage_, bytes calldata proof_ ) external pure override returns (bool) { bytes32[] memory chain = abi.decode(proof_, (bytes32[])); uint256 len = chain.length; bytes32 generatedRoot; bool isIncluded; for (uint256 i = 0; i < len; i++) { generatedRoot = keccak256(abi.encode(generatedRoot, chain[i])); if (chain[i] == packedMessage_) isIncluded = true; } return root_ == generatedRoot && isIncluded; } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 6 of 65 : SingleDecapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IDecapacitor.sol";import "../libraries/RescueFundsLib.sol";import "../utils/AccessControlExtended.sol";import {RESCUE_ROLE} from "../utils/AccessRoles.sol";contract SingleDecapacitor is IDecapacitor, AccessControlExtended { /** * @notice initialises the contract with owner address */ constructor(address owner_) AccessControlExtended(owner_) { _grantRole(RESCUE_ROLE, owner_); } /// returns if the packed message is the part of a merkle tree or not /// @inheritdoc IDecapacitor function verifyMessageInclusion( bytes32 root_, bytes32 packedMessage_, bytes calldata ) external pure override returns (bool) { return root_ == packedMessage_; } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 7 of 65 : Counter.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IPlug.sol";import "../interfaces/ISocket.sol";contract Counter is IPlug { // immutables address public immutable socket; address public owner; // application state uint256 public counter; // application ops bytes32 public constant OP_ADD = keccak256("OP_ADD"); bytes32 public constant OP_SUB = keccak256("OP_SUB"); error OnlyOwner(); constructor(address socket_) { socket = socket_; owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "can only be called by owner"); _; } function localAddOperation(uint256 amount_) external { _addOperation(amount_); } function localSubOperation(uint256 amount_) external { _subOperation(amount_); } function remoteAddOperation( uint256 chainSlug_, uint256 amount_, uint256 msgGasLimit_ ) external payable { bytes memory payload = abi.encode(OP_ADD, amount_, msg.sender); _outbound(chainSlug_, msgGasLimit_, payload); } function remoteSubOperation( uint256 chainSlug_, uint256 amount_, uint256 msgGasLimit_ ) external payable { bytes memory payload = abi.encode(OP_SUB, amount_, msg.sender); _outbound(chainSlug_, msgGasLimit_, payload); } function inbound( uint256, bytes calldata payload_ ) external payable override { require(msg.sender == socket, "Counter: Invalid Socket"); (bytes32 operationType, uint256 amount, ) = abi.decode( payload_, (bytes32, uint256, address) ); if (operationType == OP_ADD) { _addOperation(amount); } else if (operationType == OP_SUB) { _subOperation(amount); } else { revert("CounterMock: Invalid Operation"); } } function _outbound( uint256 targetChain_, uint256 msgGasLimit_, bytes memory payload_ ) private { ISocket(socket).outbound{value: msg.value}( targetChain_, msgGasLimit_, payload_ ); } // // base ops // function _addOperation(uint256 amount_) private { counter += amount_; } function _subOperation(uint256 amount_) private { require(counter > amount_, "CounterMock: Subtraction Overflow"); counter -= amount_; } // settings function setSocketConfig( uint256 remoteChainSlug_, address remotePlug_, address switchboard_ ) external onlyOwner { ISocket(socket).connect( remoteChainSlug_, remotePlug_, switchboard_, switchboard_ ); } function setupComplete() external { owner = address(0); }}

File 8 of 65 : Messenger.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IPlug.sol";import "../interfaces/ISocket.sol";import "../interfaces/ITransmitManager.sol";import "../interfaces/ISwitchboard.sol";import "../interfaces/IExecutionManager.sol";import "../utils/Ownable.sol";contract Messenger is IPlug, Ownable(msg.sender) { // immutables ISocket public immutable _socket__; uint256 public immutable _localChainSlug; bytes32 public _message; uint256 public _msgGasLimit; bytes32 public constant _PING = keccak256("PING"); bytes32 public constant _PONG = keccak256("PONG"); error NoSocketFee(); constructor(address socket_, uint256 chainSlug_, uint256 msgGasLimit_) { _socket__ = ISocket(socket_); _localChainSlug = chainSlug_; _msgGasLimit = msgGasLimit_; } receive() external payable {} function updateMsgGasLimit(uint256 msgGasLimit_) external onlyOwner { _msgGasLimit = msgGasLimit_; } function removeGas(address payable receiver_) external onlyOwner { receiver_.transfer(address(this).balance); } function sendLocalMessage(bytes32 message_) external { _updateMessage(message_); } function sendRemoteMessage( uint32 remoteChainSlug_, bytes32 message_ ) external payable { bytes memory payload = abi.encode(_localChainSlug, message_); _outbound(remoteChainSlug_, payload); } function inbound( uint256, bytes calldata payload_ ) external payable override { require(msg.sender == address(_socket__), "Counter: Invalid Socket"); (uint32 remoteChainSlug, bytes32 msgDecoded) = abi.decode( payload_, (uint32, bytes32) ); _updateMessage(msgDecoded); bytes memory newPayload = abi.encode( _localChainSlug, msgDecoded == _PING ? _PONG : _PING ); _outbound(remoteChainSlug, newPayload); } // settings function setSocketConfig( uint32 remoteChainSlug_, address remotePlug_, address switchboard_ ) external onlyOwner { _socket__.connect( remoteChainSlug_, remotePlug_, switchboard_, switchboard_ ); } function message() external view returns (bytes32) { return _message; } function _updateMessage(bytes32 message_) private { _message = message_; } function _outbound(uint32 targetChain_, bytes memory payload_) private { uint256 fee = _socket__.getMinFees( _msgGasLimit, targetChain_, address(this) ); if (!(address(this).balance >= fee)) revert NoSocketFee(); _socket__.outbound{value: fee}(targetChain_, _msgGasLimit, payload_); }}

File 9 of 65 : ExecutionManager.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;import "./interfaces/IExecutionManager.sol";import "./interfaces/IGasPriceOracle.sol";import "./utils/AccessControlExtended.sol";import "./libraries/RescueFundsLib.sol";import "./libraries/SignatureVerifierLib.sol";import "./libraries/FeesHelper.sol";import {WITHDRAW_ROLE, RESCUE_ROLE, GOVERNANCE_ROLE, EXECUTOR_ROLE} from "./utils/AccessRoles.sol";contract ExecutionManager is IExecutionManager, AccessControlExtended { IGasPriceOracle public gasPriceOracle__; event GasPriceOracleSet(address gasPriceOracle); constructor( IGasPriceOracle gasPriceOracle_, address owner_ ) AccessControlExtended(owner_) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); } function isExecutor( bytes32 packedMessage, bytes memory sig ) external view override returns (address executor, bool isValidExecutor) { executor = SignatureVerifierLib.recoverSignerFromDigest( packedMessage, sig ); isValidExecutor = _hasRole(EXECUTOR_ROLE, executor); } // these details might be needed for on-chain fee distribution later function updateExecutionFees(address, uint256, bytes32) external override {} function payFees( uint256 msgGasLimit_, uint32 siblingChainSlug_ ) external payable override {} function getMinFees( uint256 msgGasLimit_, uint32 siblingChainSlug_ ) external view override returns (uint256) { return _getMinExecutionFees(msgGasLimit_, siblingChainSlug_); } function _getMinExecutionFees( uint256 msgGasLimit_, uint32 dstChainSlug_ ) internal view returns (uint256) { uint256 dstRelativeGasPrice = gasPriceOracle__.relativeGasPrice( dstChainSlug_ ); return msgGasLimit_ * dstRelativeGasPrice; } /** * @notice updates gasPriceOracle__ * @param gasPriceOracle_ address of Gas Price Oracle */ function setGasPriceOracle( address gasPriceOracle_ ) external onlyRole(GOVERNANCE_ROLE) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); emit GasPriceOracleSet(gasPriceOracle_); } function withdrawFees(address account_) external onlyRole(WITHDRAW_ROLE) { FeesHelper.withdrawFees(account_); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 10 of 65 : GasPriceOracle.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./interfaces/IGasPriceOracle.sol";import "./interfaces/ITransmitManager.sol";import "./utils/AccessControlExtended.sol";import "./libraries/RescueFundsLib.sol";import {GOVERNANCE_ROLE, RESCUE_ROLE} from "./utils/AccessRoles.sol";contract GasPriceOracle is IGasPriceOracle, AccessControlExtended { ITransmitManager public transmitManager__; // plugs/switchboards/transmitter can use it to ensure prices are updated mapping(uint256 => uint256) public updatedAt; // chain slug => relative gas price mapping(uint32 => uint256) public override relativeGasPrice; // transmitter => nextNonce mapping(address => uint256) public nextNonce; // gas price of source chain uint256 public override sourceGasPrice; uint32 public immutable chainSlug; event TransmitManagerUpdated(address transmitManager); event RelativeGasPriceUpdated( uint256 dstChainSlug, uint256 relativeGasPrice ); event SourceGasPriceUpdated(uint256 sourceGasPrice); error TransmitterNotFound(); error InvalidNonce(); constructor( address owner_, uint32 chainSlug_ ) AccessControlExtended(owner_) { chainSlug = chainSlug_; } /** * @notice update the sourceGasPrice which is to be used in various computations * @param sourceGasPrice_ gas price of source chain */ function setSourceGasPrice( uint256 nonce_, uint256 sourceGasPrice_, bytes calldata signature_ ) external { (address transmitter, bool isTransmitter) = transmitManager__ .checkTransmitter( chainSlug, keccak256(abi.encode(chainSlug, nonce_, sourceGasPrice_)), signature_ ); if (!isTransmitter) revert TransmitterNotFound(); uint256 nonce = nextNonce[transmitter]++; if (nonce_ != nonce) revert InvalidNonce(); sourceGasPrice = sourceGasPrice_; updatedAt[chainSlug] = block.timestamp; emit SourceGasPriceUpdated(sourceGasPrice); } /** * @dev the relative prices are calculated as: * relativeGasPrice = (siblingGasPrice * siblingGasUSDPrice)/srcGasUSDPrice * It is assumed that precision of relative gas price will be same as src native tokens * So that when it is multiplied with gas limits at other contracts, we get correct values. */ function setRelativeGasPrice( uint32 siblingChainSlug_, uint256 nonce_, uint256 relativeGasPrice_, bytes calldata signature_ ) external { (address transmitter, bool isTransmitter) = transmitManager__ .checkTransmitter( siblingChainSlug_, keccak256( abi.encode( chainSlug, siblingChainSlug_, nonce_, relativeGasPrice_ ) ), signature_ ); if (!isTransmitter) revert TransmitterNotFound(); uint256 nonce = nextNonce[transmitter]++; if (nonce_ != nonce) revert InvalidNonce(); relativeGasPrice[siblingChainSlug_] = relativeGasPrice_; updatedAt[siblingChainSlug_] = block.timestamp; emit RelativeGasPriceUpdated(siblingChainSlug_, relativeGasPrice_); } function getGasPrices( uint32 siblingChainSlug_ ) external view override returns (uint256, uint256) { return (sourceGasPrice, relativeGasPrice[siblingChainSlug_]); } function setTransmitManager( ITransmitManager transmitManager_ ) external onlyRole(GOVERNANCE_ROLE) { transmitManager__ = transmitManager_; emit TransmitManagerUpdated(address(transmitManager_)); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 11 of 65 : ICapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface ICapacitor { /** * @notice emits the message details when it arrives * @param packedMessage the message packed with payload, fees and config * @param packetCount an incremental id assigned to each new packet * @param newRootHash the packed message hash (to be replaced with the root hash of the merkle tree) */ event MessageAdded( bytes32 packedMessage, uint64 packetCount, bytes32 newRootHash ); /** * @notice adds the packed message to a packet * @dev this should be only executable by socket * @dev it will be later replaced with a function adding each message to a merkle tree * @param packedMessage the message packed with payload, fees and config */ function addPackedMessage(bytes32 packedMessage) external; /** * @notice returns the latest packet details which needs to be sealed * @return root root hash of the latest packet which is not yet sealed * @return packetCount latest packet id which is not yet sealed */ function getNextPacketToBeSealed() external view returns (bytes32 root, uint64 packetCount); /** * @notice returns the root of packet for given id * @param id the id assigned to packet * @return root root hash corresponding to given id */ function getRootByCount(uint64 id) external view returns (bytes32 root); /** * @notice seals the packet * @dev also indicates the packet is ready to be shipped and no more messages can be added now. * @dev this should be executable by socket only * @return root root hash of the packet * @return packetCount id of the packed sealed */ function sealPacket( uint256 batchSize_ ) external returns (bytes32 root, uint64 packetCount);}

File 12 of 65 : ICapacitorFactory.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./ICapacitor.sol";import "./IDecapacitor.sol";interface ICapacitorFactory { error InvalidCapacitorType(); function deploy( uint256 capacitorType, uint256 siblingChainSlug, uint256 maxPacketLength ) external returns (ICapacitor, IDecapacitor);}

File 13 of 65 : IDecapacitor.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface IDecapacitor { /** * @notice returns if the packed message is the part of a merkle tree or not * @param root_ root hash of the merkle tree * @param packedMessage_ packed message which needs to be verified * @param proof_ proof used to determine the inclusion */ function verifyMessageInclusion( bytes32 root_, bytes32 packedMessage_, bytes calldata proof_ ) external pure returns (bool);}

File 14 of 65 : IExecutionManager.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;interface IExecutionManager { function isExecutor( bytes32 packedMessage, bytes memory sig ) external view returns (address, bool); function payFees(uint256 msgGasLimit, uint32 dstSlug) external payable; function getMinFees( uint256 msgGasLimit, uint32 dstSlug ) external view returns (uint256); function updateExecutionFees( address executor, uint256 executionFees, bytes32 msgId ) external;}

File 15 of 65 : IGasPriceOracle.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;interface IGasPriceOracle { function relativeGasPrice( uint32 dstChainSlug ) external view returns (uint256); function sourceGasPrice() external view returns (uint256); function getGasPrices( uint32 dstChainSlug_ ) external view returns (uint256, uint256);}

File 16 of 65 : IHasher.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface IHasher { /** * @notice returns the bytes32 hash of the message packed * @param srcChainSlug src chain slug * @param srcPlug address of plug at source * @param dstChainSlug remote chain slug * @param dstPlug address of plug at remote * @param msgId message id assigned at outbound * @param msgGasLimit gas limit which is expected to be consumed by the inbound transaction on plug * @param executionFee msg value which is expected to be sent with inbound transaction to plug * @param payload the data packed which is used by inbound for execution */ function packMessage( uint256 srcChainSlug, address srcPlug, uint256 dstChainSlug, address dstPlug, bytes32 msgId, uint256 msgGasLimit, uint256 executionFee, bytes calldata payload ) external returns (bytes32);}

File 17 of 65 : INativeRelay.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface INativeRelay { /** * @notice receiveMessage on PolygonRootReceiver * @param receivePacketProof receivePacketProof */ function receiveMessage(bytes memory receivePacketProof) external; function initiateNativeConfirmation( bytes32 packetId, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid ) external payable; function initiateNativeConfirmation(bytes32 packetId) external;}

File 18 of 65 : IPlug.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;interface IPlug { /** * @notice executes the message received from source chain * @dev this should be only executable by socket * @param srcChainSlug_ chain slug of source * @param payload_ the data which is needed by plug at inbound call on remote */ function inbound( uint256 srcChainSlug_, bytes calldata payload_ ) external payable;}

File 19 of 65 : ISignatureVerifier.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface ISignatureVerifier { /** * @notice returns the address of signer recovered from input signature * @param dstChainSlug_ remote chain slug * @param packetId_ packet id * @param root_ root hash of merkle tree * @param signature_ signature */ function recoverSigner( uint256 dstChainSlug_, uint256 packetId_, bytes32 root_, bytes calldata signature_ ) external pure returns (address signer); /** * @notice returns the address of signer recovered from input signature and digest */ function recoverSignerFromDigest( bytes32 digest_, bytes memory signature_ ) external pure returns (address signer);}

File 20 of 65 : ISocket.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;import "./ITransmitManager.sol";import "./IExecutionManager.sol";interface ISocket { /** * @param transmissionFees fees needed for transmission * @param switchboardFees fees needed by switchboard * @param executionFee fees needed for execution */ struct Fees { uint256 transmissionFees; uint256 switchboardFees; uint256 executionFee; } /** * @notice emits the message details when a new message arrives at outbound * @param localChainSlug local chain slug * @param localPlug local plug address * @param dstChainSlug remote chain slug * @param dstPlug remote plug address * @param msgId message id packed with remoteChainSlug and nonce * @param msgGasLimit gas limit needed to execute the inbound at remote * @param payload the data which will be used by inbound at remote */ event MessageOutbound( uint256 localChainSlug, address localPlug, uint256 dstChainSlug, address dstPlug, bytes32 msgId, uint256 msgGasLimit, bytes payload, Fees fees ); /** * @notice emits the status of message after inbound call * @param msgId msg id which is executed */ event ExecutionSuccess(bytes32 msgId); /** * @notice emits the status of message after inbound call * @param msgId msg id which is executed * @param result if message reverts, returns the revert message */ event ExecutionFailed(bytes32 msgId, string result); /** * @notice emits the error message in bytes after inbound call * @param msgId msg id which is executed * @param result if message reverts, returns the revert message in bytes */ event ExecutionFailedBytes(bytes32 msgId, bytes result); /** * @notice emits the config set by a plug for a remoteChainSlug * @param plug address of plug on current chain * @param siblingChainSlug sibling chain slug * @param siblingPlug address of plug on sibling chain * @param inboundSwitchboard inbound switchboard (select from registered options) * @param outboundSwitchboard outbound switchboard (select from registered options) * @param capacitor capacitor selected based on outbound switchboard * @param decapacitor decapacitor selected based on inbound switchboard */ event PlugConnected( address plug, uint256 siblingChainSlug, address siblingPlug, address inboundSwitchboard, address outboundSwitchboard, address capacitor, address decapacitor ); /** * @notice emits when a new transmitManager contract is set * @param transmitManager address of new transmitManager contract */ event TransmitManagerSet(address transmitManager); /** * @notice registers a message * @dev Packs the message and includes it in a packet with capacitor * @param remoteChainSlug_ the remote chain slug * @param msgGasLimit_ 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( uint256 remoteChainSlug_, uint256 msgGasLimit_, bytes calldata payload_ ) external payable returns (bytes32 msgId); struct MessageDetails { bytes32 msgId; uint256 executionFee; uint256 msgGasLimit; bytes payload; bytes decapacitorProof; } /** * @notice executes a message * @param packetId packet id * @param localPlug local plug address * @param messageDetails_ the details needed for message verification */ function execute( bytes32 packetId, address localPlug, ISocket.MessageDetails calldata messageDetails_, bytes memory signature ) external; /** * @notice seals data in capacitor for specific batchSizr * @param batchSize_ size of batch to be sealed * @param capacitorAddress_ address of capacitor * @param signature_ signed Data needed for verification */ function seal( uint256 batchSize_, address capacitorAddress_, bytes calldata signature_ ) external payable; /** * @notice proposes a packet * @param packetId_ packet id * @param root_ root data * @param signature_ signed Data needed for verification */ function propose( bytes32 packetId_, bytes32 root_, bytes calldata signature_ ) external; /** * @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( uint256 siblingChainSlug_, address siblingPlug_, address inboundSwitchboard_, address outboundSwitchboard_ ) external; function packetIdRoots(bytes32 packetId_) external view returns (bytes32); function getMinFees( uint256 msgGasLimit_, uint32 remoteChainSlug_, address plug_ ) external view returns (uint256 totalFees);}

File 21 of 65 : ISwitchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;interface ISwitchboard { function registerCapacitor( uint256 siblingChainSlug_, address capacitor_, uint256 maxPacketSize_ ) external; function allowPacket( bytes32 root, bytes32 packetId, uint32 srcChainSlug, uint256 proposeTime ) external view returns (bool); function payFees(uint32 dstChainSlug) external payable; function getMinFees( uint32 dstChainSlug ) external view returns (uint256 switchboardFee, uint256 verificationFee);}

File 22 of 65 : ITransmitManager.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;interface ITransmitManager { function checkTransmitter( uint32 siblingSlug, bytes32 digest, bytes calldata signature ) external view returns (address, bool); function payFees(uint32 dstSlug) external payable; function getMinFees(uint32 dstSlug) external view returns (uint256);}

File 23 of 65 : AddressAliasHelper.sol

// Copyright 2021-2022, Offchain Labs, Inc.// For license information, see https://github.com/nitro/blob/master/LICENSE// SPDX-License-Identifier: BUSL-1.1pragma solidity 0.8.7;library AddressAliasHelper { uint160 internal constant _OFFSET = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 /// @param l1Address_ the address in the L1 that triggered the tx to L2 /// @return l2Address L2 address as viewed in msg.sender function applyL1ToL2Alias( address l1Address_ ) internal pure returns (address l2Address) { unchecked { l2Address = address(uint160(l1Address_) + _OFFSET); } } /// @notice Utility function that converts the msg.sender viewed in the L2 to the /// address in the L1 that submitted a tx to the inbox /// @param l2Address_ L2 address as viewed in msg.sender /// @return l1Address the address in the L1 that triggered the tx to L2 function undoL1ToL2Alias( address l2Address_ ) internal pure returns (address l1Address) { unchecked { l1Address = address(uint160(l2Address_) - _OFFSET); } }}

File 24 of 65 : FeesHelper.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;library FeesHelper { error TransferFailed(); event FeesWithdrawn(address account, uint256 amount); // TODO: to support fee distribution /** * @notice transfers the fees collected to `account_` * @param account_ address to transfer ETH */ function withdrawFees(address account_) internal { require(account_ != address(0)); uint256 amount = address(this).balance; (bool success, ) = account_.call{value: amount}(""); if (!success) revert TransferFailed(); emit FeesWithdrawn(account_, amount); }}

File 25 of 65 : RescueFundsLib.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../libraries/SafeTransferLib.sol";library RescueFundsLib { using SafeTransferLib for IERC20; address public constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); function rescueFunds( address token_, address userAddress_, uint256 amount_ ) internal { require(userAddress_ != address(0)); if (token_ == ETH_ADDRESS) { (bool success, ) = userAddress_.call{value: address(this).balance}( "" ); require(success); } else { IERC20(token_).transfer(userAddress_, amount_); } }}

File 26 of 65 : SafeTransferLib.sol

// SPDX-License-Identifier: AGPL-3.0-onlypragma solidity 0.8.7;import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values./// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer./// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.library SafeTransferLib { function safeTransfer( IERC20 token_, address to_, uint256 amount_ ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore( freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000 ) mstore(add(freeMemoryPointer, 4), to_) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount_) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or( and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize()) ), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); }}

File 27 of 65 : SignatureVerifierLib.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;library SignatureVerifierLib { error InvalidSigLength(); function recoverSigner( uint256 destChainSlug_, uint256 packetId_, bytes32 root_, bytes calldata signature_ ) internal pure returns (address signer) { bytes32 digest = keccak256( abi.encode(destChainSlug_, packetId_, root_) ); signer = recoverSignerFromDigest(digest, signature_); } /** * @notice returns the address of signer recovered from input signature and digest */ function recoverSignerFromDigest( bytes32 digest_, bytes memory signature_ ) internal pure returns (address signer) { bytes32 digest = keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", digest_) ); (bytes32 sigR, bytes32 sigS, uint8 sigV) = _splitSignature(signature_); // recovered signer is checked for the valid roles later signer = ecrecover(digest, sigV, sigR, sigS); } /** * @notice splits the signature into v, r and s. */ function _splitSignature( bytes memory signature_ ) private pure returns (bytes32 r, bytes32 s, uint8 v) { if (signature_.length != 65) revert InvalidSigLength(); assembly { r := mload(add(signature_, 0x20)) s := mload(add(signature_, 0x40)) v := byte(0, mload(add(signature_, 0x60))) } }}

File 28 of 65 : MockAccessControl.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../utils/AccessControl.sol";contract MockAccessControl is AccessControl { bytes32 public constant ROLE_GIRAFFE = keccak256("ROLE_GIRAFFE"); bytes32 public constant ROLE_HIPPO = keccak256("ROLE_HIPPO"); constructor(address owner_) AccessControl(owner_) {} function giraffe() external onlyRole(ROLE_GIRAFFE) {} function hippo() external onlyRole(ROLE_HIPPO) {} function animal() external {}}

File 29 of 65 : MockOwnable.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../utils/Ownable.sol";contract MockOwnable is Ownable { constructor(address owner_) Ownable(owner_) {} function ownerFunction() external onlyOwner {} function publicFunction() external {}}

File 30 of 65 : Socket.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import {SocketSrc} from "./SocketSrc.sol";import "./SocketDst.sol";import "../libraries/RescueFundsLib.sol";import {RESCUE_ROLE} from "../utils/AccessRoles.sol";contract Socket is SocketSrc, SocketDst { constructor( uint32 chainSlug_, address hasher_, address transmitManager_, address executionManager_, address capacitorFactory_, address owner_ ) AccessControlExtended(owner_) SocketBase(chainSlug_) { hasher__ = IHasher(hasher_); transmitManager__ = ITransmitManager(transmitManager_); executionManager__ = IExecutionManager(executionManager_); capacitorFactory__ = ICapacitorFactory(capacitorFactory_); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 31 of 65 : SocketBase.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IHasher.sol";import "../interfaces/ITransmitManager.sol";import "../interfaces/IExecutionManager.sol";import "./SocketConfig.sol";abstract contract SocketBase is SocketConfig { IHasher public hasher__; ITransmitManager public transmitManager__; IExecutionManager public executionManager__; uint32 public immutable chainSlug; // incrementing nonce, should be handled in next socket version. uint224 public messageCount; constructor(uint32 chainSlug_) { chainSlug = chainSlug_; } error InvalidAttester(); event HasherSet(address hasher); event ExecutionManagerSet(address executionManager); function setHasher(address hasher_) external onlyRole(GOVERNANCE_ROLE) { hasher__ = IHasher(hasher_); emit HasherSet(hasher_); } /** * @notice updates transmitManager_ * @param transmitManager_ address of Transmit Manager */ function setTransmitManager( address transmitManager_ ) external onlyRole(GOVERNANCE_ROLE) { transmitManager__ = ITransmitManager(transmitManager_); emit TransmitManagerSet(transmitManager_); } /** * @notice updates executionManager_ * @param executionManager_ address of Execution Manager */ function setExecutionManager( address executionManager_ ) external onlyRole(GOVERNANCE_ROLE) { executionManager__ = IExecutionManager(executionManager_); emit ExecutionManagerSet(executionManager_); }}

File 32 of 65 : SocketBatcher.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../libraries/RescueFundsLib.sol";import "../utils/AccessControlExtended.sol";import {RESCUE_ROLE} from "../utils/AccessRoles.sol";import {ISocket} from "../interfaces/ISocket.sol";import {FastSwitchboard} from "../switchboard/default-switchboards/FastSwitchboard.sol";import {INativeRelay} from "../interfaces/INativeRelay.sol";contract SocketBatcher is AccessControlExtended { constructor(address owner_) AccessControlExtended(owner_) { _grantRole(RESCUE_ROLE, owner_); } struct SealRequest { uint256 batchSize; address capacitorAddress; bytes signature; } struct ProposeRequest { bytes32 packetId; bytes32 root; bytes signature; } struct AttestRequest { bytes32 packetId; uint256 srcChainSlug; bytes signature; } struct ExecuteRequest { bytes32 packetId; address localPlug; ISocket.MessageDetails messageDetails; bytes signature; } struct ArbitrumNativeInitiatorRequest { bytes32 packetId; uint256 maxSubmissionCost; uint256 maxGas; uint256 gasPriceBid; uint256 callValue; } /** * @notice seal a batch of packets from capacitor on sourceChain mentioned in sealRequests * @param socketAddress_ address of socket * @param sealRequests_ the list of requests with packets to be sealed on sourceChain */ function sealBatch( address socketAddress_, SealRequest[] calldata sealRequests_ ) external { uint256 sealRequestslength = sealRequests_.length; for (uint256 index = 0; index < sealRequestslength; ) { ISocket(socketAddress_).seal( sealRequests_[index].batchSize, sealRequests_[index].capacitorAddress, sealRequests_[index].signature ); unchecked { ++index; } } } /** * @notice propose a batch of packets sequentially by socketDestination * @param socketAddress_ address of socket * @param proposeRequests_ the list of requests with packets to be proposed by socketDestination */ function proposeBatch( address socketAddress_, ProposeRequest[] calldata proposeRequests_ ) external { uint256 proposeRequestslength = proposeRequests_.length; for (uint256 index = 0; index < proposeRequestslength; ) { ISocket(socketAddress_).propose( proposeRequests_[index].packetId, proposeRequests_[index].root, proposeRequests_[index].signature ); unchecked { ++index; } } } /** * @notice attests a batch of Packets * @param switchBoardAddress_ address of switchboard * @param attestRequests_ the list of requests with packets to be attested by switchboard in sequence */ function attestBatch( address switchBoardAddress_, AttestRequest[] calldata attestRequests_ ) external { uint256 attestRequestslength = attestRequests_.length; for (uint256 index = 0; index < attestRequestslength; ) { FastSwitchboard(switchBoardAddress_).attest( attestRequests_[index].packetId, attestRequests_[index].srcChainSlug, attestRequests_[index].signature ); unchecked { ++index; } } } /** * @notice executes a batch of messages * @param socketAddress_ address of socket * @param executeRequests_ the list of requests with messages to be executed in sequence */ function executeBatch( address socketAddress_, ExecuteRequest[] calldata executeRequests_ ) external { uint256 executeRequestslength = executeRequests_.length; for (uint256 index = 0; index < executeRequestslength; ) { ISocket(socketAddress_).execute( executeRequests_[index].packetId, executeRequests_[index].localPlug, executeRequests_[index].messageDetails, executeRequests_[index].signature ); unchecked { ++index; } } } /** * @notice invoke receieve Message on PolygonRootReceiver for a batch of messages in loop * @param polygonRootReceiverAddress_ address of polygonRootReceiver * @param receivePacketProofs_ the list of receivePacketProofs to be sent to receiveHook of polygonRootReceiver */ function receiveMessageBatch( address polygonRootReceiverAddress_, bytes[] calldata receivePacketProofs_ ) external { uint256 receivePacketProofsLength = receivePacketProofs_.length; for (uint256 index = 0; index < receivePacketProofsLength; ) { INativeRelay(polygonRootReceiverAddress_).receiveMessage( receivePacketProofs_[index] ); unchecked { ++index; } } } /** * @notice initiate NativeConfirmation on arbitrumChain for a batch of packets in loop * @param switchboardAddress_ address of nativeArbitrumSwitchboard * @param arbitrumNativeInitiatorRequests_ the list of requests with packets to initiate nativeConfirmation on switchboard of arbitrumChain */ function initiateArbitrumNativeBatch( address switchboardAddress_, ArbitrumNativeInitiatorRequest[] calldata arbitrumNativeInitiatorRequests_ ) external payable { uint256 arbitrumNativeInitiatorRequestsLength = arbitrumNativeInitiatorRequests_ .length; for ( uint256 index = 0; index < arbitrumNativeInitiatorRequestsLength; ) { INativeRelay(switchboardAddress_).initiateNativeConfirmation{ value: arbitrumNativeInitiatorRequests_[index].callValue }( arbitrumNativeInitiatorRequests_[index].packetId, arbitrumNativeInitiatorRequests_[index].maxSubmissionCost, arbitrumNativeInitiatorRequests_[index].maxGas, arbitrumNativeInitiatorRequests_[index].gasPriceBid ); unchecked { ++index; } } } /** * @notice initiate NativeConfirmation on nativeChain(s) for a batch of packets in loop * @param switchboardAddress_ address of nativeSwitchboard * @param nativePacketIds_ the list of requests with packets to initiate nativeConfirmation on switchboard of native chains */ function initiateNativeBatch( address switchboardAddress_, bytes32[] calldata nativePacketIds_ ) external { uint256 nativePacketIdsLength = nativePacketIds_.length; for (uint256 index = 0; index < nativePacketIdsLength; ) { INativeRelay(switchboardAddress_).initiateNativeConfirmation( nativePacketIds_[index] ); unchecked { ++index; } } } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 33 of 65 : SocketConfig.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/ISocket.sol";import "../interfaces/ICapacitorFactory.sol";import "../interfaces/ISwitchboard.sol";import "../utils/AccessControlExtended.sol";import {GOVERNANCE_ROLE} from "../utils/AccessRoles.sol";abstract contract SocketConfig is ISocket, AccessControlExtended { struct PlugConfig { address siblingPlug; ICapacitor capacitor__; IDecapacitor decapacitor__; ISwitchboard inboundSwitchboard__; ISwitchboard outboundSwitchboard__; } ICapacitorFactory public capacitorFactory__; // siblingChainSlug => capacitor address mapping(address => uint32) public capacitorToSlug; // switchboard => siblingChainSlug => ICapacitor mapping(address => mapping(uint256 => ICapacitor)) public capacitors__; // switchboard => siblingChainSlug => IDecapacitor mapping(address => mapping(uint256 => IDecapacitor)) public decapacitors__; // plug => remoteChainSlug => (siblingPlug, capacitor__, decapacitor__, inboundSwitchboard__, outboundSwitchboard__) mapping(address => mapping(uint256 => PlugConfig)) internal _plugConfigs; event SwitchboardAdded( address switchboard, uint256 siblingChainSlug, address capacitor, address decapacitor ); event CapacitorFactorySet(address capacitorFactory); error SwitchboardExists(); error InvalidConnection(); function setCapacitorFactory( address capacitorFactory_ ) external onlyRole(GOVERNANCE_ROLE) { capacitorFactory__ = ICapacitorFactory(capacitorFactory_); emit CapacitorFactorySet(capacitorFactory_); } // it's msg.sender's responsibility to set correct sibling slug function registerSwitchBoard( address switchBoardAddress_, uint256 maxPacketLength_, uint32 siblingChainSlug_, uint32 capacitorType_ ) external { // only capacitor checked, decapacitor assumed will exist if capacitor does if ( address(capacitors__[switchBoardAddress_][siblingChainSlug_]) != address(0) ) revert SwitchboardExists(); ( ICapacitor capacitor__, IDecapacitor decapacitor__ ) = capacitorFactory__.deploy( capacitorType_, siblingChainSlug_, maxPacketLength_ ); capacitorToSlug[address(capacitor__)] = siblingChainSlug_; capacitors__[switchBoardAddress_][siblingChainSlug_] = capacitor__; decapacitors__[switchBoardAddress_][siblingChainSlug_] = decapacitor__; ISwitchboard(switchBoardAddress_).registerCapacitor( siblingChainSlug_, address(capacitor__), maxPacketLength_ ); emit SwitchboardAdded( switchBoardAddress_, siblingChainSlug_, address(capacitor__), address(decapacitor__) ); } function connect( uint256 siblingChainSlug_, address siblingPlug_, address inboundSwitchboard_, address outboundSwitchboard_ ) external override { if ( address(capacitors__[inboundSwitchboard_][siblingChainSlug_]) == address(0) || address(capacitors__[outboundSwitchboard_][siblingChainSlug_]) == address(0) ) revert InvalidConnection(); PlugConfig storage _plugConfig = _plugConfigs[msg.sender][ siblingChainSlug_ ]; _plugConfig.siblingPlug = siblingPlug_; _plugConfig.capacitor__ = capacitors__[outboundSwitchboard_][ siblingChainSlug_ ]; _plugConfig.decapacitor__ = decapacitors__[inboundSwitchboard_][ siblingChainSlug_ ]; _plugConfig.inboundSwitchboard__ = ISwitchboard(inboundSwitchboard_); _plugConfig.outboundSwitchboard__ = ISwitchboard(outboundSwitchboard_); emit PlugConnected( msg.sender, siblingChainSlug_, _plugConfig.siblingPlug, address(_plugConfig.inboundSwitchboard__), address(_plugConfig.outboundSwitchboard__), address(_plugConfig.capacitor__), address(_plugConfig.decapacitor__) ); } function getPlugConfig( address plugAddress_, uint256 siblingChainSlug_ ) external view returns ( address siblingPlug, address inboundSwitchboard__, address outboundSwitchboard__, address capacitor__, address decapacitor__ ) { PlugConfig memory _plugConfig = _plugConfigs[plugAddress_][ siblingChainSlug_ ]; return ( _plugConfig.siblingPlug, address(_plugConfig.inboundSwitchboard__), address(_plugConfig.outboundSwitchboard__), address(_plugConfig.capacitor__), address(_plugConfig.decapacitor__) ); }}

File 34 of 65 : SocketDst.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IDecapacitor.sol";import "../interfaces/IPlug.sol";import "./SocketBase.sol";abstract contract SocketDst is SocketBase { error AlreadyAttested(); error InvalidProof(); error InvalidRetry(); error MessageAlreadyExecuted(); error NotExecutor(); error VerificationFailed(); // msgId => message status mapping(bytes32 => bool) public messageExecuted; // capacitorAddr|chainSlug|packetId mapping(bytes32 => bytes32) public override packetIdRoots; mapping(bytes32 => uint256) public rootProposedAt; /** * @notice emits the packet details when proposed at remote * @param transmitter address of transmitter * @param packetId packet id * @param root packet root */ event PacketProposed( address indexed transmitter, bytes32 indexed packetId, bytes32 root ); /** * @notice emits the root details when root is replaced by owner * @param packetId packet id * @param oldRoot old root * @param newRoot old root */ event PacketRootUpdated(bytes32 packetId, bytes32 oldRoot, bytes32 newRoot); function propose( bytes32 packetId_, bytes32 root_, bytes calldata signature_ ) external override { if (packetIdRoots[packetId_] != bytes32(0)) revert AlreadyAttested(); (address transmitter, bool isTransmitter) = transmitManager__ .checkTransmitter( uint32(_decodeSlug(packetId_)), keccak256(abi.encode(chainSlug, packetId_, root_)), signature_ ); if (!isTransmitter) revert InvalidAttester(); packetIdRoots[packetId_] = root_; rootProposedAt[packetId_] = block.timestamp; emit PacketProposed(transmitter, packetId_, root_); } /** * @notice executes a message, fees will go to recovered executor address * @param packetId_ packet id * @param localPlug_ remote plug address * @param messageDetails_ the details needed for message verification */ function execute( bytes32 packetId_, address localPlug_, ISocket.MessageDetails calldata messageDetails_, bytes memory signature_ ) external override { if (messageExecuted[messageDetails_.msgId]) revert MessageAlreadyExecuted(); messageExecuted[messageDetails_.msgId] = true; uint256 remoteSlug = _decodeSlug(messageDetails_.msgId); PlugConfig storage plugConfig = _plugConfigs[localPlug_][remoteSlug]; bytes32 packedMessage = hasher__.packMessage( remoteSlug, plugConfig.siblingPlug, chainSlug, localPlug_, messageDetails_.msgId, messageDetails_.msgGasLimit, messageDetails_.executionFee, messageDetails_.payload ); (address executor, bool isValidExecutor) = executionManager__ .isExecutor(packedMessage, signature_); if (!isValidExecutor) revert NotExecutor(); _verify( packetId_, remoteSlug, packedMessage, plugConfig, messageDetails_.decapacitorProof ); _execute( executor, messageDetails_.executionFee, localPlug_, remoteSlug, messageDetails_.msgGasLimit, messageDetails_.msgId, messageDetails_.payload ); } function _verify( bytes32 packetId_, uint256 remoteChainSlug_, bytes32 packedMessage_, PlugConfig storage plugConfig_, bytes memory decapacitorProof_ ) internal view { if ( !ISwitchboard(plugConfig_.inboundSwitchboard__).allowPacket( packetIdRoots[packetId_], packetId_, uint32(remoteChainSlug_), rootProposedAt[packetId_] ) ) revert VerificationFailed(); if ( !plugConfig_.decapacitor__.verifyMessageInclusion( packetIdRoots[packetId_], packedMessage_, decapacitorProof_ ) ) revert InvalidProof(); } function _execute( address executor, uint256 executionFee, address localPlug_, uint256 remoteChainSlug_, uint256 msgGasLimit_, bytes32 msgId_, bytes calldata payload_ ) internal { try IPlug(localPlug_).inbound{gas: msgGasLimit_}( remoteChainSlug_, payload_ ) { executionManager__.updateExecutionFees( executor, executionFee, msgId_ ); emit ExecutionSuccess(msgId_); } catch Error(string memory reason) { // catch failing revert() and require() messageExecuted[msgId_] = false; emit ExecutionFailed(msgId_, reason); } catch (bytes memory reason) { // catch failing assert() messageExecuted[msgId_] = false; emit ExecutionFailedBytes(msgId_, reason); } } function isPacketProposed(bytes32 packetId_) external view returns (bool) { return packetIdRoots[packetId_] == bytes32(0) ? false : true; } function _decodeSlug( bytes32 id_ ) internal pure returns (uint256 chainSlug_) { chainSlug_ = uint256(id_) >> 224; }}

File 35 of 65 : SocketSrc.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/ICapacitor.sol";import "./SocketBase.sol";abstract contract SocketSrc is SocketBase { error InsufficientFees(); /** * @notice emits the verification and seal confirmation of a packet * @param transmitter address of transmitter recovered from sig * @param packetId packed id * @param root root * @param signature signature of attester */ event PacketVerifiedAndSealed( address indexed transmitter, bytes32 indexed packetId, bytes32 root, bytes signature ); /** * @notice registers a message * @dev Packs the message and includes it in a packet with capacitor * @param remoteChainSlug_ the remote chain slug * @param msgGasLimit_ 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( uint256 remoteChainSlug_, uint256 msgGasLimit_, bytes calldata payload_ ) external payable override returns (bytes32 msgId) { PlugConfig storage plugConfig = _plugConfigs[msg.sender][ remoteChainSlug_ ]; uint256 localChainSlug = chainSlug; msgId = _encodeMsgId(localChainSlug); ISocket.Fees memory fees = _deductFees( msgGasLimit_, uint32(remoteChainSlug_), plugConfig.outboundSwitchboard__ ); bytes32 packedMessage = hasher__.packMessage( localChainSlug, msg.sender, remoteChainSlug_, plugConfig.siblingPlug, msgId, msgGasLimit_, fees.executionFee, payload_ ); plugConfig.capacitor__.addPackedMessage(packedMessage); emit MessageOutbound( localChainSlug, msg.sender, remoteChainSlug_, plugConfig.siblingPlug, msgId, msgGasLimit_, payload_, fees ); } function _deductFees( uint256 msgGasLimit_, uint32 remoteChainSlug_, ISwitchboard switchboard__ ) internal returns (Fees memory fees) { uint256 minExecutionFees; ( fees.transmissionFees, fees.switchboardFees, minExecutionFees ) = _getMinFees(msgGasLimit_, remoteChainSlug_, switchboard__); if ( msg.value < fees.transmissionFees + fees.switchboardFees + minExecutionFees ) revert InsufficientFees(); unchecked { // any extra fee is considered as executionFee fees.executionFee = msg.value - fees.transmissionFees - fees.switchboardFees; transmitManager__.payFees{value: fees.transmissionFees}( remoteChainSlug_ ); switchboard__.payFees{value: fees.switchboardFees}( remoteChainSlug_ ); executionManager__.payFees{value: fees.executionFee}( msgGasLimit_, remoteChainSlug_ ); } } function getMinFees( uint256 msgGasLimit_, uint32 remoteChainSlug_, address plug_ ) external view override returns (uint256 totalFees) { PlugConfig storage plugConfig = _plugConfigs[plug_][remoteChainSlug_]; ( uint256 transmissionFees, uint256 switchboardFees, uint256 executionFee ) = _getMinFees( msgGasLimit_, remoteChainSlug_, plugConfig.outboundSwitchboard__ ); totalFees = transmissionFees + switchboardFees + executionFee; } function _getMinFees( uint256 msgGasLimit_, uint32 remoteChainSlug_, ISwitchboard switchboard__ ) internal view returns ( uint256 transmissionFees, uint256 switchboardFees, uint256 executionFee ) { transmissionFees = transmitManager__.getMinFees(remoteChainSlug_); uint256 verificationFee; (switchboardFees, verificationFee) = switchboard__.getMinFees( remoteChainSlug_ ); uint256 msgExecutionFee = executionManager__.getMinFees( msgGasLimit_, remoteChainSlug_ ); executionFee = msgExecutionFee + verificationFee; } function seal( uint256 batchSize_, address capacitorAddress_, bytes calldata signature_ ) external payable override { (bytes32 root, uint64 packetCount) = ICapacitor(capacitorAddress_) .sealPacket(batchSize_); bytes32 packetId = _encodePacketId(capacitorAddress_, packetCount); uint32 siblingChainSlug = capacitorToSlug[capacitorAddress_]; (address transmitter, bool isTransmitter) = transmitManager__ .checkTransmitter( siblingChainSlug, keccak256(abi.encode(siblingChainSlug, packetId, root)), signature_ ); if (!isTransmitter) revert InvalidAttester(); emit PacketVerifiedAndSealed(transmitter, packetId, root, signature_); } // Packs the local plug, local chain slug, remote chain slug and nonce // messageCount++ will take care of msg id overflow as well // msgId(256) = localChainSlug(32) | nonce(224) function _encodeMsgId(uint256 slug_) internal returns (bytes32) { return bytes32((uint256(uint32(slug_)) << 224) | messageCount++); } function _encodePacketId( address capacitorAddress_, uint256 packetCount_ ) internal view returns (bytes32) { return bytes32( (uint256(chainSlug) << 224) | (uint256(uint160(capacitorAddress_)) << 64) | packetCount_ ); }}

File 36 of 65 : FastSwitchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./SwitchboardBase.sol";import "../../libraries/SignatureVerifierLib.sol";contract FastSwitchboard is SwitchboardBase { mapping(bytes32 => bool) public isPacketValid; // dst chain slug => total watchers registered mapping(uint256 => uint256) public totalWatchers; // dst chain slug => attest gas limit mapping(uint256 => uint256) public attestGasLimit; // attester => packetId => is attested mapping(address => mapping(bytes32 => bool)) public isAttested; // packetId => total attestations mapping(bytes32 => uint256) public attestations; event SocketSet(address newSocket); event PacketAttested(bytes32 packetId, address attester); event AttestGasLimitSet(uint256 dstChainSlug, uint256 attestGasLimit); error WatcherFound(); error WatcherNotFound(); error AlreadyAttested(); constructor( address owner_, address socket_, address gasPriceOracle_, uint256 chainSlug_, uint256 timeoutInSeconds_ ) AccessControlExtended(owner_) SwitchboardBase(gasPriceOracle_, socket_, chainSlug_, timeoutInSeconds_) {} function attest( bytes32 packetId_, uint256 srcChainSlug_, bytes calldata signature_ ) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( keccak256(abi.encode(srcChainSlug_, packetId_)), signature_ ); if (isAttested[watcher][packetId_]) revert AlreadyAttested(); if (!_hasRole("WATCHER_ROLE", srcChainSlug_, watcher)) revert WatcherNotFound(); isAttested[watcher][packetId_] = true; attestations[packetId_]++; if (attestations[packetId_] >= totalWatchers[srcChainSlug_]) isPacketValid[packetId_] = true; emit PacketAttested(packetId_, watcher); } /** * @notice verifies if the packet satisfies needed checks before execution * @param packetId_ packetId * @param proposeTime_ time at which packet was proposed */ function allowPacket( bytes32, bytes32 packetId_, uint32 srcChainSlug_, uint256 proposeTime_ ) external view override returns (bool) { if (tripGlobalFuse || tripSinglePath[srcChainSlug_]) return false; if (isPacketValid[packetId_]) return true; if (block.timestamp - proposeTime_ > timeoutInSeconds) return true; return false; } function _getMinSwitchboardFees( uint256 dstChainSlug_, uint256 dstRelativeGasPrice_ ) internal view override returns (uint256) { // assumption: number of watchers are going to be same on all chains for particular chain slug? return totalWatchers[dstChainSlug_] * attestGasLimit[dstChainSlug_] * dstRelativeGasPrice_; } /** * @notice updates attest gas limit for given chain slug * @param dstChainSlug_ destination chain * @param attestGasLimit_ average gas limit needed for attest function call */ function setAttestGasLimit( uint256 nonce_, uint256 dstChainSlug_, uint256 attestGasLimit_, bytes calldata signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "ATTEST_GAS_LIMIT_UPDATE", chainSlug, dstChainSlug_, nonce_, attestGasLimit_ ) ), signature_ ); if (!_hasRole("GAS_LIMIT_UPDATER_ROLE", dstChainSlug_, gasLimitUpdater)) revert NoPermit("GAS_LIMIT_UPDATER_ROLE"); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); attestGasLimit[dstChainSlug_] = attestGasLimit_; emit AttestGasLimitSet(dstChainSlug_, attestGasLimit_); } /** * @notice adds a watcher for `srcChainSlug_` chain * @param watcher_ watcher address */ function grantWatcherRole( uint256 srcChainSlug_, address watcher_ ) external onlyRole(GOVERNANCE_ROLE) { if (_hasRole("WATCHER_ROLE", srcChainSlug_, watcher_)) revert WatcherFound(); _grantRole("WATCHER_ROLE", srcChainSlug_, watcher_); totalWatchers[srcChainSlug_]++; } /** * @notice removes a watcher from `srcChainSlug_` chain list * @param watcher_ watcher address */ function revokeWatcherRole( uint256 srcChainSlug_, address watcher_ ) external onlyRole(GOVERNANCE_ROLE) { if (!_hasRole("WATCHER_ROLE", srcChainSlug_, watcher_)) revert WatcherNotFound(); _revokeRole("WATCHER_ROLE", srcChainSlug_, watcher_); totalWatchers[srcChainSlug_]--; }}

File 37 of 65 : OptimisticSwitchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./SwitchboardBase.sol";contract OptimisticSwitchboard is SwitchboardBase { constructor( address owner_, address socket_, address gasPriceOracle_, uint256 chainSlug_, uint256 timeoutInSeconds_ ) AccessControlExtended(owner_) SwitchboardBase(gasPriceOracle_, socket_, chainSlug_, timeoutInSeconds_) {} /** * @notice verifies if the packet satisfies needed checks before execution * @param srcChainSlug_ source chain slug * @param proposeTime_ time at which packet was proposed */ function allowPacket( bytes32, bytes32, uint32 srcChainSlug_, uint256 proposeTime_ ) external view override returns (bool) { if (tripGlobalFuse || tripSinglePath[srcChainSlug_]) return false; if (block.timestamp - proposeTime_ < timeoutInSeconds) return false; return true; } function _getMinSwitchboardFees( uint256, uint256 ) internal pure override returns (uint256) { return 0; }}

File 38 of 65 : SwitchboardBase.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../../interfaces/ISwitchboard.sol";import "../../interfaces/IGasPriceOracle.sol";import "../../utils/AccessControlExtended.sol";import "../../libraries/SignatureVerifierLib.sol";import "../../libraries/RescueFundsLib.sol";import "../../libraries/FeesHelper.sol";import {GOVERNANCE_ROLE, WITHDRAW_ROLE, RESCUE_ROLE, GAS_LIMIT_UPDATER_ROLE} from "../../utils/AccessRoles.sol";abstract contract SwitchboardBase is ISwitchboard, AccessControlExtended { IGasPriceOracle public gasPriceOracle__; bool public tripGlobalFuse; address public socket; uint256 public immutable chainSlug; uint256 public immutable timeoutInSeconds; mapping(uint256 => bool) public isInitialised; mapping(uint256 => uint256) public maxPacketSize; mapping(uint256 => uint256) public executionOverhead; // sourceChain => isPaused mapping(uint256 => bool) public tripSinglePath; // watcher => nextNonce mapping(address => uint256) public nextNonce; event PathTripped(uint256 srcChainSlug, bool tripSinglePath); event SwitchboardTripped(bool tripGlobalFuse); event ExecutionOverheadSet(uint256 dstChainSlug, uint256 executionOverhead); event GasPriceOracleSet(address gasPriceOracle); event CapacitorRegistered( uint256 siblingChainSlug, address capacitor, uint256 maxPacketSize ); error AlreadyInitialised(); error InvalidNonce(); error OnlySocket(); constructor( address gasPriceOracle_, address socket_, uint256 chainSlug_, uint256 timeoutInSeconds_ ) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); socket = socket_; chainSlug = chainSlug_; timeoutInSeconds = timeoutInSeconds_; } function payFees(uint32 dstChainSlug_) external payable override {} function getMinFees( uint32 dstChainSlug_ ) external view override returns (uint256, uint256) { return _calculateMinFees(dstChainSlug_); } function _calculateMinFees( uint32 dstChainSlug_ ) internal view returns (uint256 switchboardFee, uint256 verificationFee) { uint256 dstRelativeGasPrice = gasPriceOracle__.relativeGasPrice( dstChainSlug_ ); switchboardFee = _getMinSwitchboardFees(dstChainSlug_, dstRelativeGasPrice) / maxPacketSize[dstChainSlug_]; verificationFee = executionOverhead[dstChainSlug_] * dstRelativeGasPrice; } function _getMinSwitchboardFees( uint256 dstChainSlug_, uint256 dstRelativeGasPrice_ ) internal view virtual returns (uint256); /** * @notice set capacitor address and packet size * @param capacitor_ capacitor address * @param maxPacketSize_ max messages allowed in one packet */ function registerCapacitor( uint256 siblingChainSlug_, address capacitor_, uint256 maxPacketSize_ ) external override { if (msg.sender != socket) revert OnlySocket(); if (isInitialised[siblingChainSlug_]) revert AlreadyInitialised(); isInitialised[siblingChainSlug_] = true; maxPacketSize[siblingChainSlug_] = maxPacketSize_; emit CapacitorRegistered(siblingChainSlug_, capacitor_, maxPacketSize_); } /** * @notice pause a path */ function tripPath( uint256 nonce_, uint256 srcChainSlug_, bytes memory signature_ ) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256( abi.encode("TRIP_PATH", srcChainSlug_, chainSlug, nonce_, true) ), signature_ ); if (!_hasRole("TRIP_ROLE", srcChainSlug_, watcher)) revert NoPermit("TRIP_ROLE"); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); //source chain based tripping tripSinglePath[srcChainSlug_] = true; emit PathTripped(srcChainSlug_, true); } /** * @notice pause execution */ function tripGlobal(uint256 nonce_, bytes memory signature_) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256(abi.encode("TRIP", chainSlug, nonce_, true)), signature_ ); if (!_hasRole("TRIP_ROLE", watcher)) revert NoPermit("TRIP_ROLE"); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); tripGlobalFuse = true; emit SwitchboardTripped(true); } /** * @notice unpause a path */ function untripPath( uint256 nonce_, uint256 srcChainSlug_, bytes memory signature_ ) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256( abi.encode( "UNTRIP_PATH", chainSlug, srcChainSlug_, nonce_, false ) ), signature_ ); if (!_hasRole("UNTRIP_ROLE", srcChainSlug_, watcher)) revert NoPermit("UNTRIP_ROLE"); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); tripSinglePath[srcChainSlug_] = false; emit PathTripped(srcChainSlug_, false); } /** * @notice unpause execution */ function untrip(uint256 nonce_, bytes memory signature_) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256(abi.encode("UNTRIP", chainSlug, nonce_, false)), signature_ ); if (!_hasRole("UNTRIP_ROLE", watcher)) revert NoPermit("UNTRIP_ROLE"); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); tripGlobalFuse = false; emit SwitchboardTripped(false); } /** * @notice updates execution overhead * @param executionOverhead_ new execution overhead cost */ function setExecutionOverhead( uint256 nonce_, uint256 dstChainSlug_, uint256 executionOverhead_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "EXECUTION_OVERHEAD_UPDATE", nonce_, chainSlug, dstChainSlug_, executionOverhead_ ) ), signature_ ); if (!_hasRole("GAS_LIMIT_UPDATER_ROLE", dstChainSlug_, gasLimitUpdater)) revert NoPermit("GAS_LIMIT_UPDATER_ROLE"); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); executionOverhead[dstChainSlug_] = executionOverhead_; emit ExecutionOverheadSet(dstChainSlug_, executionOverhead_); } /** * @notice updates gasPriceOracle_ address * @param gasPriceOracle_ new gasPriceOracle_ */ function setGasPriceOracle( address gasPriceOracle_ ) external onlyRole(GOVERNANCE_ROLE) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); emit GasPriceOracleSet(gasPriceOracle_); } function withdrawFees(address account_) external onlyRole(WITHDRAW_ROLE) { FeesHelper.withdrawFees(account_); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 39 of 65 : ArbitrumL1Switchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "lib/openzeppelin-contracts/contracts/vendor/arbitrum/IBridge.sol";import "lib/openzeppelin-contracts/contracts/vendor/arbitrum/IInbox.sol";import "lib/openzeppelin-contracts/contracts/vendor/arbitrum/IOutbox.sol";import "./NativeSwitchboardBase.sol";contract ArbitrumL1Switchboard is NativeSwitchboardBase { address public remoteRefundAddress; address public callValueRefundAddress; uint256 public arbitrumNativeFee; IInbox public inbox__; IBridge public bridge__; IOutbox public outbox__; event UpdatedInboxAddress(address inbox); event UpdatedRefundAddresses( address remoteRefundAddress, address callValueRefundAddress ); event UpdatedArbitrumNativeFee(uint256 arbitrumNativeFee); event UpdatedBridge(address bridgeAddress); event UpdatedOutbox(address outboxAddress); modifier onlyRemoteSwitchboard() override { if (msg.sender != address(bridge__)) revert InvalidSender(); address l2Sender = outbox__.l2ToL1Sender(); if (l2Sender != remoteNativeSwitchboard) revert InvalidSender(); _; } constructor( uint256 chainSlug_, uint256 arbitrumNativeFee_, uint256 initiateGasLimit_, uint256 executionOverhead_, address inbox_, address owner_, address socket_, IGasPriceOracle gasPriceOracle_, address bridge_, address outbox_ ) AccessControlExtended(owner_) NativeSwitchboardBase( socket_, chainSlug_, initiateGasLimit_, executionOverhead_, gasPriceOracle_ ) { inbox__ = IInbox(inbox_); arbitrumNativeFee = arbitrumNativeFee_; bridge__ = IBridge(bridge_); outbox__ = IOutbox(outbox_); remoteRefundAddress = msg.sender; callValueRefundAddress = msg.sender; } function initiateNativeConfirmation( bytes32 packetId_, uint256 maxSubmissionCost_, uint256 maxGas_, uint256 gasPriceBid_ ) external payable { bytes memory data = _encodeRemoteCall(packetId_); // to avoid stack too deep address callValueRefund = callValueRefundAddress; address remoteRefund = remoteRefundAddress; inbox__.createRetryableTicket{value: msg.value}( remoteNativeSwitchboard, 0, // no value needed for receivePacket maxSubmissionCost_, remoteRefund, callValueRefund, maxGas_, gasPriceBid_, data ); emit InitiatedNativeConfirmation(packetId_); } function _encodeRemoteCall( bytes32 packetId_ ) internal view returns (bytes memory data) { data = abi.encodeWithSelector( this.receivePacket.selector, packetId_, _getRoot(packetId_) ); } function _getMinSwitchboardFees( uint256, uint256, uint256 sourceGasPrice_ ) internal view override returns (uint256) { // TODO: check if dynamic fees can be divided into more constants // arbitrum: check src contract return initiateGasLimit * sourceGasPrice_ + arbitrumNativeFee; } function updateRefundAddresses( address remoteRefundAddress_, address callValueRefundAddress_ ) external onlyRole(GOVERNANCE_ROLE) { remoteRefundAddress = remoteRefundAddress_; callValueRefundAddress = callValueRefundAddress_; emit UpdatedRefundAddresses( remoteRefundAddress_, callValueRefundAddress_ ); } function updateArbitrumNativeFee( uint256 nonce_, uint256 arbitrumNativeFee_, bytes calldata signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "ARBITRUM_NATIVE_FEE_UPDATE", chainSlug, nonce_, arbitrumNativeFee_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); arbitrumNativeFee = arbitrumNativeFee_; emit UpdatedArbitrumNativeFee(arbitrumNativeFee_); } function updateInboxAddresses( address inbox_ ) external onlyRole(GOVERNANCE_ROLE) { inbox__ = IInbox(inbox_); emit UpdatedInboxAddress(inbox_); } function updateBridge( address bridgeAddress_ ) external onlyRole(GOVERNANCE_ROLE) { bridge__ = IBridge(bridgeAddress_); emit UpdatedBridge(bridgeAddress_); } function updateOutbox( address outboxAddress_ ) external onlyRole(GOVERNANCE_ROLE) { outbox__ = IOutbox(outboxAddress_); emit UpdatedOutbox(outboxAddress_); }}

File 40 of 65 : ArbitrumL2Switchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "lib/openzeppelin-contracts/contracts/vendor/arbitrum/IArbSys.sol";import "../../libraries/AddressAliasHelper.sol";import "./NativeSwitchboardBase.sol";contract ArbitrumL2Switchboard is NativeSwitchboardBase { uint256 public confirmGasLimit; IArbSys public immutable arbsys__ = IArbSys(address(100)); event UpdatedConfirmGasLimit(uint256 confirmGasLimit); modifier onlyRemoteSwitchboard() override { if ( msg.sender != AddressAliasHelper.applyL1ToL2Alias(remoteNativeSwitchboard) ) revert InvalidSender(); _; } constructor( uint256 chainSlug_, uint256 confirmGasLimit_, uint256 initiateGasLimit_, uint256 executionOverhead_, address owner_, address socket_, IGasPriceOracle gasPriceOracle_ ) AccessControlExtended(owner_) NativeSwitchboardBase( socket_, chainSlug_, initiateGasLimit_, executionOverhead_, gasPriceOracle_ ) { confirmGasLimit = confirmGasLimit_; } function initiateNativeConfirmation(bytes32 packetId_) external { bytes memory data = _encodeRemoteCall(packetId_); arbsys__.sendTxToL1(remoteNativeSwitchboard, data); emit InitiatedNativeConfirmation(packetId_); } function _encodeRemoteCall( bytes32 packetId_ ) internal view returns (bytes memory data) { data = abi.encodeWithSelector( this.receivePacket.selector, packetId_, _getRoot(packetId_) ); } function _getMinSwitchboardFees( uint256, uint256 dstRelativeGasPrice_, uint256 sourceGasPrice_ ) internal view override returns (uint256) { return initiateGasLimit * sourceGasPrice_ + confirmGasLimit * dstRelativeGasPrice_; } function updateConfirmGasLimit( uint256 nonce_, uint256 confirmGasLimit_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "L1_RECEIVE_GAS_LIMIT_UPDATE", chainSlug, nonce_, confirmGasLimit_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); confirmGasLimit = confirmGasLimit_; emit UpdatedConfirmGasLimit(confirmGasLimit_); }}

File 41 of 65 : NativeSwitchboardBase.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../../interfaces/ISwitchboard.sol";import "../../interfaces/IGasPriceOracle.sol";import "../../interfaces/ICapacitor.sol";import "../../utils/AccessControlExtended.sol";import "../../libraries/SignatureVerifierLib.sol";import "../../libraries/RescueFundsLib.sol";import "../../libraries/FeesHelper.sol";import {GAS_LIMIT_UPDATER_ROLE, GOVERNANCE_ROLE, RESCUE_ROLE, WITHDRAW_ROLE, TRIP_ROLE, UNTRIP_ROLE} from "../../utils/AccessRoles.sol";abstract contract NativeSwitchboardBase is ISwitchboard, AccessControlExtended { IGasPriceOracle public gasPriceOracle__; bool public tripGlobalFuse; ICapacitor public capacitor__; bool public isInitialised; uint256 public maxPacketSize; uint256 public executionOverhead; uint256 public initiateGasLimit; address public remoteNativeSwitchboard; address public socket; uint256 public immutable chainSlug; // stores the roots received from native bridge mapping(bytes32 => bytes32) public packetIdToRoot; // transmitter => nextNonce mapping(address => uint256) public nextNonce; event SwitchboardTripped(bool tripGlobalFuse); event ExecutionOverheadSet(uint256 executionOverhead); event InitiateGasLimitSet(uint256 gasLimit); event CapacitorSet(address capacitor); event GasPriceOracleSet(address gasPriceOracle); event InitiatedNativeConfirmation(bytes32 packetId); event CapacitorRegistered(address capacitor, uint256 maxPacketSize); event UpdatedRemoteNativeSwitchboard(address remoteNativeSwitchboard); event RootReceived(bytes32 packetId, bytes32 root); error FeesNotEnough(); error AlreadyInitialised(); error InvalidSender(); error NoRootFound(); error InvalidNonce(); error OnlySocket(); modifier onlyRemoteSwitchboard() virtual { _; } constructor( address socket_, uint256 chainSlug_, uint256 initiateGasLimit_, uint256 executionOverhead_, IGasPriceOracle gasPriceOracle_ ) { socket = socket_; chainSlug = chainSlug_; initiateGasLimit = initiateGasLimit_; executionOverhead = executionOverhead_; gasPriceOracle__ = gasPriceOracle_; } function _getRoot(bytes32 packetId_) internal view returns (bytes32 root) { uint64 capacitorPacketCount = uint64(uint256(packetId_)); root = capacitor__.getRootByCount(capacitorPacketCount); if (root == bytes32(0)) revert NoRootFound(); } function receivePacket( bytes32 packetId_, bytes32 root_ ) external onlyRemoteSwitchboard { packetIdToRoot[packetId_] = root_; emit RootReceived(packetId_, root_); } /** * @notice verifies if the packet satisfies needed checks before execution * @param packetId_ packet id */ function allowPacket( bytes32 root_, bytes32 packetId_, uint32, uint256 ) external view override returns (bool) { if (tripGlobalFuse) return false; if (packetIdToRoot[packetId_] != root_) return false; return true; } // assumption: natives have 18 decimals function payFees(uint32 dstChainSlug_) external payable override {} function getMinFees( uint32 dstChainSlug_ ) external view override returns (uint256 switchboardFee_, uint256 verificationFee_) { return _calculateMinFees(dstChainSlug_); } function _calculateMinFees( uint32 dstChainSlug_ ) internal view returns (uint256 switchboardFee_, uint256 verificationFee_) { (uint256 sourceGasPrice, uint256 dstRelativeGasPrice) = gasPriceOracle__ .getGasPrices(dstChainSlug_); switchboardFee_ = _getMinSwitchboardFees( dstChainSlug_, dstRelativeGasPrice, sourceGasPrice ) / maxPacketSize; verificationFee_ = executionOverhead * dstRelativeGasPrice; } function _getMinSwitchboardFees( uint256 dstChainSlug_, uint256 dstRelativeGasPrice_, uint256 sourceGasPrice_ ) internal view virtual returns (uint256); /** * @notice set capacitor address and packet size * @param capacitor_ capacitor address * @param maxPacketSize_ max messages allowed in one packet */ function registerCapacitor( uint256, address capacitor_, uint256 maxPacketSize_ ) external override { if (msg.sender != socket) revert OnlySocket(); if (isInitialised) revert AlreadyInitialised(); isInitialised = true; maxPacketSize = maxPacketSize_; capacitor__ = ICapacitor(capacitor_); emit CapacitorRegistered(capacitor_, maxPacketSize_); } /** * @notice pause execution */ function tripGlobal(uint256 nonce_, bytes memory signature_) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256(abi.encode("TRIP", chainSlug, nonce_, true)), signature_ ); if (!_hasRole(TRIP_ROLE, watcher)) revert NoPermit(TRIP_ROLE); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); tripGlobalFuse = true; emit SwitchboardTripped(true); } /** * @notice unpause execution */ function untrip(uint256 nonce_, bytes memory signature_) external { address watcher = SignatureVerifierLib.recoverSignerFromDigest( // it includes trip status at the end keccak256(abi.encode("UNTRIP", chainSlug, nonce_, false)), signature_ ); if (!_hasRole(UNTRIP_ROLE, watcher)) revert NoPermit(UNTRIP_ROLE); uint256 nonce = nextNonce[watcher]++; if (nonce_ != nonce) revert InvalidNonce(); tripGlobalFuse = false; emit SwitchboardTripped(false); } /** * @notice updates execution overhead * @param executionOverhead_ new execution overhead cost */ function setExecutionOverhead( uint256 nonce_, uint256 executionOverhead_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "EXECUTION_OVERHEAD_UPDATE", nonce_, chainSlug, executionOverhead_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); executionOverhead = executionOverhead_; emit ExecutionOverheadSet(executionOverhead_); } /** * @notice updates initiateGasLimit * @param gasLimit_ new gas limit for initiateGasLimit */ function setInitiateGasLimit( uint256 nonce_, uint256 gasLimit_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "INITIAL_CONFIRMATION_GAS_LIMIT_UPDATE", chainSlug, nonce_, gasLimit_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); initiateGasLimit = gasLimit_; emit InitiateGasLimitSet(gasLimit_); } /** * @notice updates gasPriceOracle_ address * @param gasPriceOracle_ new gasPriceOracle_ */ function setGasPriceOracle( address gasPriceOracle_ ) external onlyRole(GOVERNANCE_ROLE) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); emit GasPriceOracleSet(gasPriceOracle_); } function updateRemoteNativeSwitchboard( address remoteNativeSwitchboard_ ) external onlyRole(GOVERNANCE_ROLE) { remoteNativeSwitchboard = remoteNativeSwitchboard_; emit UpdatedRemoteNativeSwitchboard(remoteNativeSwitchboard_); } function withdrawFees(address account_) external onlyRole(WITHDRAW_ROLE) { FeesHelper.withdrawFees(account_); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 42 of 65 : OptimismSwitchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "lib/openzeppelin-contracts/contracts/vendor/optimism/ICrossDomainMessenger.sol";import "./NativeSwitchboardBase.sol";contract OptimismSwitchboard is NativeSwitchboardBase { uint256 public receiveGasLimit; uint256 public confirmGasLimit; ICrossDomainMessenger public immutable crossDomainMessenger__; event UpdatedReceiveGasLimit(uint256 receiveGasLimit); event UpdatedConfirmGasLimit(uint256 confirmGasLimit); modifier onlyRemoteSwitchboard() override { if ( msg.sender != address(crossDomainMessenger__) && crossDomainMessenger__.xDomainMessageSender() != remoteNativeSwitchboard ) revert InvalidSender(); _; } constructor( uint256 chainSlug_, uint256 receiveGasLimit_, uint256 confirmGasLimit_, uint256 initiateGasLimit_, uint256 executionOverhead_, address owner_, address socket_, IGasPriceOracle gasPriceOracle_, address crossDomainMessenger_ ) AccessControlExtended(owner_) NativeSwitchboardBase( socket_, chainSlug_, initiateGasLimit_, executionOverhead_, gasPriceOracle_ ) { receiveGasLimit = receiveGasLimit_; confirmGasLimit = confirmGasLimit_; crossDomainMessenger__ = ICrossDomainMessenger(crossDomainMessenger_); } function initiateNativeConfirmation(bytes32 packetId_) external { bytes memory data = _encodeRemoteCall(packetId_); crossDomainMessenger__.sendMessage( remoteNativeSwitchboard, data, uint32(receiveGasLimit) ); emit InitiatedNativeConfirmation(packetId_); } function _encodeRemoteCall( bytes32 packetId_ ) internal view returns (bytes memory data) { data = abi.encodeWithSelector( this.receivePacket.selector, packetId_, _getRoot(packetId_) ); } function _getMinSwitchboardFees( uint256, uint256 dstRelativeGasPrice_, uint256 sourceGasPrice_ ) internal view override returns (uint256) { // confirmGasLimit will be 0 when switchboard is deployed on L1 return initiateGasLimit * sourceGasPrice_ + confirmGasLimit * dstRelativeGasPrice_; } function updateConfirmGasLimit( uint256 nonce_, uint256 confirmGasLimit_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "L1_RECEIVE_GAS_LIMIT_UPDATE", chainSlug, nonce_, confirmGasLimit_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); confirmGasLimit = confirmGasLimit_; emit UpdatedConfirmGasLimit(confirmGasLimit_); } function updateReceiveGasLimit( uint256 receiveGasLimit_ ) external onlyRole(GOVERNANCE_ROLE) { receiveGasLimit = receiveGasLimit_; emit UpdatedReceiveGasLimit(receiveGasLimit_); }}

File 43 of 65 : PolygonL1Switchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "lib/contracts/contracts/tunnel/FxBaseRootTunnel.sol";import "./NativeSwitchboardBase.sol";contract PolygonL1Switchboard is NativeSwitchboardBase, FxBaseRootTunnel { event FxChildTunnelSet(address fxChildTunnel, address newFxChildTunnel); modifier onlyRemoteSwitchboard() override { require(true, "ONLY_FX_CHILD"); _; } constructor( uint256 chainSlug_, uint256 initiateGasLimit_, uint256 executionOverhead_, address checkpointManager_, address fxRoot_, address owner_, address socket_, IGasPriceOracle gasPriceOracle_ ) AccessControlExtended(owner_) NativeSwitchboardBase( socket_, chainSlug_, initiateGasLimit_, executionOverhead_, gasPriceOracle_ ) FxBaseRootTunnel(checkpointManager_, fxRoot_) {} /** * @param packetId_ - packet id */ function initiateNativeConfirmation(bytes32 packetId_) external payable { bytes memory data = _encodeRemoteCall(packetId_); _sendMessageToChild(data); emit InitiatedNativeConfirmation(packetId_); } function _encodeRemoteCall( bytes32 packetId_ ) internal view returns (bytes memory data) { data = abi.encode(packetId_, _getRoot(packetId_)); } function _processMessageFromChild(bytes memory message_) internal override { (bytes32 packetId, bytes32 root) = abi.decode( message_, (bytes32, bytes32) ); packetIdToRoot[packetId] = root; emit RootReceived(packetId, root); } function _getMinSwitchboardFees( uint256, uint256, uint256 sourceGasPrice_ ) internal view override returns (uint256) { return initiateGasLimit * sourceGasPrice_; } // set fxChildTunnel if not set already function setFxChildTunnel( address fxChildTunnel_ ) public override onlyRole(GOVERNANCE_ROLE) { emit FxChildTunnelSet(fxChildTunnel, fxChildTunnel_); fxChildTunnel = fxChildTunnel_; }}

File 44 of 65 : PolygonL2Switchboard.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "lib/contracts/contracts/tunnel/FxBaseChildTunnel.sol";import "./NativeSwitchboardBase.sol";contract PolygonL2Switchboard is NativeSwitchboardBase, FxBaseChildTunnel { uint256 public confirmGasLimit; event FxChildUpdate(address oldFxChild, address newFxChild); event FxRootTunnelSet(address fxRootTunnel, address newFxRootTunnel); event UpdatedConfirmGasLimit(uint256 confirmGasLimit); modifier onlyRemoteSwitchboard() override { require(true, "ONLY_FX_CHILD"); _; } constructor( uint256 chainSlug_, uint256 confirmGasLimit_, uint256 initiateGasLimit_, uint256 executionOverhead_, address fxChild_, address owner_, address socket_, IGasPriceOracle gasPriceOracle_ ) AccessControlExtended(owner_) NativeSwitchboardBase( socket_, chainSlug_, initiateGasLimit_, executionOverhead_, gasPriceOracle_ ) FxBaseChildTunnel(fxChild_) { confirmGasLimit = confirmGasLimit_; } /** * @param packetId_ - packet id */ function initiateNativeConfirmation(bytes32 packetId_) external payable { bytes memory data = _encodeRemoteCall(packetId_); _sendMessageToRoot(data); emit InitiatedNativeConfirmation(packetId_); } function _encodeRemoteCall( bytes32 packetId_ ) internal view returns (bytes memory data) { data = abi.encode(packetId_, _getRoot(packetId_)); } /** * validate sender verifies if `rootMessageSender` is the root contract (notary) on L1. */ function _processMessageFromRoot( uint256, address rootMessageSender_, bytes memory data_ ) internal override validateSender(rootMessageSender_) { (bytes32 packetId, bytes32 root) = abi.decode( data_, (bytes32, bytes32) ); packetIdToRoot[packetId] = root; emit RootReceived(packetId, root); } function _getMinSwitchboardFees( uint256, uint256 dstRelativeGasPrice_, uint256 sourceGasPrice_ ) internal view override returns (uint256) { return initiateGasLimit * sourceGasPrice_ + confirmGasLimit * dstRelativeGasPrice_; } function updateConfirmGasLimit( uint256 nonce_, uint256 confirmGasLimit_, bytes memory signature_ ) external { address gasLimitUpdater = SignatureVerifierLib.recoverSignerFromDigest( keccak256( abi.encode( "L1_RECEIVE_GAS_LIMIT_UPDATE", chainSlug, nonce_, confirmGasLimit_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); confirmGasLimit = confirmGasLimit_; emit UpdatedConfirmGasLimit(confirmGasLimit_); } /** * @notice Update the address of the FxChild * @param fxChild_ The address of the new FxChild **/ function updateFxChild( address fxChild_ ) external onlyRole(GOVERNANCE_ROLE) { emit FxChildUpdate(fxChild, fxChild_); fxChild = fxChild_; } function setFxRootTunnel( address fxRootTunnel_ ) external override onlyRole(GOVERNANCE_ROLE) { emit FxRootTunnelSet(fxRootTunnel, fxRootTunnel_); fxRootTunnel = fxRootTunnel_; }}

File 45 of 65 : TransmitManager.sol

// SPDX-License-Identifier: UNLICENSEDpragma solidity 0.8.7;import "./interfaces/ITransmitManager.sol";import "./interfaces/ISignatureVerifier.sol";import "./interfaces/IGasPriceOracle.sol";import "./utils/AccessControlExtended.sol";import "./libraries/RescueFundsLib.sol";import "./libraries/FeesHelper.sol";import {GOVERNANCE_ROLE, WITHDRAW_ROLE, RESCUE_ROLE, GAS_LIMIT_UPDATER_ROLE} from "./utils/AccessRoles.sol";contract TransmitManager is ITransmitManager, AccessControlExtended { ISignatureVerifier public signatureVerifier__; IGasPriceOracle public gasPriceOracle__; uint32 public immutable chainSlug; uint256 public sealGasLimit; mapping(uint256 => uint256) public proposeGasLimit; // transmitter => nextNonce mapping(address => uint256) public nextNonce; error InsufficientTransmitFees(); error InvalidNonce(); event GasPriceOracleSet(address gasPriceOracle); event SealGasLimitSet(uint256 gasLimit); event ProposeGasLimitSet(uint256 dstChainSlug, uint256 gasLimit); /** * @notice emits when a new signature verifier contract is set * @param signatureVerifier address of new verifier contract */ event SignatureVerifierSet(address signatureVerifier); constructor( ISignatureVerifier signatureVerifier_, IGasPriceOracle gasPriceOracle_, address owner_, uint32 chainSlug_, uint256 sealGasLimit_ ) AccessControlExtended(owner_) { chainSlug = chainSlug_; sealGasLimit = sealGasLimit_; signatureVerifier__ = signatureVerifier_; gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); } // @param slugs_ packs the siblingChainSlug & sigChainSlug // @dev signature sent to this function can be reused on other chains // @dev hence caller should add some identifier to stop this. // slugs_(256) = siblingChainSlug(128) | sigChainSlug(128) // @dev sibling chain slug is required to check the transmitter role // @dev sig chain slug is required by signature. On src, this is sibling slug while on // destination, it is current chain slug function checkTransmitter( uint32 siblingSlug, bytes32 digest_, bytes calldata signature_ ) external view override returns (address, bool) { address transmitter = signatureVerifier__.recoverSignerFromDigest( digest_, signature_ ); return ( transmitter, _hasRole("TRANSMITTER_ROLE", siblingSlug, transmitter) ); } function payFees(uint32 siblingChainSlug_) external payable override {} function getMinFees( uint32 siblingChainSlug_ ) external view override returns (uint256) { return _calculateMinFees(siblingChainSlug_); } function _calculateMinFees( uint32 siblingChainSlug_ ) internal view returns (uint256 minTransmissionFees) { ( uint256 sourceGasPrice, uint256 siblingRelativeGasPrice ) = gasPriceOracle__.getGasPrices(siblingChainSlug_); minTransmissionFees = sealGasLimit * sourceGasPrice + proposeGasLimit[siblingChainSlug_] * siblingRelativeGasPrice; } function withdrawFees(address account_) external onlyRole(WITHDRAW_ROLE) { FeesHelper.withdrawFees(account_); } /** * @notice updates seal gas limit * @param gasLimit_ new seal gas limit */ function setSealGasLimit( uint256 nonce_, uint256 gasLimit_, bytes calldata signature_ ) external { address gasLimitUpdater = signatureVerifier__.recoverSignerFromDigest( keccak256( abi.encode( "SEAL_GAS_LIMIT_UPDATE", chainSlug, nonce_, gasLimit_ ) ), signature_ ); if (!_hasRole(GAS_LIMIT_UPDATER_ROLE, gasLimitUpdater)) revert NoPermit(GAS_LIMIT_UPDATER_ROLE); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); sealGasLimit = gasLimit_; emit SealGasLimitSet(gasLimit_); } /** * @notice updates propose gas limit for `dstChainSlug_` * @param gasLimit_ new propose gas limit */ function setProposeGasLimit( uint256 nonce_, uint256 dstChainSlug_, uint256 gasLimit_, bytes calldata signature_ ) external { address gasLimitUpdater = signatureVerifier__.recoverSignerFromDigest( keccak256( abi.encode( "PROPOSE_GAS_LIMIT_UPDATE", chainSlug, dstChainSlug_, nonce_, gasLimit_ ) ), signature_ ); if (!_hasRole("GAS_LIMIT_UPDATER_ROLE", dstChainSlug_, gasLimitUpdater)) revert NoPermit("GAS_LIMIT_UPDATER_ROLE"); uint256 nonce = nextNonce[gasLimitUpdater]++; if (nonce_ != nonce) revert InvalidNonce(); proposeGasLimit[dstChainSlug_] = gasLimit_; emit ProposeGasLimitSet(dstChainSlug_, gasLimit_); } /** * @notice updates gasPriceOracle__ * @param gasPriceOracle_ address of Gas Price Oracle */ function setGasPriceOracle( address gasPriceOracle_ ) external onlyRole(GOVERNANCE_ROLE) { gasPriceOracle__ = IGasPriceOracle(gasPriceOracle_); emit GasPriceOracleSet(gasPriceOracle_); } /** * @notice updates signatureVerifier_ * @param signatureVerifier_ address of Signature Verifier */ function setSignatureVerifier( address signatureVerifier_ ) external onlyRole(GOVERNANCE_ROLE) { signatureVerifier__ = ISignatureVerifier(signatureVerifier_); emit SignatureVerifierSet(signatureVerifier_); } function rescueFunds( address token_, address userAddress_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, userAddress_, amount_); }}

File 46 of 65 : AccessControl.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./Ownable.sol";abstract contract AccessControl is Ownable { // role => address => permit mapping(bytes32 => mapping(address => bool)) private _permits; event RoleGranted(bytes32 indexed role, address indexed grantee); event RoleRevoked(bytes32 indexed role, address indexed revokee); error NoPermit(bytes32 role); constructor(address owner_) Ownable(owner_) {} modifier onlyRole(bytes32 role) { if (!_permits[role][msg.sender]) revert NoPermit(role); _; } function grantRole( bytes32 role_, address grantee_ ) external virtual onlyOwner { _grantRole(role_, grantee_); } function revokeRole( bytes32 role_, address revokee_ ) external virtual onlyOwner { _revokeRole(role_, revokee_); } function _grantRole(bytes32 role_, address grantee_) internal { _permits[role_][grantee_] = true; emit RoleGranted(role_, grantee_); } function _revokeRole(bytes32 role_, address revokee_) internal { _permits[role_][revokee_] = false; emit RoleRevoked(role_, revokee_); } function hasRole( bytes32 role_, address address_ ) external view returns (bool) { return _hasRole(role_, address_); } function _hasRole( bytes32 role_, address address_ ) internal view returns (bool) { return _permits[role_][address_]; }}

File 47 of 65 : AccessControlExtended.sol

(Video) Blockchain Forensics R&D with Python - Track Attacker Transactions with Etherscan API Line By Line

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "./AccessControl.sol";contract AccessControlExtended is AccessControl { modifier onlyRoleWithChainSlug( string memory roleName_, uint256 chainSlug_ ) { bytes32 role = keccak256(abi.encode(roleName_, chainSlug_)); if (!_hasRole(role, msg.sender)) revert NoPermit(role); _; } constructor(address owner_) AccessControl(owner_) {} function grantRole( string memory roleName_, uint256 chainSlug_, address grantee_ ) external virtual onlyOwner { _grantRole(roleName_, chainSlug_, grantee_); } function grantBatchRole( bytes32[] calldata roleNames_, address[] calldata grantees_ ) external virtual onlyOwner { require(roleNames_.length == grantees_.length); for (uint256 index = 0; index < roleNames_.length; index++) _grantRole(roleNames_[index], grantees_[index]); } function revokeBatchRole( bytes32[] calldata roleNames_, address[] calldata grantees_ ) external virtual onlyOwner { require(roleNames_.length == grantees_.length); for (uint256 index = 0; index < roleNames_.length; index++) _revokeRole(roleNames_[index], grantees_[index]); } function _grantRole( string memory roleName_, uint256 chainSlug_, address grantee_ ) internal { _grantRole(keccak256(abi.encode(roleName_, chainSlug_)), grantee_); } function hasRole( string memory roleName_, uint256 chainSlug_, address address_ ) external view returns (bool) { return _hasRole(roleName_, chainSlug_, address_); } function _hasRole( string memory roleName_, uint256 chainSlug_, address address_ ) internal view returns (bool) { return _hasRole(keccak256(abi.encode(roleName_, chainSlug_)), address_); } function revokeRole( string memory roleName_, uint256 chainSlug_, address grantee_ ) external virtual onlyOwner { _revokeRole(roleName_, chainSlug_, grantee_); } function _revokeRole( string memory roleName_, uint256 chainSlug_, address revokee_ ) internal { _revokeRole(keccak256(abi.encode(roleName_, chainSlug_)), revokee_); }}

File 48 of 65 : AccessRoles.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;bytes32 constant RESCUE_ROLE = keccak256("RESCUE_ROLE");bytes32 constant WITHDRAW_ROLE = keccak256("WITHDRAW_ROLE");bytes32 constant TRIP_ROLE = keccak256("TRIP_ROLE");bytes32 constant UNTRIP_ROLE = keccak256("UNTRIP_ROLE");bytes32 constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");bytes32 constant GAS_LIMIT_UPDATER_ROLE = keccak256("GAS_LIMIT_UPDATER_ROLE");bytes32 constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");

File 49 of 65 : Hasher.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/IHasher.sol";contract Hasher is IHasher { /// @inheritdoc IHasher function packMessage( uint256 srcChainSlug_, address srcPlug_, uint256 dstChainSlug_, address dstPlug_, bytes32 msgId_, uint256 msgGasLimit_, uint256 executionFee_, bytes calldata payload_ ) external pure override returns (bytes32) { return keccak256( abi.encode( srcChainSlug_, srcPlug_, dstChainSlug_, dstPlug_, msgId_, msgGasLimit_, executionFee_, payload_ ) ); }}

File 50 of 65 : Ownable.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;abstract contract Ownable { address private _owner; address private _nominee; event OwnerNominated(address indexed nominee); event OwnerClaimed(address indexed claimer); error OnlyOwner(); error OnlyNominee(); constructor(address owner_) { _claimOwner(owner_); } modifier onlyOwner() { if (msg.sender != _owner) revert OnlyOwner(); _; } function owner() external view returns (address) { return _owner; } function nominee() external view returns (address) { return _nominee; } function nominateOwner(address nominee_) external { if (msg.sender != _owner) revert OnlyOwner(); _nominee = nominee_; emit OwnerNominated(_nominee); } function claimOwner() external { if (msg.sender != _nominee) revert OnlyNominee(); _claimOwner(msg.sender); } function _claimOwner(address claimer_) internal { _owner = claimer_; _nominee = address(0); }}

File 51 of 65 : ReentrancyGuard.sol

// SPDX-License-Identifier: AGPL-3.0-onlypragma solidity 0.8.7;/// @notice Gas optimized reentrancy protection for smart contracts./// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)abstract contract ReentrancyGuard { uint256 private _locked = 1; modifier nonReentrant() virtual { require(_locked == 1, "REENTRANCY"); _locked = 2; _; _locked = 1; }}

File 52 of 65 : SignatureVerifier.sol

// SPDX-License-Identifier: GPL-3.0-onlypragma solidity 0.8.7;import "../interfaces/ISignatureVerifier.sol";import "../libraries/SignatureVerifierLib.sol";contract SignatureVerifier is ISignatureVerifier { /// @inheritdoc ISignatureVerifier function recoverSigner( uint256 destChainSlug_, uint256 packetId_, bytes32 root_, bytes calldata signature_ ) external pure override returns (address signer) { return SignatureVerifierLib.recoverSigner( destChainSlug_, packetId_, root_, signature_ ); } /** * @notice returns the address of signer recovered from input signature and digest */ function recoverSignerFromDigest( bytes32 digest_, bytes memory signature_ ) public pure override returns (address signer) { return SignatureVerifierLib.recoverSignerFromDigest(digest_, signature_); }}

File 53 of 65 : ExitPayloadReader.sol

pragma solidity ^0.8.0;import {RLPReader} from "./RLPReader.sol";library ExitPayloadReader { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; uint8 constant WORD_SIZE = 32; struct ExitPayload { RLPReader.RLPItem[] data; } struct Receipt { RLPReader.RLPItem[] data; bytes raw; uint256 logIndex; } struct Log { RLPReader.RLPItem data; RLPReader.RLPItem[] list; } struct LogTopics { RLPReader.RLPItem[] data; } // copy paste of private copy() from RLPReader to avoid changing of existing contracts function copy( uint256 src, uint256 dest, uint256 len ) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len == 0) return; // left over bytes. Mask is used to remove unwanted bytes from the word uint256 mask = 256**(WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) { RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList(); return ExitPayload(payloadData); } function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[0].toUint(); } function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[1].toBytes(); } function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[2].toUint(); } function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[3].toUint(); } function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[4].toUint()); } function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[5].toUint()); } function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) { receipt.raw = payload.data[6].toBytes(); RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem(); if (receiptItem.isList()) { // legacy tx receipt.data = receiptItem.toList(); } else { // pop first byte before parsing receipt bytes memory typedBytes = receipt.raw; bytes memory result = new bytes(typedBytes.length - 1); uint256 srcPtr; uint256 destPtr; assembly { srcPtr := add(33, typedBytes) destPtr := add(0x20, result) } copy(srcPtr, destPtr, result.length); receipt.data = result.toRlpItem().toList(); } receipt.logIndex = getReceiptLogIndex(payload); return receipt; } function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[7].toBytes(); } function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[8].toBytes(); } function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[8].toUint(); } function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[9].toUint(); } // Receipt methods function toBytes(Receipt memory receipt) internal pure returns (bytes memory) { return receipt.raw; } function getLog(Receipt memory receipt) internal pure returns (Log memory) { RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex]; return Log(logData, logData.toList()); } // Log methods function getEmitter(Log memory log) internal pure returns (address) { return RLPReader.toAddress(log.list[0]); } function getTopics(Log memory log) internal pure returns (LogTopics memory) { return LogTopics(log.list[1].toList()); } function getData(Log memory log) internal pure returns (bytes memory) { return log.list[2].toBytes(); } function toRlpBytes(Log memory log) internal pure returns (bytes memory) { return log.data.toRlpBytes(); } // LogTopics methods function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) { return topics.data[index]; }}

File 54 of 65 : Merkle.sol

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;library Merkle { function checkMembership( bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof ) internal pure returns (bool) { require(proof.length % 32 == 0, "Invalid proof length"); uint256 proofHeight = proof.length / 32; // Proof of size n means, height of the tree is n+1. // In a tree of height n+1, max #leafs possible is 2 ^ n require(index < 2**proofHeight, "Leaf index is too big"); bytes32 proofElement; bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { assembly { proofElement := mload(add(proof, i)) } if (index % 2 == 0) { computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } index = index / 2; } return computedHash == rootHash; }}

File 55 of 65 : MerklePatriciaProof.sol

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import {RLPReader} from "./RLPReader.sol";library MerklePatriciaProof { /* * @dev Verifies a merkle patricia proof. * @param value The terminating value in the trie. * @param encodedPath The path in the trie leading to value. * @param rlpParentNodes The rlp encoded stack of nodes. * @param root The root hash of the trie. * @return The boolean validity of the proof. */ function verify( bytes memory value, bytes memory encodedPath, bytes memory rlpParentNodes, bytes32 root ) internal pure returns (bool) { RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes); RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item); bytes memory currentNode; RLPReader.RLPItem[] memory currentNodeList; bytes32 nodeKey = root; uint256 pathPtr = 0; bytes memory path = _getNibbleArray(encodedPath); if (path.length == 0) { return false; } for (uint256 i = 0; i < parentNodes.length; i++) { if (pathPtr > path.length) { return false; } currentNode = RLPReader.toRlpBytes(parentNodes[i]); if (nodeKey != keccak256(currentNode)) { return false; } currentNodeList = RLPReader.toList(parentNodes[i]); if (currentNodeList.length == 17) { if (pathPtr == path.length) { if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) { return true; } else { return false; } } uint8 nextPathNibble = uint8(path[pathPtr]); if (nextPathNibble > 16) { return false; } nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble])); pathPtr += 1; } else if (currentNodeList.length == 2) { uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr); if (pathPtr + traversed == path.length) { //leaf node if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) { return true; } else { return false; } } //extension node if (traversed == 0) { return false; } pathPtr += traversed; nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1])); } else { return false; } } } function _nibblesToTraverse( bytes memory encodedPartialPath, bytes memory path, uint256 pathPtr ) private pure returns (uint256) { uint256 len = 0; // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath // and slicedPath have elements that are each one hex character (1 nibble) bytes memory partialPath = _getNibbleArray(encodedPartialPath); bytes memory slicedPath = new bytes(partialPath.length); // pathPtr counts nibbles in path // partialPath.length is a number of nibbles for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) { bytes1 pathNibble = path[i]; slicedPath[i - pathPtr] = pathNibble; } if (keccak256(partialPath) == keccak256(slicedPath)) { len = partialPath.length; } else { len = 0; } return len; } // bytes b must be hp encoded function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) { bytes memory nibbles = ""; if (b.length > 0) { uint8 offset; uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b)); if (hpNibble == 1 || hpNibble == 3) { nibbles = new bytes(b.length * 2 - 1); bytes1 oddNibble = _getNthNibbleOfBytes(1, b); nibbles[0] = oddNibble; offset = 1; } else { nibbles = new bytes(b.length * 2 - 2); offset = 0; } for (uint256 i = offset; i < nibbles.length; i++) { nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b); } } return nibbles; } function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) { return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10); }}

File 56 of 65 : RLPReader.sol

/* * @author Hamdi Allam [emailprotected] * Please reach out with any questions or concerns */pragma solidity ^0.8.0;library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint256 len; uint256 memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint256 nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint256 ptr = self.nextPtr; uint256 itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint256 memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param item RLP encoded bytes */ function rlpLen(RLPItem memory item) internal pure returns (uint256) { return item.len; } /* * @param item RLP encoded bytes */ function payloadLen(RLPItem memory item) internal pure returns (uint256) { return item.len - _payloadOffset(item.memPtr); } /* * @param item RLP encoded list in bytes */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint256 items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 dataLen; for (uint256 i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint256 memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { uint256 offset = _payloadOffset(item.memPtr); uint256 memPtr = item.memPtr + offset; uint256 len = item.len - offset; // data length return (memPtr, len); } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint256 memPtr, uint256 len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint256 ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte < 128 is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint256 result; uint256 memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } return result == 0 ? false : true; } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(uint160(toUint(item))); } function toUint(RLPItem memory item) internal pure returns (uint256) { require(item.len > 0 && item.len <= 33); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; uint256 result; uint256 memPtr = item.memPtr + offset; assembly { result := mload(memPtr) // shift to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint256) { // one byte prefix require(item.len == 33); uint256 result; uint256 memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; // data length bytes memory result = new bytes(len); uint256 destPtr; assembly { destPtr := add(0x20, result) } copy(item.memPtr + offset, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint256) { if (item.len == 0) return 0; uint256 count = 0; uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint256 memPtr) private pure returns (uint256) { uint256 itemLen; uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint256 memPtr) private pure returns (uint256) { uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy( uint256 src, uint256 dest, uint256 len ) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len == 0) return; // left over bytes. Mask is used to remove unwanted bytes from the word uint256 mask = 256**(WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } }}

File 57 of 65 : FxBaseChildTunnel.sol

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;// IFxMessageProcessor represents interface to process messageinterface IFxMessageProcessor { function processMessageFromRoot( uint256 stateId, address rootMessageSender, bytes calldata data ) external;}/** * @notice Mock child tunnel contract to receive and send message from L2 */abstract contract FxBaseChildTunnel is IFxMessageProcessor { // MessageTunnel on L1 will get data from this event event MessageSent(bytes message); // fx child address public fxChild; // fx root tunnel address public fxRootTunnel; constructor(address _fxChild) { fxChild = _fxChild; } // Sender must be fxRootTunnel in case of ERC20 tunnel modifier validateSender(address sender) { require(sender == fxRootTunnel, "FxBaseChildTunnel: INVALID_SENDER_FROM_ROOT"); _; } // set fxRootTunnel if not set already function setFxRootTunnel(address _fxRootTunnel) external virtual { require(fxRootTunnel == address(0x0), "FxBaseChildTunnel: ROOT_TUNNEL_ALREADY_SET"); fxRootTunnel = _fxRootTunnel; } function processMessageFromRoot( uint256 stateId, address rootMessageSender, bytes calldata data ) external override { require(msg.sender == fxChild, "FxBaseChildTunnel: INVALID_SENDER"); _processMessageFromRoot(stateId, rootMessageSender, data); } /** * @notice Emit message that can be received on Root Tunnel * @dev Call the internal function when need to emit message * @param message bytes message that will be sent to Root Tunnel * some message examples - * abi.encode(tokenId); * abi.encode(tokenId, tokenMetadata); * abi.encode(messageType, messageData); */ function _sendMessageToRoot(bytes memory message) internal { emit MessageSent(message); } /** * @notice Process message received from Root Tunnel * @dev function needs to be implemented to handle message as per requirement * This is called by onStateReceive function. * Since it is called via a system call, any event will not be emitted during its execution. * @param stateId unique state id * @param sender root message sender * @param message bytes message that was sent from Root Tunnel */ function _processMessageFromRoot( uint256 stateId, address sender, bytes memory message ) internal virtual;}

File 58 of 65 : FxBaseRootTunnel.sol

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import {RLPReader} from "../lib/RLPReader.sol";import {MerklePatriciaProof} from "../lib/MerklePatriciaProof.sol";import {Merkle} from "../lib/Merkle.sol";import "../lib/ExitPayloadReader.sol";interface IFxStateSender { function sendMessageToChild(address _receiver, bytes calldata _data) external;}contract ICheckpointManager { struct HeaderBlock { bytes32 root; uint256 start; uint256 end; uint256 createdAt; address proposer; } /** * @notice mapping of checkpoint header numbers to block details * @dev These checkpoints are submited by plasma contracts */ mapping(uint256 => HeaderBlock) public headerBlocks;}abstract contract FxBaseRootTunnel { using RLPReader for RLPReader.RLPItem; using Merkle for bytes32; using ExitPayloadReader for bytes; using ExitPayloadReader for ExitPayloadReader.ExitPayload; using ExitPayloadReader for ExitPayloadReader.Log; using ExitPayloadReader for ExitPayloadReader.LogTopics; using ExitPayloadReader for ExitPayloadReader.Receipt; // keccak256(MessageSent(bytes)) bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036; // state sender contract IFxStateSender public fxRoot; // root chain manager ICheckpointManager public checkpointManager; // child tunnel contract which receives and sends messages address public fxChildTunnel; // storage to avoid duplicate exits mapping(bytes32 => bool) public processedExits; constructor(address _checkpointManager, address _fxRoot) { checkpointManager = ICheckpointManager(_checkpointManager); fxRoot = IFxStateSender(_fxRoot); } // set fxChildTunnel if not set already function setFxChildTunnel(address _fxChildTunnel) public virtual { require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET"); fxChildTunnel = _fxChildTunnel; } /** * @notice Send bytes message to Child Tunnel * @param message bytes message that will be sent to Child Tunnel * some message examples - * abi.encode(tokenId); * abi.encode(tokenId, tokenMetadata); * abi.encode(messageType, messageData); */ function _sendMessageToChild(bytes memory message) internal { fxRoot.sendMessageToChild(fxChildTunnel, message); } function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) { ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload(); bytes memory branchMaskBytes = payload.getBranchMaskAsBytes(); uint256 blockNumber = payload.getBlockNumber(); // checking if exit has already been processed // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex) bytes32 exitHash = keccak256( abi.encodePacked( blockNumber, // first 2 nibbles are dropped while generating nibble array // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only) // so converting to nibble array and then hashing it MerklePatriciaProof._getNibbleArray(branchMaskBytes), payload.getReceiptLogIndex() ) ); require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED"); processedExits[exitHash] = true; ExitPayloadReader.Receipt memory receipt = payload.getReceipt(); ExitPayloadReader.Log memory log = receipt.getLog(); // check child tunnel require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL"); bytes32 receiptRoot = payload.getReceiptRoot(); // verify receipt inclusion require( MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot), "FxRootTunnel: INVALID_RECEIPT_PROOF" ); // verify checkpoint inclusion _checkBlockMembershipInCheckpoint( blockNumber, payload.getBlockTime(), payload.getTxRoot(), receiptRoot, payload.getHeaderNumber(), payload.getBlockProof() ); ExitPayloadReader.LogTopics memory topics = log.getTopics(); require( bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig "FxRootTunnel: INVALID_SIGNATURE" ); // received message data bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message return message; } function _checkBlockMembershipInCheckpoint( uint256 blockNumber, uint256 blockTime, bytes32 txRoot, bytes32 receiptRoot, uint256 headerNumber, bytes memory blockProof ) private view { (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber); require( keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership( blockNumber - startBlock, headerRoot, blockProof ), "FxRootTunnel: INVALID_HEADER" ); } /** * @notice receive message from L2 to L1, validated by proof * @dev This function verifies if the transaction actually happened on child chain * * @param inputData RLP encoded data of the reference tx containing following list of fields * 0 - headerNumber - Checkpoint header block number containing the reference tx * 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root * 2 - blockNumber - Block number containing the reference tx on child chain * 3 - blockTime - Reference tx block time * 4 - txRoot - Transactions root of block * 5 - receiptRoot - Receipts root of block * 6 - receipt - Receipt of the reference transaction * 7 - receiptProof - Merkle proof of the reference receipt * 8 - branchMask - 32 bits denoting the path of receipt in merkle tree * 9 - receiptLogIndex - Log Index to read from the receipt */ function receiveMessage(bytes memory inputData) public virtual { bytes memory message = _validateAndExtractMessage(inputData); _processMessageFromChild(message); } /** * @notice Process message received from Child Tunnel * @dev function needs to be implemented to handle message as per requirement * This is called by receiveMessage function. * Since it is called via a system call, any event will not be emitted during its execution. * @param message bytes message that was sent from Child Tunnel */ function _processMessageFromChild(bytes memory message) internal virtual;}

File 59 of 65 : IERC20.sol

// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)pragma solidity ^0.8.0;/** * @dev Interface of the ERC20 standard as defined in the EIP. */interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool);}

File 60 of 65 : IArbSys.sol

// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IArbSys.sol)pragma solidity >=0.4.21 <0.9.0;/** * @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality. */interface IArbSys { /** * @notice Get internal version number identifying an ArbOS build * @return version number as int */ function arbOSVersion() external pure returns (uint256); function arbChainID() external view returns (uint256); /** * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) * @return block number as int */ function arbBlockNumber() external view returns (uint256); /** * @notice Send given amount of Eth to dest from sender. * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1. * @param destination recipient address on L1 * @return unique identifier for this L2-to-L1 transaction. */ function withdrawEth(address destination) external payable returns (uint256); /** * @notice Send a transaction to L1 * @param destination recipient address on L1 * @param calldataForL1 (optional) calldata for L1 contract call * @return a unique identifier for this L2-to-L1 transaction. */ function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns (uint256); /** * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract * @param account target account * @return the number of transactions issued by the given external account or the account sequence number of the given contract */ function getTransactionCount(address account) external view returns (uint256); /** * @notice get the value of target L2 storage slot * This function is only callable from address 0 to prevent contracts from being able to call it * @param account target account * @param index target index of storage slot * @return stotage value for the given account at the given index */ function getStorageAt(address account, uint256 index) external view returns (uint256); /** * @notice check if current call is coming from l1 * @return true if the caller of this was called directly from L1 */ function isTopLevelCall() external view returns (bool); /** * @notice check if the caller (of this caller of this) is an aliased L1 contract address * @return true iff the caller's address is an alias for an L1 contract address */ function wasMyCallersAddressAliased() external view returns (bool); /** * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing * @return address of the caller's caller, without applying L1 contract address aliasing */ function myCallersAddressWithoutAliasing() external view returns (address); /** * @notice map L1 sender contract address to its L2 alias * @param sender sender address * @param dest destination address * @return aliased sender address */ function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns (address); /** * @notice get the caller's amount of available storage gas * @return amount of storage gas available to the caller */ function getStorageGasAvailable() external view returns (uint256); event L2ToL1Transaction( address caller, address indexed destination, uint256 indexed uniqueId, uint256 indexed batchNumber, uint256 indexInBatch, uint256 arbBlockNum, uint256 ethBlockNum, uint256 timestamp, uint256 callvalue, bytes data );}

File 61 of 65 : IBridge.sol

// SPDX-License-Identifier: Apache-2.0// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IBridge.sol)/* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */pragma solidity ^0.8.0;interface IBridge { event MessageDelivered( uint256 indexed messageIndex, bytes32 indexed beforeInboxAcc, address inbox, uint8 kind, address sender, bytes32 messageDataHash ); event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); event InboxToggle(address indexed inbox, bool enabled); event OutboxToggle(address indexed outbox, bool enabled); function deliverMessageToInbox( uint8 kind, address sender, bytes32 messageDataHash ) external payable returns (uint256); function executeCall( address destAddr, uint256 amount, bytes calldata data ) external returns (bool success, bytes memory returnData); // These are only callable by the admin function setInbox(address inbox, bool enabled) external; function setOutbox(address inbox, bool enabled) external; // View functions function activeOutbox() external view returns (address); function allowedInboxes(address inbox) external view returns (bool); function allowedOutboxes(address outbox) external view returns (bool); function inboxAccs(uint256 index) external view returns (bytes32); function messageCount() external view returns (uint256);}

File 62 of 65 : IInbox.sol

// SPDX-License-Identifier: Apache-2.0// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IInbox.sol)/* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */pragma solidity ^0.8.0;import "./IMessageProvider.sol";interface IInbox is IMessageProvider { function sendL2Message(bytes calldata messageData) external returns (uint256); function sendUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, uint256 nonce, address destAddr, uint256 amount, bytes calldata data ) external returns (uint256); function sendContractTransaction( uint256 maxGas, uint256 gasPriceBid, address destAddr, uint256 amount, bytes calldata data ) external returns (uint256); function sendL1FundedUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, uint256 nonce, address destAddr, bytes calldata data ) external payable returns (uint256); function sendL1FundedContractTransaction( uint256 maxGas, uint256 gasPriceBid, address destAddr, bytes calldata data ) external payable returns (uint256); function createRetryableTicket( address destAddr, uint256 arbTxCallValue, uint256 maxSubmissionCost, address submissionRefundAddress, address valueRefundAddress, uint256 maxGas, uint256 gasPriceBid, bytes calldata data ) external payable returns (uint256); function createRetryableTicketNoRefundAliasRewrite( address destAddr, uint256 arbTxCallValue, uint256 maxSubmissionCost, address submissionRefundAddress, address valueRefundAddress, uint256 maxGas, uint256 gasPriceBid, bytes calldata data ) external payable returns (uint256); function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); function bridge() external view returns (address); function pauseCreateRetryables() external; function unpauseCreateRetryables() external; function startRewriteAddress() external; function stopRewriteAddress() external;}

File 63 of 65 : IMessageProvider.sol

// SPDX-License-Identifier: Apache-2.0// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IMessageProvider.sol)/* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */pragma solidity ^0.8.0;interface IMessageProvider { event InboxMessageDelivered(uint256 indexed messageNum, bytes data); event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);}

File 64 of 65 : IOutbox.sol

// SPDX-License-Identifier: Apache-2.0// OpenZeppelin Contracts (last updated v4.6.0) (vendor/arbitrum/IOutbox.sol)/* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */pragma solidity ^0.8.0;interface IOutbox { event OutboxEntryCreated( uint256 indexed batchNum, uint256 outboxEntryIndex, bytes32 outputRoot, uint256 numInBatch ); event OutBoxTransactionExecuted( address indexed destAddr, address indexed l2Sender, uint256 indexed outboxEntryIndex, uint256 transactionIndex ); function l2ToL1Sender() external view returns (address); function l2ToL1Block() external view returns (uint256); function l2ToL1EthBlock() external view returns (uint256); function l2ToL1Timestamp() external view returns (uint256); function l2ToL1BatchNum() external view returns (uint256); function l2ToL1OutputId() external view returns (bytes32); function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; function outboxEntryExists(uint256 batchNum) external view returns (bool);}

File 65 of 65 : ICrossDomainMessenger.sol

// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (vendor/optimism/ICrossDomainMessenger.sol)pragma solidity >0.5.0 <0.9.0;/** * @title ICrossDomainMessenger */interface ICrossDomainMessenger { /********** * Events * **********/ event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); event RelayedMessage(bytes32 indexed msgHash); event FailedRelayedMessage(bytes32 indexed msgHash); /************* * Variables * *************/ function xDomainMessageSender() external view returns (address); /******************** * Public Functions * ********************/ /** * Sends a cross domain message to the target messenger. * @param _target Target contract address. * @param _message Message to send to the target. * @param _gasLimit Gas limit for the provided message. */ function sendMessage( address _target, bytes calldata _message, uint32 _gasLimit ) external;}

Settings

{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {}}

Contract ABI

  • JSON Format
  • RAW/Text Format
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"socket_","type":"address"},{"internalType":"address","name":"gasPriceOracle_","type":"address"},{"internalType":"uint256","name":"chainSlug_","type":"uint256"},{"internalType":"uint256","name":"timeoutInSeconds_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAttested","type":"error"},{"inputs":[],"name":"AlreadyInitialised","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSigLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NoPermit","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"OnlySocket","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"WatcherFound","type":"error"},{"inputs":[],"name":"WatcherNotFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dstChainSlug","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"attestGasLimit","type":"uint256"}],"name":"AttestGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"siblingChainSlug","type":"uint256"},{"indexed":false,"internalType":"address","name":"capacitor","type":"address"},{"indexed":false,"internalType":"uint256","name":"maxPacketSize","type":"uint256"}],"name":"CapacitorRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"dstChainSlug","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"executionOverhead","type":"uint256"}],"name":"ExecutionOverheadSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"gasPriceOracle","type":"address"}],"name":"GasPriceOracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"}],"name":"OwnerClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominee","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"packetId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"attester","type":"address"}],"name":"PacketAttested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"srcChainSlug","type":"uint256"},{"indexed":false,"internalType":"bool","name":"tripSinglePath","type":"bool"}],"name":"PathTripped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"grantee","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"revokee","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSocket","type":"address"}],"name":"SocketSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"tripGlobalFuse","type":"bool"}],"name":"SwitchboardTripped","type":"event"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"packetId_","type":"bytes32"},{"internalType":"uint32","name":"srcChainSlug_","type":"uint32"},{"internalType":"uint256","name":"proposeTime_","type":"uint256"}],"name":"allowPacket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"packetId_","type":"bytes32"},{"internalType":"uint256","name":"srcChainSlug_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"attest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"attestGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"attestations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainSlug","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"executionOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPriceOracle__","outputs":[{"internalType":"contract IGasPriceOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstChainSlug_","type":"uint32"}],"name":"getMinFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"roleNames_","type":"bytes32[]"},{"internalType":"address[]","name":"grantees_","type":"address[]"}],"name":"grantBatchRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roleName_","type":"string"},{"internalType":"uint256","name":"chainSlug_","type":"uint256"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"srcChainSlug_","type":"uint256"},{"internalType":"address","name":"watcher_","type":"address"}],"name":"grantWatcherRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roleName_","type":"string"},{"internalType":"uint256","name":"chainSlug_","type":"uint256"},{"internalType":"address","name":"address_","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"address_","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"isAttested","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isInitialised","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"isPacketValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"maxPacketSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nominee_","type":"address"}],"name":"nominateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstChainSlug_","type":"uint32"}],"name":"payFees","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"siblingChainSlug_","type":"uint256"},{"internalType":"address","name":"capacitor_","type":"address"},{"internalType":"uint256","name":"maxPacketSize_","type":"uint256"}],"name":"registerCapacitor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"userAddress_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"roleNames_","type":"bytes32[]"},{"internalType":"address[]","name":"grantees_","type":"address[]"}],"name":"revokeBatchRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"roleName_","type":"string"},{"internalType":"uint256","name":"chainSlug_","type":"uint256"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"revokee_","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"srcChainSlug_","type":"uint256"},{"internalType":"address","name":"watcher_","type":"address"}],"name":"revokeWatcherRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint256","name":"dstChainSlug_","type":"uint256"},{"internalType":"uint256","name":"attestGasLimit_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setAttestGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint256","name":"dstChainSlug_","type":"uint256"},{"internalType":"uint256","name":"executionOverhead_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setExecutionOverhead","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gasPriceOracle_","type":"address"}],"name":"setGasPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"socket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeoutInSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalWatchers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"tripGlobal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tripGlobalFuse","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint256","name":"srcChainSlug_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"tripPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tripSinglePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"untrip","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint256","name":"srcChainSlug_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"untripPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Contract Creation Code

Decompile ByteCode Switch to Opcodes View

60c06040523480156200001157600080fd5b5060405162003345380380620033458339810160408190526200003491620000a5565b600080546001600160a01b039687166001600160a01b031991821617909155600180548216905560038054821694871694909417909355600480549093169390941692909217905560805260a05262000102565b80516001600160a01b0381168114620000a057600080fd5b919050565b600080600080600060a08688031215620000be57600080fd5b620000c98662000088565b9450620000d96020870162000088565b9350620000e96040870162000088565b6060870151608090970151959894975095949392505050565b60805160a0516131ec62000159600039600081816109630152611bb40152600081816107c5015281816109c7015281816110e40152818161198d01528181611c3201528181611e33015261200e01526131ec6000f3fe6080604052600436106102dc5760003560e01c80635b94db2711610184578063b553b3a4116100d6578063c32b0a821161008a578063d4dc1bd411610064578063d4dc1bd414610911578063d547741f14610931578063efec6cd41461095157600080fd5b8063c32b0a82146108a4578063d0c628bd146108c4578063d39a38c1146108f157600080fd5b8063bd9ffd28116100bb578063bd9ffd2814610837578063bfcdc40714610864578063c13428071461088457600080fd5b8063b553b3a4146107e7578063bc6aad781461081757600080fd5b806391d14854116101385780639ea2694d116101125780639ea2694d14610782578063a4d0c0a914610793578063b349ba65146107b357600080fd5b806391d1485414610708578063940992a3146107285780639a1dc5051461075557600080fd5b80636d53126e116101695780636d53126e1461068d57806376920cab146106ad5780638da5cb5b146106dd57600080fd5b80635b94db271461064d5780636ccae0541461066d57600080fd5b80632676cdbf1161023d5780633c49eb33116101f15780634b2499bd116101cb5780634b2499bd146105ce5780634eb5ae07146105ee5780635a3a39491461061b57600080fd5b80633c49eb331461056e5780633e59000c1461058e5780633f8393f9146105ae57600080fd5b806331d1e0631161022257806331d1e063146104ee57806337708725146105295780633bd1adec1461055957600080fd5b80632676cdbf146104ae5780632f2ff15d146104ce57600080fd5b8063164e68de1161029457806320f99c0a1161027957806320f99c0a14610405578063210810c21461045157806322c8f6cd1461048157600080fd5b8063164e68de146103c55780631bd1cffd146103e557600080fd5b80630cd55abf116102c55780630cd55abf1461033d57806311ba7ba014610378578063146ce2e01461039857600080fd5b80630132dd9b146102e157806306da42e014610303575b600080fd5b3480156102ed57600080fd5b506103016102fc366004612e8b565b610985565b005b34801561030f57600080fd5b5061032361031e366004612f96565b610bad565b604080519283526020830191909152015b60405180910390f35b34801561034957600080fd5b5061036a610358366004612bc3565b60096020526000908152604090205481565b604051908152602001610334565b34801561038457600080fd5b50610301610393366004612c44565b610bc2565b3480156103a457600080fd5b5061036a6103b3366004612cd2565b600c6020526000908152604090205481565b3480156103d157600080fd5b506103016103e0366004612bc3565b610c8b565b3480156103f157600080fd5b50610301610400366004612d9b565b610d25565b34801561041157600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610334565b34801561045d57600080fd5b5061047161046c366004612d9b565b610d86565b6040519015158152602001610334565b34801561048d57600080fd5b5060045461042c9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104ba57600080fd5b506103016104c9366004612ceb565b610d9b565b3480156104da57600080fd5b506103016104e9366004612ceb565b610f02565b3480156104fa57600080fd5b50610471610509366004612c1a565b600d60209081526000928352604080842090915290825290205460ff1681565b34801561053557600080fd5b50610471610544366004612cd2565b60056020526000908152604090205460ff1681565b34801561056557600080fd5b50610301610f5d565b34801561057a57600080fd5b50610301610589366004612c44565b610fe6565b34801561059a57600080fd5b506103016105a9366004612edb565b6110a8565b3480156105ba57600080fd5b506103016105c9366004612d9b565b6112db565b3480156105da57600080fd5b506103016105e9366004612d54565b611337565b3480156105fa57600080fd5b5061036a610609366004612cd2565b60076020526000908152604090205481565b34801561062757600080fd5b506003546104719074010000000000000000000000000000000000000000900460ff1681565b34801561065957600080fd5b50610301610668366004612bc3565b611553565b34801561067957600080fd5b50610301610688366004612bde565b611613565b34801561069957600080fd5b506103016106a8366004612ceb565b6116b1565b3480156106b957600080fd5b506104716106c8366004612cd2565b600a6020526000908152604090205460ff1681565b3480156106e957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661042c565b34801561071457600080fd5b50610471610723366004612ceb565b61180f565b34801561073457600080fd5b5061036a610743366004612cd2565b600e6020526000908152604090205481565b34801561076157600080fd5b5060035461042c9073ffffffffffffffffffffffffffffffffffffffff1681565b610301610790366004612f96565b50565b34801561079f57600080fd5b506103016107ae366004612bc3565b61184a565b3480156107bf57600080fd5b5061036a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107f357600080fd5b50610471610802366004612cd2565b60086020526000908152604090205460ff1681565b34801561082357600080fd5b50610301610832366004612e44565b611951565b34801561084357600080fd5b5061036a610852366004612cd2565b60066020526000908152604090205481565b34801561087057600080fd5b5061047161087f366004612d17565b611b45565b34801561089057600080fd5b5061030161089f366004612e8b565b611bf6565b3480156108b057600080fd5b506103016108bf366004612f3c565b611df1565b3480156108d057600080fd5b5061036a6108df366004612cd2565b600b6020526000908152604090205481565b3480156108fd57600080fd5b5061030161090c366004612e44565b611fd2565b34801561091d57600080fd5b5061030161092c366004612e1f565b6121d6565b34801561093d57600080fd5b5061030161094c366004612ceb565b612311565b34801561095d57600080fd5b5061036a7f000000000000000000000000000000000000000000000000000000000000000081565b6040805160a060208201819052600960c08301527f545249505f50415448000000000000000000000000000000000000000000000060e08301529181018490527f0000000000000000000000000000000000000000000000000000000000000000606082015260808101859052600191810191909152600090610a2390610100015b604051602081830303815290604052805190602001208361236c565b9050610a656040518060400160405280600981526020017f545249505f524f4c4500000000000000000000000000000000000000000000008152508483612459565b610ac2576040517f962f63330000000000000000000000000000000000000000000000000000000081527f545249505f524f4c45000000000000000000000000000000000000000000000060048201526024015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082610af4836130f0565b919050559050808514610b33576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526008602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558251878152918201527f52696448b19e976fdff1df3604c7fe438e48c398c9b83e00bc77b5f613a7480591015b60405180910390a15050505050565b600080610bb9836124d8565b91509150915091565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c13576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828114610c1f57600080fd5b60005b83811015610c8457610c72858583818110610c3f57610c3f613158565b90506020020135848484818110610c5857610c58613158565b9050602002016020810190610c6d9190612bc3565b6125dd565b80610c7c816130f0565b915050610c22565b5050505050565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff16610d18576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610ab9565b610d2182612660565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d76576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d81838383612766565b505050565b6000610d93848484612459565b949350505050565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff16610e28576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610ab9565b610e686040518060400160405280600c81526020017f574154434845525f524f4c4500000000000000000000000000000000000000008152508484612459565b610e9e576040517fa278e4ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ede6040518060400160405280600c81526020017f574154434845525f524f4c4500000000000000000000000000000000000000008152508484612798565b6000838152600b60205260408120805491610ef8836130bb565b9190505550505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f53576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2182826127ca565b60015473ffffffffffffffffffffffffffffffffffffffff163314610fae576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081163317909155600180549091169055565b60005473ffffffffffffffffffffffffffffffffffffffff163314611037576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82811461104357600080fd5b60005b83811015610c845761109685858381811061106357611063613158565b9050602002013584848481811061107c5761107c613158565b90506020020160208101906110919190612bc3565b6127ca565b806110a0816130f0565b915050611046565b6040805160a060208201819052601760c08301527f4154544553545f4741535f4c494d49545f55504441544500000000000000000060e08301527f000000000000000000000000000000000000000000000000000000000000000092820192909252606081018690526080810187905290810184905260009061117c90610100015b6040516020818303038152906040528051906020012084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061236c92505050565b90506111be6040518060400160405280601681526020017f4741535f4c494d49545f555044415445525f524f4c45000000000000000000008152508683612459565b611216576040517f962f63330000000000000000000000000000000000000000000000000000000081527f4741535f4c494d49545f555044415445525f524f4c45000000000000000000006004820152602401610ab9565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082611248836130f0565b919050559050808714611287576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600c602090815260409182902087905581518881529081018790527f6ccba2c85bb8e0527ca24268806f6e3dd808eee2de980218d10fd8374e0d0feb910160405180910390a150505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461132c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d81838383612798565b6000611358848660405160200161112a929190918252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d6020908152604080832089845290915290205490915060ff16156113c6576040517f35d9080500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114066040518060400160405280600c81526020017f574154434845525f524f4c4500000000000000000000000000000000000000008152508583612459565b61143c576040517fa278e4ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600d60209081526040808320888452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600e90915281208054916114a8836130f0565b90915550506000848152600b6020908152604080832054888452600e9092529091205410611508576000858152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b6040805186815273ffffffffffffffffffffffffffffffffffffffff831660208201527f9252c8c2f6561af208f474c233ba1d93c687cb742293de5a99e0d95cad349fce9101610b9e565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115a4576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff166116a0576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610ab9565b6116ab848484612850565b50505050565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff1661173e576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610ab9565b61177e6040518060400160405280600c81526020017f574154434845525f524f4c4500000000000000000000000000000000000000008152508484612459565b156117b5576040517fa080b55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117f56040518060400160405280600c81526020017f574154434845525f524f4c4500000000000000000000000000000000000000008152508484612766565b6000838152600b60205260408120805491610ef8836130f0565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff166118d7576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610ab9565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527f613a64b3662b10f8597546393ac0fcc0042be57b95447f7f53384f5c020ee9fa9060200160405180910390a15050565b60408051608060208201819052600660a08301527f554e54524950000000000000000000000000000000000000000000000000000060c08301527f0000000000000000000000000000000000000000000000000000000000000000928201929092526060810184905260009181018290526119ce9060e001610a07565b73ffffffffffffffffffffffffffffffffffffffff811660009081527fec8735a6f9360cce4cfd71deed80e8ff6582ffbecde98525316dc9c7ebf3e1ba602052604090205490915060ff16611a71576040517f962f63330000000000000000000000000000000000000000000000000000000081527f554e545249505f524f4c450000000000000000000000000000000000000000006004820152602401610ab9565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082611aa3836130f0565b919050559050808414611ae2576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055604051600081527f0d5bd1d24e1dc8f87ca28713158eb445b10d72c9fbb6facb3d625bfb5ab67b63906020015b60405180910390a150505050565b60035460009074010000000000000000000000000000000000000000900460ff1680611b86575063ffffffff831660009081526008602052604090205460ff165b15611b9357506000610d93565b6000848152600a602052604090205460ff1615611bb257506001610d93565b7f0000000000000000000000000000000000000000000000000000000000000000611bdd83426130a4565b1115611beb57506001610d93565b506000949350505050565b6040805160a060208201819052600b60c08301527f554e545249505f5041544800000000000000000000000000000000000000000060e08301527f00000000000000000000000000000000000000000000000000000000000000009282019290925260608101849052608081018590526000918101829052611c7b9061010001610a07565b9050611cbd6040518060400160405280600b81526020017f554e545249505f524f4c450000000000000000000000000000000000000000008152508483612459565b611d15576040517f962f63330000000000000000000000000000000000000000000000000000000081527f554e545249505f524f4c450000000000000000000000000000000000000000006004820152602401610ab9565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082611d47836130f0565b919050559050808514611d86576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260086020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051878152918201929092527f52696448b19e976fdff1df3604c7fe438e48c398c9b83e00bc77b5f613a748059101610b9e565b6040805160a060208201819052601960c08301527f455845435554494f4e5f4f564552484541445f5550444154450000000000000060e08301529181018690527f0000000000000000000000000000000000000000000000000000000000000000606082015260808101859052908101839052600090611e749061010001610a07565b9050611eb66040518060400160405280601681526020017f4741535f4c494d49545f555044415445525f524f4c45000000000000000000008152508583612459565b611f0e576040517f962f63330000000000000000000000000000000000000000000000000000000081527f4741535f4c494d49545f555044415445525f524f4c45000000000000000000006004820152602401610ab9565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082611f40836130f0565b919050559050808614611f7f576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008581526007602090815260409182902086905581518781529081018690527f4b6e1951999da15d9b411635fb5df0b3b3e78d5e19bae64af3f2f271943cdaba910160405180910390a1505050505050565b60408051608060208201819052600460a08301527f545249500000000000000000000000000000000000000000000000000000000060c08301527f000000000000000000000000000000000000000000000000000000000000000092820192909252606081018490526001918101919091526000906120539060e001610a07565b73ffffffffffffffffffffffffffffffffffffffff811660009081527ef971d2906bc2b30e8466492ce79c9f3ec1853cead39c33cbcf8da6618fac81602052604090205490915060ff166120f5576040517f962f63330000000000000000000000000000000000000000000000000000000081527f545249505f524f4c4500000000000000000000000000000000000000000000006004820152602401610ab9565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260096020526040812080549082612127836130f0565b919050559050808414612166576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055604051600181527f0d5bd1d24e1dc8f87ca28713158eb445b10d72c9fbb6facb3d625bfb5ab67b6390602001611b37565b60045473ffffffffffffffffffffffffffffffffffffffff163314612227576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526005602052604090205460ff1615612270576040517f3c3282e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556006825291829020839055815185815273ffffffffffffffffffffffffffffffffffffffff8516918101919091529081018290527fd253cff633cf6f75e5a1a5638f00149a011f753ee76180bcac410b00da1a9686906060015b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612362576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2182826125dd565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018390526000908190605c0160405160208183030381529060405280519060200120905060008060006123ca866129b7565b60408051600081526020810180835289905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa158015612425573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6000610d938484604051602001612471929190612fb1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b6003546040517f408f76fb00000000000000000000000000000000000000000000000000000000815263ffffffff831660048201526000918291829173ffffffffffffffffffffffffffffffffffffffff169063408f76fb9060240160206040518083038186803b15801561254c57600080fd5b505afa158015612560573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125849190612e06565b63ffffffff85166000818152600660205260409020549192506125a79083612a15565b6125b1919061302c565b63ffffffff85166000908152600760205260409020549093506125d5908290613067565b915050915091565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b73ffffffffffffffffffffffffffffffffffffffff811661268057600080fd5b604051479060009073ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d80600081146126da576040519150601f19603f3d011682016040523d82523d6000602084013e6126df565b606091505b505090508061271a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85168152602081018490527fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a9101612304565b610d81838360405160200161277c929190612fb1565b60405160208183030381529060405280519060200120826127ca565b610d8183836040516020016127ae929190612fb1565b60405160208183030381529060405280519060200120826125dd565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b73ffffffffffffffffffffffffffffffffffffffff821661287057600080fd5b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561290f5760008273ffffffffffffffffffffffffffffffffffffffff164760405160006040518083038185875af1925050503d80600081146128fc576040519150601f19603f3d011682016040523d82523d6000602084013e612901565b606091505b50509050806116ab57600080fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b15801561297f57600080fd5b505af1158015612993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ab9190612cb0565b600080600083516041146129f7576040517fd245329300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505060208101516040820151606090920151909260009190911a90565b6000828152600c6020908152604080832054600b9092528220548391612a3a91613067565b6118439190613067565b600067ffffffffffffffff80841115612a5f57612a5f613187565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612aa557612aa5613187565b81604052809350858152868686011115612abe57600080fd5b858560208301376000602087830101525050509392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612afc57600080fd5b919050565b60008083601f840112612b1357600080fd5b50813567ffffffffffffffff811115612b2b57600080fd5b6020830191508360208260051b8501011115612b4657600080fd5b9250929050565b60008083601f840112612b5f57600080fd5b50813567ffffffffffffffff811115612b7757600080fd5b602083019150836020828501011115612b4657600080fd5b600082601f830112612ba057600080fd5b61184383833560208501612a44565b803563ffffffff81168114612afc57600080fd5b600060208284031215612bd557600080fd5b61184382612ad8565b600080600060608486031215612bf357600080fd5b612bfc84612ad8565b9250612c0a60208501612ad8565b9150604084013590509250925092565b60008060408385031215612c2d57600080fd5b612c3683612ad8565b946020939093013593505050565b60008060008060408587031215612c5a57600080fd5b843567ffffffffffffffff80821115612c7257600080fd5b612c7e88838901612b01565b90965094506020870135915080821115612c9757600080fd5b50612ca487828801612b01565b95989497509550505050565b600060208284031215612cc257600080fd5b8151801515811461184357600080fd5b600060208284031215612ce457600080fd5b5035919050565b60008060408385031215612cfe57600080fd5b82359150612d0e60208401612ad8565b90509250929050565b60008060008060808587031215612d2d57600080fd5b8435935060208501359250612d4460408601612baf565b9396929550929360600135925050565b60008060008060608587031215612d6a57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612d8f57600080fd5b612ca487828801612b4d565b600080600060608486031215612db057600080fd5b833567ffffffffffffffff811115612dc757600080fd5b8401601f81018613612dd857600080fd5b612de786823560208401612a44565b93505060208401359150612dfd60408501612ad8565b90509250925092565b600060208284031215612e1857600080fd5b5051919050565b600080600060608486031215612e3457600080fd5b83359250612c0a60208501612ad8565b60008060408385031215612e5757600080fd5b82359150602083013567ffffffffffffffff811115612e7557600080fd5b612e8185828601612b8f565b9150509250929050565b600080600060608486031215612ea057600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612ec557600080fd5b612ed186828701612b8f565b9150509250925092565b600080600080600060808688031215612ef357600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115612f1f57600080fd5b612f2b88828901612b4d565b969995985093965092949392505050565b60008060008060808587031215612f5257600080fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115612f7e57600080fd5b612f8a87828801612b8f565b91505092959194509250565b600060208284031215612fa857600080fd5b61184382612baf565b604081526000835180604084015260005b81811015612fdf5760208187018101516060868401015201612fc2565b81811115612ff1576000606083860101525b50602083019390935250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601606001919050565b600082613062577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561309f5761309f613129565b500290565b6000828210156130b6576130b6613129565b500390565b6000816130ca576130ca613129565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561312257613122613129565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea2646970667358221220ea6c8ca8d301f22233f3041432f43407111795a88dcc84f45043426ebe14337364736f6c63430008070033000000000000000000000000752b38fa38f53df7fa60e6113cfd9094b7e040aa000000000000000000000000d11519ae2cb258ffe820b5d6bb052cbb03c9c635000000000000000000000000d85c61ac15cf843f005b44e87635bcfc3a531ca300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000001c20


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

000000000000000000000000752b38fa38f53df7fa60e6113cfd9094b7e040aa000000000000000000000000d11519ae2cb258ffe820b5d6bb052cbb03c9c635000000000000000000000000d85c61ac15cf843f005b44e87635bcfc3a531ca300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000001c20

-----Decoded View---------------
Arg [0] : owner_ (address): 0x752B38FA38F53dF7fa60e6113CFd9094b7e040Aa
Arg [1] : socket_ (address): 0xd11519aE2cB258ffe820B5d6bB052cbb03C9C635
Arg [2] : gasPriceOracle_ (address): 0xD85c61AC15cf843f005b44e87635BcfC3A531Ca3
Arg [3] : chainSlug_ (uint256): 5
Arg [4] : timeoutInSeconds_ (uint256): 7200

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000752b38fa38f53df7fa60e6113cfd9094b7e040aa
Arg [1] : 000000000000000000000000d11519ae2cb258ffe820b5d6bb052cbb03c9c635
Arg [2] : 000000000000000000000000d85c61ac15cf843f005b44e87635bcfc3a531ca3
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [4] : 0000000000000000000000000000000000000000000000000000000000001c20


BlockTransactionDifficulty Gas UsedReward

View All Blocks Produced

BlockUncle NumberDifficultyGas UsedReward

View All Uncles

Loading...

Loading

(Video) SmartContract hacking: How to cheat Etherscan
Validator IndexBlockAmount

View All Withdrawals

Txn HashBlockValue Eth2 PubKeyValid

View All Deposits

[Download: CSV Export ]

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.

Address QR Code
My Address - Private Name Tag or Note

My Name Tag:

Private Name Tags (up to 35 characters) can be used for easy identification of addresses

Private Note:

A private note (up to 500 characters) can be attached to this address.
Please DO NOT store any passwords or private keys here.

View all Private Name Tags

Compiler specific version warnings:

The compiled contract might be susceptible to AbiReencodingHeadOverflowWithStaticArrayCleanup (medium-severity), DirtyBytesArrayToStorage (low-severity), DataLocationChangeInInternalOverride (very low-severity), NestedCalldataArrayAbiReencodingSizeValidation (very low-severity), SignedImmutables (very low-severity) Solidity Compiler Bugs.

Connect a Wallet
Connect a Wallet
(Video) Get transactions by address - Etherscan api with python 3 tutorial 3

FAQs

What is verify address ownership? ›

Verify Contract Address Ownership process involves verifying the ownership of a smart contract address with the Ethereum address used to create the smart contract and then linking the contract address to the owner's Etherscan account.

How do I verify my smart contract? ›

Verifying a smart contract basically involves the following steps:
  1. Input the source files and compilation settings to a compiler.
  2. Compiler outputs the bytecode of the contract.
  3. Get the bytecode of the deployed contract at a given address.
  4. Compare the deployed bytecode with the recompiled bytecode.
Jan 19, 2023

What is the token address in MetaMask? ›

The contract address is necessary for MetaMask to know exactly which token you're referring to. The address itself is the location of a smart contract which manages the balances of all token holders, amongst other things, such as the total supply and its basic features (name, decimals, etc.).

Where is the contract address on NFT collectible? ›

The contract address can be found on the home page of the NFT collection or next to a particular NFTs token ID and other metadata. When buying an NFT, always make sure it features the same contract address as other NFTs in the collection.

How can I verify domain ownership? ›

Verifying ownership
  1. Go to Search Console.
  2. Click Domain.
  3. Click Continue.
  4. On the Record Type Dropdown in the Verify domain ownership via DNS record banner, use the Recommended methods option if possible.
  5. Sign in to your Domain name provider and complete the verification process per the instructions.

What is domain ownership verification? ›

Ownership verification means proving to Search Console that you own a specific website. A verified owner has the highest degree of permissions in Search Console.

Are smart contracts traceable? ›

Smart contracts ensure that transactions are transparent, traceable, and cannot be altered. Smart contracts have a wide range of use cases not only in the financial sector but also in other industries.

Can anyone see a smart contract? ›

As you may already know, smart contracts are computer programs that run on blockchains whose source code is publicly available for anyone to verify, and, as said, anyone can interact with them without the need for a web-based interface.

Can you see the source code of a smart contract? ›

In general, viewing the source code for the smart contract that would be used on the client side, can be done via contract registries. Essentially, you need to validate that at this specific address, this source matches the binary.

How do I see hidden tokens in MetaMask? ›

Unhiding tokens and NFTs

Hiding assets of both kinds is completely reversible. To unhide tokens, go to Settings > Hidden tokens and click the plus button next to the asset. To unhide NFTs, go to the NFTs page of your portfolio by flicking the toggle on the right-hand side of the dashboard.

How do I see assets in MetaMask? ›

To see your tokens, click on the Assets tab. Your tokens should be listed under this tab. If they're not, and automatic token detection isn't picking them up, then click on 'Import token' at the bottom.

Is my MetaMask address the same for all tokens? ›

Try it out: add a network to MetaMask, or switch over from one you've already added. Notice how your account and its address stay the same. This means your MetaMask address on both Ethereum mainnet and BSC, for example, is exactly the same.

What is the difference between contract address and token ID in NFT? ›

You will see the Contract Address and Token ID under [Details] below the visual of the NFT. Contract Address refers to the address where the contract is deployed on the blockchain (e.g., Ethereum), while Token ID refers to this specific NFT. We will use the ERC-721 token as an example.

What is the difference between wallet address and smart contract address? ›

Externally owned address or wallet address is an account of public and private key pair that holds your funds. Contract address is the address to a collection of application code on the blockchain that executes application specific functions.

What is the wallet address for NFTs? ›

The wallet address to receive Crypto.org Chain NFTs is the same as your Crypto.org Chain token address. The wallet address to receive ERC721 and ERC1155 NFTs is the same as your ETH/ERC-20 token address. The wallet address to receive Cronos Beta Chain NFTs is the same as your CRC-20 token address.

What are TXT DNS records used for? ›

TXT records are a type of Domain Name System (DNS) record in text format, which contain information about your domain. TXT records also have information that helps external network servers and services handle outgoing email from your domain.

WHOIS my DNS provider? ›

To find out who is responsible for DNS hosting of a domain, you need to find the authoritative DNS servers (or Name Servers) for that domain. A list of DNS servers authoritative for the domain is shown in the Name Server (NS) record. To find this record, you can use the NSLOOKUP tool.

How do you check if a domain has ever been registered? ›

Here's how to do it:
  1. Step 1: Find a WHOIS search service.
  2. Step 2: Type a domain name into the search field.
  3. Step 3: Check out the results.
  4. Step 1: Go to the site of your choice.
  5. Step 2: Type in the domain name.
  6. Step 3: Check out the info.
  7. Step 1: Go to archive.org.
  8. Step 2: Search for the domain you want to check out.
Apr 29, 2022

What are the other three things you can do to verify the domain? ›

As soon as your certificate has been ordered, there are 3 ways of verifying your domain(s). The standard (and quickest) way of verifying one or more domains is by making use of Email Verification. Other methods include DNS (CNAME) verification or HTTP File Upload.

What does a domain name identify and where is it registered? ›

Registration of a domain name establishes a set of Start of Authority (SOA) records in the DNS servers of the parent domain, indicating the IP address (or domain name) of DNS servers that are authoritative for the domain. This provides merely a reference for how to find the domain data – not the actual domain data.

What does this domain has been registered and is in the process of ownership verification? ›

"This domain has been registered and is in the process of ownership verification." If you receive this message when trying to sign up for a Google service, it might be because: You or someone in your organization already created a managed Google account with your domain and is in the process of domain verification.

Can a smart contract steal private key? ›

If the private key of a contract that implements a form of access control is leaked, an attacker could control the smart contract, potentially stealing funds or performing other malicious actions. A private key leak occurs when a smart contract's private key is exposed, either accidentally or intentionally.

Can a smart contract hold a secret? ›

In most blockchains, smart contracts cannot hold a private key. The reason is that everyone on the network needs to be able to run the logic of any smart contract (to update the state when they see a transaction).

What is truffle blockchain? ›

Truffle is a world-class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier. Truffle is widely considered the most popular tool for blockchain application development with over 1.5 million lifetime downloads.

Where are smart contracts stored? ›

Smart contracts are executed on blockchain, which means that the terms are stored in a distributed database and cannot be changed. Transactions are also processed on the blockchain, which automates payments and counterparties.

How do you read data from blockchain? ›

To retrieve the blockchain height only, use GET /blocks/height method. To retrieve all the headers of the last block, including height and timestamp, use GET /blocks/headers/last method. See method descriptions in Swagger web interface .

Why would someone use a smart contract? ›

Smart contracts are simply programs stored on a blockchain that run when predetermined conditions are met. They typically are used to automate the execution of an agreement so that all participants can be immediately certain of the outcome, without any intermediary's involvement or time loss.

How do I view smart contracts on blockchain? ›

Blockchain has a culture of transparency, and generally speaking the coding for smart contract functions will be published for anyone to review and read. So, if you are into coding, you can check the contract code by clicking on “Contract” in the same tab where you checked the contract transactions.

What network are smart contract written on? ›

The most popular blockchain for running smart contracts is Ethereum. On Ethereum, smart contracts are typically written in a Turing-complete programming language called Solidity, and compiled into low-level bytecode to be executed by the Ethereum Virtual Machine.

What is the private key of a smart contract? ›

Control of a smart contract is written into the code and assigned to a wallet, usually the wallet that created it but it can be transfered to another. There is no private key for a smart contract.

How do I use a secret key in MetaMask? ›

On the account page, click on the menu (three dots) in the upper right corner, and then on the "Account Details" button. Click “Export Private Key”. To access your private key, you'll now need to enter your wallet password. Once you've done so, click “Confirm” to proceed.

How do I see everything in MetaMask wallet? ›

After you enter your MetaMask public address, which is on Ethereum mainnet, you will see the ETH balance in native value, today's fiat value and a separate total balance of all your custom ERC-20 tokens. You will also see all the up-to-date transactions in your wallet.

How do I trace a MetaMask address? ›

To find your account's address, just hover over the label for the selected account — in this case, Account 1 — which will let you copy the account's address to the clipboard. If you're on MetaMask Mobile, you may have to tap a few times. You will then see: QR code for your account.

How do I trace MetaMask transaction history? ›

Locate the transaction:
  1. Extension: Access the 'Activity' tab and click on the relevant transaction.
  2. Mobile: Tap the hamburger icon and either select 'Transaction History', or select the token on your wallet landing page to view all its transactions.
Feb 28, 2023

How do I view MetaMask browsing history? ›

To get them: Open MetaMask and ensure it's unlocked. Click on your Account icon on the top right corner. Click on Settings and then select Advanced.
...
These logs tell us:
  1. Your account addresses.
  2. Your sent transaction history.
  3. Your internal UI State.
Oct 11, 2022

What is the difference between wallet address and account address in MetaMask? ›

'Wallet' describes the MetaMask software you're using. 'Account' refers to a public-private key pair. Your wallet doesn't have an address; an account within it does. Instead, a MetaMask wallet is a software tool that allows you to manage and access accounts.

How do I get all ERC-20 tokens owned by an address? ›

In order to get all ERC20 tokens owned by an address, Moralis provides you with an getWalletTokenBalances endpoint. Here you'll need two parameters: address and chain . Once you have obtained the address and chain , you can copy the following code: index.

Are different accounts on MetaMask different wallets? ›

Each account you create in MetaMask is derived from your Secret Recovery Phrase; therefore, your wallet contains one or more accounts.

What is the difference between ID token and access token? ›

Unlike access tokens, which are opaque objects that cannot be inspected by the application, ID tokens are meant to be inspected and used by the application. Information from the token, such as Who signed the token or the identity for whom the ID token was issued, is available for use by the application.

How do I know if my contract is erc20 or erc721? ›

2 Answers
  1. Load Transfer event.
  2. Check if the contract supports ERC-721 (via ERC-165)
  3. If yes, it is an ERC-721 transfer.
  4. If no, it is an ERC-20 transfer.
Nov 22, 2021

What is the difference between a token and an NFT? ›

Fungible tokens are digital assets that can be replaced by another identical asset. For example, Bitcoin is a fungible token because each Bitcoin is the same as any other Bitcoin. In contrast, non-fungible tokens (NFTs) are digital assets that cannot be replaced by another identical asset.

How do I identify a wallet address? ›

A wallet address is a sequence of numbers and letters, with no spaces nor symbols. Each wallet address is unique and there is no other wallet address like it. It is the unique identifier for your account on the blockchain.

What's the difference between an Ethereum wallet address and ERC20 wallet address? ›

Typically, the ERC20 wallet address is an Ethereum address. More so, all Ethereum addresses are compatible with storing ERC20. Also, all Ethereum wallets are actually connected to the Ethereum blockchain. Therefore, the ERC20 address will mean an address in the Ethereum platform.

What is the difference between wallet and smart contract wallet? ›

Many wallets today are managed by EOAs, which is how users can transfer Ether (ETH) and other tokens from a wallet by signing transactions with a private key. In contrast, smart contract wallets (also called smart wallets) are controlled by contract code instead of a private key.

What is wallet network address? ›

Crypto wallet addresses function similarly to an email address. They're safely shared with anybody looking to send you cryptocurrency, and likewise identify your wallet as the sending address when you make a crypto payment.

What blockchain are NFTs stored on? ›

Ethereum, the blockchain that most NFTs are minted on, is particularly good at adapting its protocols.

How do I find out who owns an NFT? ›

You can see who currently owns the NFT by looking at the "Tokens Transferred From and To" section. The current owner of the NFT in question is shown by the address displayed after "To."

What does verify address mean? ›

Address validation (or verification) is the process of checking a mailing address against an authoritative address database. If the address matches an address in the official database, the address "validates", meaning it's real.

What does address verification do? ›

The Address Verification Service (AVS) is a fraud prevention system that, when used effectively, can help to limit fraud and chargebacks. AVS works to verify that the address entered by the customer is associated with the cardholder's credit card account.

What is the purpose of address verification? ›

The Address Verification Service (AVS) is a fraud prevention system that can help to limit fraud and charge-backs. AVS verifies that the billing address entered by the customer is the same as the one associated with the cardholder's credit card account.

What is an example of address verification? ›

Proof of Address
  • Valid Driver's License.
  • Property Tax Receipt.
  • Posted Mail with name of applicant.
  • Utility Bill.
  • Lease Agreement or mortgage statement.
  • Insurance Card.
  • Voter Registration Card.
  • College Enrollment Papers.

What is proof of address verify? ›

People usually prove their address by supplying one or more official documents that list both their full name and address of residence – such as a utility bill or government correspondence addressed to them. In the past, proof of address verification was largely a paper-based process.

What does override address verification? ›

The Address Override Dialog Box appears when the City, State, and ZIP can be verified, but the rest of the address cannot be verified. Accept the override if you are absolutely certain this is the correct address.

How can I verify my address with Google? ›

On your computer
  1. Sign in to Google My Business.
  2. Choose the business you'd like to verify.
  3. Click Verify now.
  4. On the postcard request screen, make sure your address is displayed accurately. To help deliver your postcard, you can also add an optional contact name.
  5. Click Send postcard.
  6. Check the mail for your postcard.

How to bypass AVS mismatch? ›

This mismatch can cause a transaction to be declined as the bank will presume that the purchase is being attempted with a stolen or counterfeit debit or credit card. In most cases, AVS mismatches can be resolved by contacting the card issuer and updating the billing address on file.

Can you check if an address is valid? ›

USPS Address Verification validates and corrects US mailing addresses following the USPS Coding Accuracy Support System (CASS) standards. Address verification against the USPS database confirms whether the address is mailable, reduces mailing costs, decreases lost/returned mail, and speeds up delivery.

What is address verification API? ›

The Address Validation API is a service that accepts an address. It identifies address components and validates them. It also standardizes the address for mailing and finds the best known latitude/longitude coordinates for it.

How do banks verify address? ›

Utility bills (electricity, water, gas, etc.) Tax bills. Bank statements. Credit card statements.

What is the difference between address validation and verification? ›

What is the difference between Address Validation and Address Verification? Address Verification goes beyond just validating that an address exists; it determines that an address is deliverable by comparing it against third party reference data (such as the USPS) and involves address correction when possible.

What are some examples of verification? ›

Activities performed in the normal course of software development such as requirements reviews, design reviews, unit testing, static tests, and build audits are all examples of verification.

What are examples of security verification? ›

Common examples include driver's licenses, passports, birth certificates, Social Security cards, and other government IDs.

Videos

1. Etherscan.io Tutorial: How to Check Ethereum Transactions & ETH Wallet
(Crypto Mining)
2. How to send and sign a message on the blockchain with your wallet
(ZenGo Wallet)
3. How to CONNECT METAMASK to ETHERSCAN TOKEN APPROVAL?
(mrhackio)
4. How To Revoke Access Via Etherscan & Avoid The OpenSea Exploit
(AlphaMint)
5. How To Use and Read Etherscan In 10 Minutes (Etherscan 101)
(decryptoverse)
6. How To Connect Metamask To Etherscan
(MrRaccoon)

References

Top Articles
Latest Posts
Article information

Author: Carlyn Walter

Last Updated: 09/13/2023

Views: 5470

Rating: 5 / 5 (50 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Carlyn Walter

Birthday: 1996-01-03

Address: Suite 452 40815 Denyse Extensions, Sengermouth, OR 42374

Phone: +8501809515404

Job: Manufacturing Technician

Hobby: Table tennis, Archery, Vacation, Metal detecting, Yo-yoing, Crocheting, Creative writing

Introduction: My name is Carlyn Walter, I am a lively, glamorous, healthy, clean, powerful, calm, combative person who loves writing and wants to share my knowledge and understanding with you.