Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
OptimisticSwitchboard
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "./SwitchboardBase.sol"; /** * @title OptimisticSwitchboard * @notice A contract that extends the SwitchboardBase contract and implements the * allowPacket and fee getter functions. */ contract OptimisticSwitchboard is SwitchboardBase { /** * @notice Creates an OptimisticSwitchboard instance with the specified parameters. * @param owner_ The address of the contract owner. * @param socket_ The address of the socket contract. * @param chainSlug_ The chain slug. * @param timeoutInSeconds_ The timeout period in seconds after which proposals become valid if not tripped. * @param signatureVerifier_ The address of the signature verifier contract */ constructor( address owner_, address socket_, uint32 chainSlug_, uint256 timeoutInSeconds_, ISignatureVerifier signatureVerifier_ ) AccessControlExtended(owner_) SwitchboardBase( socket_, chainSlug_, timeoutInSeconds_, signatureVerifier_ ) {} /** * @inheritdoc ISwitchboard */ function allowPacket( bytes32, bytes32 packetId_, uint256 proposalCount_, uint32 srcChainSlug_, uint256 proposeTime_ ) external view override returns (bool) { uint64 packetCount = uint64(uint256(packetId_)); // any relevant trips triggered or invalid packet count. if ( isGlobalTipped || isPathTripped[srcChainSlug_] || isProposalTripped[packetId_][proposalCount_] || packetCount < initialPacketCount[srcChainSlug_] ) return false; // time to detect and call trip is not over. if (block.timestamp - proposeTime_ < timeoutInSeconds) return false; // enough time has passed without trip return true; } /** * @inheritdoc ISwitchboard */ function setFees( uint256 nonce_, uint32 dstChainSlug_, uint128 switchboardFees_, uint128 verificationOverheadFees_, bytes calldata signature_ ) external override { address feesUpdater = signatureVerifier__.recoverSigner( keccak256( abi.encode( FEES_UPDATE_SIG_IDENTIFIER, address(this), chainSlug, dstChainSlug_, nonce_, switchboardFees_, verificationOverheadFees_ ) ), signature_ ); _checkRoleWithSlug(FEES_UPDATER_ROLE, dstChainSlug_, feesUpdater); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[feesUpdater]++) revert InvalidNonce(); } Fees storage fee = fees[dstChainSlug_]; fee.verificationOverheadFees = verificationOverheadFees_; fee.switchboardFees = switchboardFees_; emit SwitchboardFeesSet(dstChainSlug_, fee); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; /** * @title Execution Manager Interface * @dev This interface defines the functions for managing and executing transactions on external chains * @dev It is also responsible for collecting all the socket fees, which can then be pulled by others */ interface IExecutionManager { struct ExecutionFeesParam { // for calculating perGasCost * gasLimit uint80 perGasCost; // for calculating cost for executing payload (needed for rollups) uint80 perByteCost; // additional cost (differs based on chain) uint80 overhead; } /** * @notice Returns the executor of the packed message and whether the executor is authorized * @param packedMessage The message packed with payload, fees and config * @param sig The signature of the message * @return The address of the executor and a boolean indicating if the executor is authorized */ function isExecutor( bytes32 packedMessage, bytes memory sig ) external view returns (address, bool); /** * @notice Pays the fees for executing a transaction on the external chain * @dev This function is payable and assumes the socket is going to send correct amount of fees. * @param minMsgGasLimit_ The minimum gas limit for the transaction * @param payloadSize_ The payload size in bytes * @param executionParams_ Extra params for execution * @param transmissionParams_ Extra params for transmission * @param siblingChainSlug_ Sibling chain identifier * @param switchboardFees_ fee charged by switchboard for processing transaction * @param verificationOverheadFees_ fee charged for verifying transaction * @param transmitManager_ The transmitManager address * @param switchboard_ The switchboard address * @param maxPacketLength_ The maxPacketLength for the capacitor */ function payAndCheckFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, bytes32 transmissionParams_, uint32 siblingChainSlug_, uint128 switchboardFees_, uint128 verificationOverheadFees_, address transmitManager_, address switchboard_, uint256 maxPacketLength_ ) external payable returns (uint128, uint128); /** * @notice Returns the minimum fees required for executing a transaction on the external chain * @param minMsgGasLimit_ minMsgGasLimit_ * @param siblingChainSlug_ The destination slug * @return The minimum fees required for executing the transaction */ function getMinFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, uint32 siblingChainSlug_ ) external view returns (uint128); /** * @notice function for getting the minimum fees required for executing and transmitting a cross-chain transaction * @dev this function is called at source to calculate the execution cost. * @param payloadSize_ byte length of payload. Currently only used to check max length, later on will be used for fees calculation. * @param executionParams_ Can be used for providing extra information. Currently used for msgValue * @param siblingChainSlug_ Sibling chain identifier * @return minExecutionFee : Minimum fees required for executing the transaction */ function getExecutionTransmissionMinFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, bytes32 transmissionParams_, uint32 siblingChainSlug_, address transmitManager_ ) external view returns (uint128, uint128); /** * @notice Updates the execution fees for an executor and message ID * @param executor The executor address * @param executionFees The execution fees to update * @param msgId The ID of the message */ function updateExecutionFees( address executor, uint128 executionFees, bytes32 msgId ) external; /** * @notice updates the transmission fee * @param remoteChainSlug_ sibling chain identifier * @param transmitMinFees_ transmission fees collected */ function setTransmissionMinFees( uint32 remoteChainSlug_, uint128 transmitMinFees_ ) external; /** * @notice sets the minimum execution fees required for executing at `siblingChainSlug_` * @dev this function currently sets the price for a constant msg gas limit and payload size * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param executionFees_ total fees where price in destination native token is converted to source native tokens * @param signature_ signature of fee updater */ function setExecutionFees( uint256 nonce_, uint32 siblingChainSlug_, ExecutionFeesParam calldata executionFees_, bytes calldata signature_ ) external; /** * @notice sets the min limit for msg value for `siblingChainSlug_` * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param msgValueMinThreshold_ min msg value * @param signature_ signature of fee updater */ function setMsgValueMinThreshold( uint256 nonce_, uint32 siblingChainSlug_, uint256 msgValueMinThreshold_, bytes calldata signature_ ) external; /** * @notice sets the max limit for msg value for `siblingChainSlug_` * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param msgValueMaxThreshold_ max msg value * @param signature_ signature of fee updater */ function setMsgValueMaxThreshold( uint256 nonce_, uint32 siblingChainSlug_, uint256 msgValueMaxThreshold_, bytes calldata signature_ ) external; /** * @notice sets the relative token price for `siblingChainSlug_` * @dev this function is expected to be called frequently to match the original prices * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param relativeNativeTokenPrice_ relative price * @param signature_ signature of fee updater */ function setRelativeNativeTokenPrice( uint256 nonce_, uint32 siblingChainSlug_, uint256 relativeNativeTokenPrice_, bytes calldata signature_ ) external; /** * @notice called by socket while executing message to validate if the msg value provided is enough * @param executionParams_ a bytes32 string where first byte gives param type (if value is 0 or not) * and remaining bytes give the msg value needed * @param msgValue_ msg.value to be sent with inbound */ function verifyParams( bytes32 executionParams_, uint256 msgValue_ ) external view; /** * @notice withdraws switchboard fees from contract * @param siblingChainSlug_ withdraw fees corresponding to this slug * @param amount_ withdraw amount */ function withdrawSwitchboardFees( uint32 siblingChainSlug_, address switchboard_, uint128 amount_ ) external; /** * @dev this function gets the transmitManager address from the socket contract. If it is ever upgraded in socket, * @dev remove the fees from executionManager first, and then upgrade address at socket. * @notice withdraws transmission fees from contract * @param siblingChainSlug_ withdraw fees corresponding to this slug * @param amount_ withdraw amount */ function withdrawTransmissionFees( uint32 siblingChainSlug_, uint128 amount_ ) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; /** * @title Signature Verifier * @notice Verifies the signatures and returns the address of signer recovered from the input signature or digest. */ interface ISignatureVerifier { /** * @notice returns the address of signer recovered from input signature and digest */ function recoverSigner( bytes32 digest_, bytes memory signature_ ) external pure returns (address signer); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "./ITransmitManager.sol"; import "./IExecutionManager.sol"; /** * @title ISocket * @notice An interface for a cross-chain communication contract * @dev This interface provides methods for transmitting and executing messages between chains, * connecting a plug to a remote chain and setting up switchboards for the message transmission * This interface also emits events for important operations such as message transmission, execution status, * and plug connection */ interface ISocket { /** * @notice A struct containing fees required for message transmission and execution * @param transmissionFees fees needed for transmission * @param switchboardFees fees needed by switchboard * @param executionFee fees needed for execution */ struct Fees { uint128 transmissionFees; uint128 executionFee; uint128 switchboardFees; } /** * @title MessageDetails * @dev This struct defines the details of a message to be executed in a Decapacitor contract. */ struct MessageDetails { // A unique identifier for the message. bytes32 msgId; // The fee to be paid for executing the message. uint256 executionFee; // The min amount of gas that can be used to execute the message. uint256 minMsgGasLimit; // The extra params which might provide msg value and additional info needed for message exec bytes32 executionParams; // The payload data to be executed in the message. bytes payload; } /** * @title ExecutionDetails * @dev This struct defines the execution details */ struct ExecutionDetails { // packet id bytes32 packetId; // proposal count uint256 proposalCount; // gas limit needed to execute inbound uint256 executionGasLimit; // proof data required by the Decapacitor contract to verify the message's authenticity bytes decapacitorProof; // signature of executor bytes signature; } /** * @notice emits the status of message after inbound call * @param msgId msg id which is executed */ event ExecutionSuccess(bytes32 msgId); /** * @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, uint32 siblingChainSlug, address siblingPlug, address inboundSwitchboard, address outboundSwitchboard, address capacitor, address decapacitor ); /** * @notice registers a message * @dev Packs the message and includes it in a packet with capacitor * @param remoteChainSlug_ the remote chain slug * @param minMsgGasLimit_ the gas limit needed to execute the payload on remote * @param payload_ the data which is needed by plug at inbound call on remote */ function outbound( uint32 remoteChainSlug_, uint256 minMsgGasLimit_, bytes32 executionParams_, bytes32 transmissionParams_, bytes calldata payload_ ) external payable returns (bytes32 msgId); /** * @notice executes a message * @param executionDetails_ the packet details, proof and signature needed for message execution * @param messageDetails_ the message details */ function execute( ISocket.ExecutionDetails calldata executionDetails_, ISocket.MessageDetails calldata messageDetails_ ) external payable; /** * @notice seals data in capacitor for specific batchSize * @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 switchboard_ The address of switchboard for which this packet is proposed * @param signature_ signed Data needed for verification */ function proposeForSwitchboard( bytes32 packetId_, bytes32 root_, address switchboard_, bytes calldata signature_ ) external payable; /** * @notice sets the config specific to the plug * @param siblingChainSlug_ the sibling chain slug * @param siblingPlug_ address of plug present at sibling chain to call inbound * @param inboundSwitchboard_ the address of switchboard to use for receiving messages * @param outboundSwitchboard_ the address of switchboard to use for sending messages */ function connect( uint32 siblingChainSlug_, address siblingPlug_, address inboundSwitchboard_, address outboundSwitchboard_ ) external; /** * @notice deploy capacitor and decapacitor for a switchboard with a specified max packet length, sibling chain slug, and capacitor type. * @param siblingChainSlug_ The slug of the sibling chain that the switchboard is registered with. * @param maxPacketLength_ The maximum length of a packet allowed by the switchboard. * @param capacitorType_ The type of capacitor that the switchboard uses. * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` */ function registerSwitchboardForSibling( uint32 siblingChainSlug_, uint256 maxPacketLength_, uint256 capacitorType_, address siblingSwitchboard_ ) external returns (address capacitor, address decapacitor); /** * @notice Emits the sibling switchboard for given `siblingChainSlug_`. * @dev This function is expected to be only called by switchboard. * @dev the event emitted is tracked by transmitters to decide which switchboard a packet should be proposed on * @param siblingChainSlug_ The slug of the sibling chain * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` */ function useSiblingSwitchboard( uint32 siblingChainSlug_, address siblingSwitchboard_ ) external; /** * @notice Retrieves the packet id roots for a specified packet id. * @param packetId_ The packet id for which to retrieve the root. * @param proposalCount_ The proposal id for packetId_ for which to retrieve the root. * @param switchboard_ The address of switchboard for which this packet is proposed * @return The packet id roots for the specified packet id. */ function packetIdRoots( bytes32 packetId_, uint256 proposalCount_, address switchboard_ ) external view returns (bytes32); /** * @notice Retrieves the latest proposalCount for a packet id. * @return The proposal count for the specified packet id. */ function proposalCount(bytes32 packetId_) external view returns (uint256); /** * @notice Retrieves the minimum fees required for a message with a specified gas limit and destination chain. * @param minMsgGasLimit_ The gas limit of the message. * @param remoteChainSlug_ The slug of the destination chain for the message. * @param plug_ The address of the plug through which the message is sent. * @return totalFees The minimum fees required for the specified message. */ function getMinFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, bytes32 transmissionParams_, uint32 remoteChainSlug_, address plug_ ) external view returns (uint256 totalFees); /// return instance of transmit manager function transmitManager__() external view returns (ITransmitManager); /// return instance of execution manager function executionManager__() external view returns (IExecutionManager); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; /** * @title ISwitchboard * @dev The interface for a switchboard contract that is responsible for verification of packets between * different blockchain networks. */ interface ISwitchboard { /** * @notice Registers itself in Socket for given `siblingChainSlug_`. * @dev This function is expected to be only called by admin as it handles the capacitor config for given chain * @param siblingChainSlug_ The slug of the sibling chain to register switchboard with. * @param maxPacketLength_ The maximum length of a packet allowed by the switchboard. * @param capacitorType_ The type of capacitor that the switchboard uses. * @param initialPacketCount_ The packet count at the time of registering switchboard. Packets with packet count below this won't be allowed * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` */ function registerSiblingSlug( uint32 siblingChainSlug_, uint256 maxPacketLength_, uint256 capacitorType_, uint256 initialPacketCount_, address siblingSwitchboard_ ) external; /** * @notice Updates the sibling switchboard for given `siblingChainSlug_`. * @dev This function is expected to be only called by admin * @param siblingChainSlug_ The slug of the sibling chain to register switchboard with. * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` */ function updateSibling( uint32 siblingChainSlug_, address siblingSwitchboard_ ) external; /** * @notice Checks if a packet can be allowed to go through the switchboard. * @param root the packet root. * @param packetId The unique identifier for the packet. * @param proposalCount The unique identifier for a proposal for the packet. * @param srcChainSlug The unique identifier for the source chain of the packet. * @param proposeTime The time when the packet was proposed. * @return A boolean indicating whether the packet is allowed to go through the switchboard or not. */ function allowPacket( bytes32 root, bytes32 packetId, uint256 proposalCount, uint32 srcChainSlug, uint256 proposeTime ) external view returns (bool); /** * @notice Retrieves the minimum fees required for the destination chain to process the packet. * @param dstChainSlug the unique identifier for the destination chain of the packet. * @return switchboardFee the switchboard fee required for the destination chain to process the packet. * @return verificationOverheadFees the verification fee required for the destination chain to process the packet. */ function getMinFees( uint32 dstChainSlug ) external view returns (uint128 switchboardFee, uint128 verificationOverheadFees); /** * @notice Receives the fees for processing of packet. * @param siblingChainSlug_ the chain slug of the sibling chain. */ function receiveFees(uint32 siblingChainSlug_) external payable; /** * @notice Sets the minimum fees required for the destination chain to process the packet. * @param nonce_ the nonce of fee Updater to avoid replay. * @param dstChainSlug_ the unique identifier for the destination chain. * @param switchboardFees_ the switchboard fee required for the destination chain to process the packet. * @param verificationOverheadFees_ the verification fee required for the destination chain to process the packet. * @param signature_ the signature of the request. * @dev not important to override in all switchboards */ function setFees( uint256 nonce_, uint32 dstChainSlug_, uint128 switchboardFees_, uint128 verificationOverheadFees_, bytes calldata signature_ ) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; /** * @title ITransmitManager * @dev The interface for a transmit manager contract */ interface ITransmitManager { /** * @notice Checks if a given transmitter is authorized to send transactions to the destination chain. * @param siblingSlug The unique identifier for the sibling chain. * @param digest The digest of the message being signed. * @param signature The signature of the message being signed. * @return The address of the transmitter and a boolean indicating whether the transmitter is authorized or not. */ function checkTransmitter( uint32 siblingSlug, bytes32 digest, bytes calldata signature ) external view returns (address, bool); /** * @notice sets the transmission fee needed to transmit message to given `siblingSlug_` * @dev recovered address should add have feeUpdater role for `siblingSlug_` * @param nonce_ The incremental nonce to prevent signature replay * @param siblingSlug_ sibling id for which fee updater is registered * @param transmissionFees_ digest which is signed by transmitter * @param signature_ signature */ function setTransmissionFees( uint256 nonce_, uint32 siblingSlug_, uint128 transmissionFees_, bytes calldata signature_ ) external; /** * @notice receives fees from Execution manager * @dev this function can be used to keep track of fees received for each slug * @param siblingSlug_ sibling id for which fee updater is registered */ function receiveFees(uint32 siblingSlug_) external payable; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "lib/solmate/src/utils/SafeTransferLib.sol"; error ZeroAddress(); /** * @title RescueFundsLib * @dev A library that provides a function to rescue funds from a contract. */ library RescueFundsLib { /** * @dev The address used to identify ETH. */ address public constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); /** * @dev thrown when the given token address don't have any code */ error InvalidTokenAddress(); /** * @dev Rescues funds from a contract. * @param token_ The address of the token contract. * @param rescueTo_ The address of the user. * @param amount_ The amount of tokens to be rescued. */ function rescueFunds( address token_, address rescueTo_, uint256 amount_ ) internal { if (rescueTo_ == address(0)) revert ZeroAddress(); if (token_ == ETH_ADDRESS) { SafeTransferLib.safeTransferETH(rescueTo_, amount_); } else { if (token_.code.length == 0) revert InvalidTokenAddress(); SafeTransferLib.safeTransfer(ERC20(token_), rescueTo_, amount_); } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "../../interfaces/ISocket.sol"; import "../../interfaces/ISwitchboard.sol"; import "../../interfaces/ISignatureVerifier.sol"; import "../../utils/AccessControlExtended.sol"; import "../../libraries/RescueFundsLib.sol"; import {GOVERNANCE_ROLE, WITHDRAW_ROLE, RESCUE_ROLE, TRIP_ROLE, UN_TRIP_ROLE, WATCHER_ROLE, FEES_UPDATER_ROLE} from "../../utils/AccessRoles.sol"; import {TRIP_PATH_SIG_IDENTIFIER, TRIP_GLOBAL_SIG_IDENTIFIER, TRIP_PROPOSAL_SIG_IDENTIFIER, UN_TRIP_PATH_SIG_IDENTIFIER, UN_TRIP_GLOBAL_SIG_IDENTIFIER, FEES_UPDATE_SIG_IDENTIFIER} from "../../utils/SigIdentifiers.sol"; abstract contract SwitchboardBase is ISwitchboard, AccessControlExtended { // signature verifier contract ISignatureVerifier public immutable signatureVerifier__; // socket contract ISocket public immutable socket__; // chain slug of deployed chain uint32 public immutable chainSlug; // timeout after which packets become valid // optimistic switchboard: this is the wait time to validate packet // fast switchboard: this makes packets valid even if all watchers have not attested // used to make the system work when watchers are inactive due to infra etc problems // this is only applicable if none of the trips are triggered uint256 public immutable timeoutInSeconds; // variable to pause the switchboard completely, to be used only in case of smart contract bug // trip can be done by TRIP_ROLE holders // untrip can be done by UN_TRIP_ROLE holders bool public isGlobalTipped; // pause all proposals coming from given chain. // to be used if a transmitter has gone rogue and needs to be kicked to resume normal functioning // trip can be done by WATCHER_ROLE holders // untrip can be done by UN_TRIP_ROLE holders // sourceChain => isPaused mapping(uint32 => bool) public isPathTripped; // block execution of single proposal // to be used if transmitter proposes wrong packet root single time // trip can be done by WATCHER_ROLE holders // untrip not possible, but same root can be proposed again at next proposalCount // isProposalTripped(packetId => proposalCount => isTripped) mapping(bytes32 => mapping(uint256 => bool)) public isProposalTripped; // incrementing nonce for each signer // watcher => nextNonce mapping(address => uint256) public nextNonce; struct Fees { uint128 switchboardFees; // Fees paid to Switchboard per packet uint128 verificationOverheadFees; // Fees paid to executor per message } // destinationChainSlug => fees-struct with verificationOverheadFees and switchboardFees mapping(uint32 => Fees) public fees; // destinationChainSlug => initialPacketCount - packets with packetCount after this will be accepted at the switchboard. // This is to prevent attacks with sending messages for chain slugs before the switchboard is registered for them. mapping(uint32 => uint256) public initialPacketCount; /** * @dev Emitted when global trip status changes * @param isGlobalTipped New trip status of the contract */ event GlobalTripChanged(bool isGlobalTipped); /** * @dev Emitted when path trip status changes * @param srcChainSlug Chain slug of the source chain * @param isPathTripped New trip status of the path */ event PathTripChanged(uint32 srcChainSlug, bool isPathTripped); /** * @dev Emitted when a proposal for a packetId is tripped * @param packetId packetId of packet * @param proposalCount proposalCount being tripped */ event ProposalTripped(bytes32 packetId, uint256 proposalCount); /** * @dev Emitted when a fees is set for switchboard * @param siblingChainSlug Chain slug of the sibling chain * @param fees Fees struct with verificationOverheadFees and switchboardFees */ event SwitchboardFeesSet(uint32 siblingChainSlug, Fees fees); // Error hit when a signature with unexpected nonce is received error InvalidNonce(); // Error hit when tx from invalid ExecutionManager is received error OnlyExecutionManager(); /** * @dev Constructor of SwitchboardBase * @param socket_ Address of the socket contract * @param chainSlug_ Chain slug of deployment chain * @param timeoutInSeconds_ Time after which proposals become valid if not tripped * @param signatureVerifier_ signatureVerifier_ contract */ constructor( address socket_, uint32 chainSlug_, uint256 timeoutInSeconds_, ISignatureVerifier signatureVerifier_ ) { socket__ = ISocket(socket_); chainSlug = chainSlug_; timeoutInSeconds = timeoutInSeconds_; signatureVerifier__ = signatureVerifier_; } /** * @inheritdoc ISwitchboard */ function getMinFees( uint32 dstChainSlug_ ) external view override returns (uint128, uint128) { Fees memory minFees = fees[dstChainSlug_]; return (minFees.switchboardFees, minFees.verificationOverheadFees); } /** * @inheritdoc ISwitchboard */ function registerSiblingSlug( uint32 siblingChainSlug_, uint256 maxPacketLength_, uint256 capacitorType_, uint256 initialPacketCount_, address siblingSwitchboard_ ) external override onlyRole(GOVERNANCE_ROLE) { initialPacketCount[siblingChainSlug_] = initialPacketCount_; socket__.registerSwitchboardForSibling( siblingChainSlug_, maxPacketLength_, capacitorType_, siblingSwitchboard_ ); } /** * @notice Signals sibling switchboard for given `siblingChainSlug_`. * @dev This function is expected to be only called by governance * @param siblingChainSlug_ The slug of the sibling chain whos switchboard is being connected. * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` */ function updateSibling( uint32 siblingChainSlug_, address siblingSwitchboard_ ) external onlyRole(GOVERNANCE_ROLE) { socket__.useSiblingSwitchboard(siblingChainSlug_, siblingSwitchboard_); } /** * @notice Pauses this switchboard completely. To be used in case of contract bug. * @param nonce_ The nonce used for signature. * @param signature_ The signature provided to validate the trip. */ function tripGlobal(uint256 nonce_, bytes memory signature_) external { address tripper = signatureVerifier__.recoverSigner( // it includes trip status at the end keccak256( abi.encode( TRIP_GLOBAL_SIG_IDENTIFIER, address(this), chainSlug, nonce_, true ) ), signature_ ); _checkRole(TRIP_ROLE, tripper); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[tripper]++) revert InvalidNonce(); } isGlobalTipped = true; emit GlobalTripChanged(true); } /** * @notice Pauses a path. To be used when a transmitter goes rogue and needs to be kicked. * @param nonce_ The nonce used for signature. * @param srcChainSlug_ The source chain slug of the path to be paused. * @param signature_ The signature provided to validate the trip. */ function tripPath( uint256 nonce_, uint32 srcChainSlug_, bytes memory signature_ ) external { address watcher = signatureVerifier__.recoverSigner( // it includes trip status at the end keccak256( abi.encode( TRIP_PATH_SIG_IDENTIFIER, address(this), srcChainSlug_, chainSlug, nonce_, true ) ), signature_ ); _checkRoleWithSlug(WATCHER_ROLE, srcChainSlug_, watcher); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[watcher]++) revert InvalidNonce(); } //source chain based tripping isPathTripped[srcChainSlug_] = true; emit PathTripChanged(srcChainSlug_, true); } /** * @notice Pauses a particular proposal of a packet. To be used if transmitter proposes wrong root. * @param nonce_ The nonce used for signature. * @param packetId_ The ID of the packet. * @param proposalCount_ The count of the proposal to be paused. * @param signature_ The signature provided to validate the trip. */ function tripProposal( uint256 nonce_, bytes32 packetId_, uint256 proposalCount_, bytes memory signature_ ) external { uint32 srcChainSlug = uint32(uint256(packetId_) >> 224); address watcher = signatureVerifier__.recoverSigner( keccak256( abi.encode( TRIP_PROPOSAL_SIG_IDENTIFIER, address(this), srcChainSlug, chainSlug, nonce_, packetId_, proposalCount_ ) ), signature_ ); _checkRoleWithSlug(WATCHER_ROLE, srcChainSlug, watcher); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[watcher]++) revert InvalidNonce(); } isProposalTripped[packetId_][proposalCount_] = true; emit ProposalTripped(packetId_, proposalCount_); } /** * @notice Unpauses a path. To be used after bad transmitter has been kicked from system. * @param nonce_ The nonce used for the signature. * @param srcChainSlug_ The source chain slug of the path to be unpaused. * @param signature_ The signature provided to validate the un trip. */ function unTripPath( uint256 nonce_, uint32 srcChainSlug_, bytes memory signature_ ) external { address unTripper = signatureVerifier__.recoverSigner( // it includes trip status at the end keccak256( abi.encode( UN_TRIP_PATH_SIG_IDENTIFIER, address(this), srcChainSlug_, chainSlug, nonce_, false ) ), signature_ ); _checkRole(UN_TRIP_ROLE, unTripper); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[unTripper]++) revert InvalidNonce(); } isPathTripped[srcChainSlug_] = false; emit PathTripChanged(srcChainSlug_, false); } /** * @notice Unpauses global execution. To be used if contract bug is addressed. * @param nonce_ The nonce used for the signature. * @param signature_ The signature provided to validate the un trip. */ function unTrip(uint256 nonce_, bytes memory signature_) external { address unTripper = signatureVerifier__.recoverSigner( // it includes trip status at the end keccak256( abi.encode( UN_TRIP_GLOBAL_SIG_IDENTIFIER, address(this), chainSlug, nonce_, false ) ), signature_ ); _checkRole(UN_TRIP_ROLE, unTripper); // Nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[unTripper]++) revert InvalidNonce(); } isGlobalTipped = false; emit GlobalTripChanged(false); } /** * @notice Withdraw fees from the contract to an account. * @param withdrawTo_ The address where we should send the fees. */ function withdrawFees( address withdrawTo_ ) external onlyRole(WITHDRAW_ROLE) { if (withdrawTo_ == address(0)) revert ZeroAddress(); SafeTransferLib.safeTransferETH(withdrawTo_, address(this).balance); } /** * @notice Rescues funds from the contract if they are locked by mistake. * @param token_ The address of the token contract. * @param rescueTo_ The address where rescued tokens need to be sent. * @param amount_ The amount of tokens to be rescued. */ function rescueFunds( address token_, address rescueTo_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, rescueTo_, amount_); } /** * @inheritdoc ISwitchboard * @dev Receiving only allowed from execution manager * @dev Need to receive fees before change in case execution manager * is being updated on socket. */ function receiveFees(uint32) external payable override { if (msg.sender != address(socket__.executionManager__())) revert OnlyExecutionManager(); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "./Ownable.sol"; /** * @title AccessControl * @dev This abstract contract implements access control mechanism based on roles. * Each role can have one or more addresses associated with it, which are granted * permission to execute functions with the onlyRole modifier. */ abstract contract AccessControl is Ownable { /** * @dev A mapping of roles to a mapping of addresses to boolean values indicating whether or not they have the role. */ mapping(bytes32 => mapping(address => bool)) private _permits; /** * @dev Emitted when a role is granted to an address. */ event RoleGranted(bytes32 indexed role, address indexed grantee); /** * @dev Emitted when a role is revoked from an address. */ event RoleRevoked(bytes32 indexed role, address indexed revokee); /** * @dev Error message thrown when an address does not have permission to execute a function with onlyRole modifier. */ error NoPermit(bytes32 role); /** * @dev Constructor that sets the owner of the contract. */ constructor(address owner_) Ownable(owner_) {} /** * @dev Modifier that restricts access to addresses having roles * Throws an error if the caller do not have permit */ modifier onlyRole(bytes32 role) { if (!_permits[role][msg.sender]) revert NoPermit(role); _; } /** * @dev Checks and reverts if an address do not have a specific role. * @param role_ The role to check. * @param address_ The address to check. */ function _checkRole(bytes32 role_, address address_) internal virtual { if (!_hasRole(role_, address_)) revert NoPermit(role_); } /** * @dev Grants a role to a given address. * @param role_ The role to grant. * @param grantee_ The address to grant the role to. * Emits a RoleGranted event. * Can only be called by the owner of the contract. */ function grantRole( bytes32 role_, address grantee_ ) external virtual onlyOwner { _grantRole(role_, grantee_); } /** * @dev Revokes a role from a given address. * @param role_ The role to revoke. * @param revokee_ The address to revoke the role from. * Emits a RoleRevoked event. * Can only be called by the owner of the contract. */ function revokeRole( bytes32 role_, address revokee_ ) external virtual onlyOwner { _revokeRole(role_, revokee_); } /** * @dev Internal function to grant a role to a given address. * @param role_ The role to grant. * @param grantee_ The address to grant the role to. * Emits a RoleGranted event. */ function _grantRole(bytes32 role_, address grantee_) internal { _permits[role_][grantee_] = true; emit RoleGranted(role_, grantee_); } /** * @dev Internal function to revoke a role from a given address. * @param role_ The role to revoke. * @param revokee_ The address to revoke the role from. * Emits a RoleRevoked event. */ function _revokeRole(bytes32 role_, address revokee_) internal { _permits[role_][revokee_] = false; emit RoleRevoked(role_, revokee_); } /** * @dev Checks whether an address has a specific role. * @param role_ The role to check. * @param address_ The address to check. * @return A boolean value indicating whether or not the address has the role. */ 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_]; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; import "./AccessControl.sol"; /** * @title AccessControlExtended * @dev This contract extends the functionality of the AccessControl contract by adding * the ability to grant and revoke roles based on a combination of role name and a chain slug. * It also provides batch operations for granting and revoking roles. */ contract AccessControlExtended is AccessControl { /** * @dev Constructor that sets the owner of the contract. */ constructor(address owner_) AccessControl(owner_) {} /** * @dev thrown when array lengths are not equal */ error UnequalArrayLengths(); /** * @dev Checks if an address has the role. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param address_ The address to be granted the role. */ function _checkRoleWithSlug( bytes32 roleName_, uint256 chainSlug_, address address_ ) internal virtual { bytes32 roleHash = keccak256(abi.encode(roleName_, chainSlug_)); if (!_hasRole(roleHash, address_)) revert NoPermit(roleHash); } /** * @dev Grants a role to an address based on the role name and chain slug. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param grantee_ The address to be granted the role. */ function grantRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) external virtual onlyOwner { _grantRoleWithSlug(roleName_, chainSlug_, grantee_); } /** * @dev Grants multiple roles to multiple addresses in batch. * @param roleNames_ The names of the roles to grant. * @param slugs_ The slugs for chain specific roles. For roles which are not chain-specific, we can use slug = 0 * @param grantees_ The addresses to be granted the roles. */ function grantBatchRole( bytes32[] calldata roleNames_, uint32[] calldata slugs_, address[] calldata grantees_ ) external virtual onlyOwner { if ( roleNames_.length != grantees_.length || roleNames_.length != slugs_.length ) revert UnequalArrayLengths(); uint256 totalRoles = roleNames_.length; for (uint256 index = 0; index < totalRoles; ) { if (slugs_[index] > 0) _grantRoleWithSlug( roleNames_[index], slugs_[index], grantees_[index] ); else _grantRole(roleNames_[index], grantees_[index]); // inputs are controlled by owner unchecked { ++index; } } } /** * @dev Revokes multiple roles from multiple addresses in batch. * @param roleNames_ The names of the roles to revoke. * @param slugs_ The slugs for chain specific roles. For roles which are not chain-specific, we can use slug = 0 * @param grantees_ The addresses to be revoked the roles. */ function revokeBatchRole( bytes32[] calldata roleNames_, uint32[] calldata slugs_, address[] calldata grantees_ ) external virtual onlyOwner { if ( roleNames_.length != grantees_.length || roleNames_.length != slugs_.length ) revert UnequalArrayLengths(); uint256 totalRoles = roleNames_.length; for (uint256 index = 0; index < totalRoles; ) { if (slugs_[index] > 0) _revokeRoleWithSlug( roleNames_[index], slugs_[index], grantees_[index] ); else _revokeRole(roleNames_[index], grantees_[index]); // inputs are controlled by owner unchecked { ++index; } } } function _grantRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) internal { _grantRole(keccak256(abi.encode(roleName_, chainSlug_)), grantee_); } /** * @dev Checks if an address has a role based on the role name and chain slug. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param address_ The address to check for the role. * @return A boolean indicating whether the address has the specified role. */ function hasRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address address_ ) external view returns (bool) { return _hasRoleWithSlug(roleName_, chainSlug_, address_); } function _hasRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address address_ ) internal view returns (bool) { return _hasRole(keccak256(abi.encode(roleName_, chainSlug_)), address_); } /** * @dev Revokes roles from an address * @param roleName_ The names of the roles to revoke. * @param chainSlug_ The chain slug associated with the role. * @param grantee_ The addresses to be revoked the roles. */ function revokeRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) external virtual onlyOwner { _revokeRoleWithSlug(roleName_, chainSlug_, grantee_); } function _revokeRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address revokee_ ) internal { _revokeRole(keccak256(abi.encode(roleName_, chainSlug_)), revokee_); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; // contains role hashes used in socket dl for various different operations // used to rescue funds bytes32 constant RESCUE_ROLE = keccak256("RESCUE_ROLE"); // used to withdraw fees bytes32 constant WITHDRAW_ROLE = keccak256("WITHDRAW_ROLE"); // used to trip switchboards bytes32 constant TRIP_ROLE = keccak256("TRIP_ROLE"); // used to un trip switchboards bytes32 constant UN_TRIP_ROLE = keccak256("UN_TRIP_ROLE"); // used by governance bytes32 constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); //used by executors which executes message at destination bytes32 constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); // used by transmitters who seal and propose packets in socket bytes32 constant TRANSMITTER_ROLE = keccak256("TRANSMITTER_ROLE"); // used by switchboard watchers who work against transmitters bytes32 constant WATCHER_ROLE = keccak256("WATCHER_ROLE"); // used by fee updaters responsible for updating fees at switchboards, transmit manager and execution manager bytes32 constant FEES_UPDATER_ROLE = keccak256("FEES_UPDATER_ROLE");
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; /** * @title Ownable * @dev The Ownable contract provides a simple way to manage ownership of a contract * and allows for ownership to be transferred to a nominated address. */ abstract contract Ownable { address private _owner; address private _nominee; event OwnerNominated(address indexed nominee); event OwnerClaimed(address indexed claimer); error OnlyOwner(); error OnlyNominee(); /** * @dev Sets the contract's owner to the address that is passed to the constructor. */ constructor(address owner_) { _claimOwner(owner_); } /** * @dev Modifier that restricts access to only the contract's owner. * Throws an error if the caller is not the owner. */ modifier onlyOwner() { if (msg.sender != _owner) revert OnlyOwner(); _; } /** * @dev Returns the current owner of the contract. */ function owner() external view returns (address) { return _owner; } /** * @dev Returns the current nominee for ownership of the contract. */ function nominee() external view returns (address) { return _nominee; } /** * @dev Allows the current owner to nominate a new owner for the contract. * Throws an error if the caller is not the owner. * Emits an `OwnerNominated` event with the address of the nominee. */ function nominateOwner(address nominee_) external { if (msg.sender != _owner) revert OnlyOwner(); _nominee = nominee_; emit OwnerNominated(_nominee); } /** * @dev Allows the nominated owner to claim ownership of the contract. * Throws an error if the caller is not the nominee. * Sets the nominated owner as the new owner of the contract. * Emits an `OwnerClaimed` event with the address of the new owner. */ function claimOwner() external { if (msg.sender != _nominee) revert OnlyNominee(); _claimOwner(msg.sender); } /** * @dev Internal function that sets the owner of the contract to the specified address * and sets the nominee to address(0). */ function _claimOwner(address claimer_) internal { _owner = claimer_; _nominee = address(0); emit OwnerClaimed(claimer_); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.19; // contains unique identifiers which are hashes of strings, they help in making signature digest unique // hence preventing signature replay attacks // default switchboards bytes32 constant TRIP_PATH_SIG_IDENTIFIER = keccak256("TRIP_PATH"); bytes32 constant TRIP_PROPOSAL_SIG_IDENTIFIER = keccak256("TRIP_PROPOSAL"); bytes32 constant TRIP_GLOBAL_SIG_IDENTIFIER = keccak256("TRIP_GLOBAL"); bytes32 constant UN_TRIP_PATH_SIG_IDENTIFIER = keccak256("UN_TRIP_PATH"); bytes32 constant UN_TRIP_GLOBAL_SIG_IDENTIFIER = keccak256("UN_TRIP_GLOBAL"); // native switchboards bytes32 constant TRIP_NATIVE_SIG_IDENTIFIER = keccak256("TRIP_NATIVE"); bytes32 constant UN_TRIP_NATIVE_SIG_IDENTIFIER = keccak256("UN_TRIP_NATIVE"); // value threshold, price and fee updaters bytes32 constant FEES_UPDATE_SIG_IDENTIFIER = keccak256("FEES_UPDATE"); bytes32 constant RELATIVE_NATIVE_TOKEN_PRICE_UPDATE_SIG_IDENTIFIER = keccak256( "RELATIVE_NATIVE_TOKEN_PRICE_UPDATE" ); bytes32 constant MSG_VALUE_MIN_THRESHOLD_SIG_IDENTIFIER = keccak256( "MSG_VALUE_MIN_THRESHOLD_UPDATE" ); bytes32 constant MSG_VALUE_MAX_THRESHOLD_SIG_IDENTIFIER = keccak256( "MSG_VALUE_MAX_THRESHOLD_UPDATE" );
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.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 { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, 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, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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 100 because the length of our calldata totals up like so: 4 + 32 * 3. // 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, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 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), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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"); } function safeApprove( ERC20 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, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. 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, "APPROVE_FAILED"); } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"socket_","type":"address"},{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"uint256","name":"timeoutInSeconds_","type":"uint256"},{"internalType":"contract ISignatureVerifier","name":"signatureVerifier_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NoPermit","type":"error"},{"inputs":[],"name":"OnlyExecutionManager","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"UnequalArrayLengths","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isGlobalTipped","type":"bool"}],"name":"GlobalTripChanged","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":"uint32","name":"srcChainSlug","type":"uint32"},{"indexed":false,"internalType":"bool","name":"isPathTripped","type":"bool"}],"name":"PathTripChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"packetId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"proposalCount","type":"uint256"}],"name":"ProposalTripped","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":"uint32","name":"siblingChainSlug","type":"uint32"},{"components":[{"internalType":"uint128","name":"switchboardFees","type":"uint128"},{"internalType":"uint128","name":"verificationOverheadFees","type":"uint128"}],"indexed":false,"internalType":"struct SwitchboardBase.Fees","name":"fees","type":"tuple"}],"name":"SwitchboardFeesSet","type":"event"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"packetId_","type":"bytes32"},{"internalType":"uint256","name":"proposalCount_","type":"uint256"},{"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":[],"name":"chainSlug","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"fees","outputs":[{"internalType":"uint128","name":"switchboardFees","type":"uint128"},{"internalType":"uint128","name":"verificationOverheadFees","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"dstChainSlug_","type":"uint32"}],"name":"getMinFees","outputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"roleNames_","type":"bytes32[]"},{"internalType":"uint32[]","name":"slugs_","type":"uint32[]"},{"internalType":"address[]","name":"grantees_","type":"address[]"}],"name":"grantBatchRole","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":"bytes32","name":"roleName_","type":"bytes32"},{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"grantRoleWithSlug","outputs":[],"stateMutability":"nonpayable","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":"bytes32","name":"roleName_","type":"bytes32"},{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"address","name":"address_","type":"address"}],"name":"hasRoleWithSlug","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"initialPacketCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isGlobalTipped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"isPathTripped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isProposalTripped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"","type":"uint32"}],"name":"receiveFees","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint256","name":"maxPacketLength_","type":"uint256"},{"internalType":"uint256","name":"capacitorType_","type":"uint256"},{"internalType":"uint256","name":"initialPacketCount_","type":"uint256"},{"internalType":"address","name":"siblingSwitchboard_","type":"address"}],"name":"registerSiblingSlug","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"rescueTo_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"roleNames_","type":"bytes32[]"},{"internalType":"uint32[]","name":"slugs_","type":"uint32[]"},{"internalType":"address[]","name":"grantees_","type":"address[]"}],"name":"revokeBatchRole","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":"bytes32","name":"roleName_","type":"bytes32"},{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"revokeRoleWithSlug","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint32","name":"dstChainSlug_","type":"uint32"},{"internalType":"uint128","name":"switchboardFees_","type":"uint128"},{"internalType":"uint128","name":"verificationOverheadFees_","type":"uint128"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signatureVerifier__","outputs":[{"internalType":"contract ISignatureVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"socket__","outputs":[{"internalType":"contract ISocket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeoutInSeconds","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":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint32","name":"srcChainSlug_","type":"uint32"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"tripPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"bytes32","name":"packetId_","type":"bytes32"},{"internalType":"uint256","name":"proposalCount_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"tripProposal","outputs":[],"stateMutability":"nonpayable","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":"uint32","name":"srcChainSlug_","type":"uint32"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"unTripPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"address","name":"siblingSwitchboard_","type":"address"}],"name":"updateSibling","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"withdrawTo_","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101006040523480156200001257600080fd5b5060405162003113380380620031138339810160408190526200003591620000e2565b83838383888080620000478162000076565b5050506001600160a01b0393841660a05263ffffffff90921660c05260e05216608052506200015e9350505050565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b6001600160a01b0381168114620000df57600080fd5b50565b600080600080600060a08688031215620000fb57600080fd5b85516200010881620000c9565b60208701519095506200011b81620000c9565b604087015190945063ffffffff811681146200013657600080fd5b6060870151608088015191945092506200015081620000c9565b809150509295509295909350565b60805160a05160c05160e051612f0b62000208600039600081816107f2015261107901526000818161062001528181610b61015281816112600152818161149f01528181611acb01528181611cff0152611f840152600081816106b9015281816117ea01528181611934015261199701526000818161074701528181610bae015281816112ad015281816114de01528181611b1801528181611d4c0152611ff20152612f0b6000f3fe6080604052600436106102345760003560e01c80638da5cb5b11610138578063c6a261d2116100b0578063d5b8da731161007f578063ef7b769011610064578063ef7b769014610789578063efec6cd4146107e0578063f22b460e1461081457600080fd5b8063d5b8da7314610735578063ecb974841461076957600080fd5b8063c6a261d2146106a7578063c8779308146106db578063d39a38c1146106f5578063d547741f1461071557600080fd5b8063a9a541b211610107578063b349ba65116100ec578063b349ba651461060e578063b947aac614610657578063be94a4761461068757600080fd5b8063a9a541b2146105c0578063aac96557146105d357600080fd5b80638da5cb5b1461053557806391d14854146105605780639aefe4e014610580578063a0851863146105a057600080fd5b80632f2ff15d116101cb5780635b94db271161019a5780637c1388141161017f5780637c138814146104c857806382987d30146104f557806389ee87551461051557600080fd5b80635b94db27146104885780636ccae054146104a857600080fd5b80632f2ff15d146104035780633bd1adec1461042357806343fa97ca146104385780634c4081801461045857600080fd5b80631e867311116102075780631e8673111461035757806320f99c0a1461037757806325750e37146103c35780632e7eb258146103e357600080fd5b806306da42e0146102395780630cd55abf146102da578063164e68de146103155780631ba8e48414610337575b600080fd5b34801561024557600080fd5b506102ac6102543660046127d8565b63ffffffff166000908152600760209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff808216808552700100000000000000000000000000000000909204169290910182905291565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152015b60405180910390f35b3480156102e657600080fd5b506103076102f5366004612815565b60066020526000908152604090205481565b6040519081526020016102d1565b34801561032157600080fd5b50610335610330366004612815565b610834565b005b34801561034357600080fd5b50610335610352366004612839565b610921565b34801561036357600080fd5b506103356103723660046128c5565b610982565b34801561038357600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102d1565b3480156103cf57600080fd5b506103356103de366004612a39565b610b28565b3480156103ef57600080fd5b506103356103fe366004612839565b610d41565b34801561040f57600080fd5b5061033561041e366004612a80565b610d9d565b34801561042f57600080fd5b50610335610df8565b34801561044457600080fd5b506103356104533660046128c5565b610e54565b34801561046457600080fd5b50610478610473366004612ab0565b610ff0565b60405190151581526020016102d1565b34801561049457600080fd5b506103356104a3366004612815565b6110c1565b3480156104b457600080fd5b506103356104c3366004612af7565b611181565b3480156104d457600080fd5b506103076104e33660046127d8565b60086020526000908152604090205481565b34801561050157600080fd5b50610335610510366004612b38565b61121f565b34801561052157600080fd5b50610335610530366004612b8f565b61145a565b34801561054157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661039e565b34801561056c57600080fd5b5061047861057b366004612a80565b6116ad565b34801561058c57600080fd5b5061033561059b366004612be9565b6116ea565b3480156105ac57600080fd5b506103356105bb366004612c3d565b611856565b6103356105ce3660046127d8565b611995565b3480156105df57600080fd5b506104786105ee366004612c69565b600560209081526000928352604080842090915290825290205460ff1681565b34801561061a57600080fd5b506106427f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016102d1565b34801561066357600080fd5b506104786106723660046127d8565b60046020526000908152604090205460ff1681565b34801561069357600080fd5b506103356106a2366004612b38565b611a8a565b3480156106b357600080fd5b5061039e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106e757600080fd5b506003546104789060ff1681565b34801561070157600080fd5b50610335610710366004612a39565b611cc6565b34801561072157600080fd5b50610335610730366004612a80565b611edb565b34801561074157600080fd5b5061039e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561077557600080fd5b50610478610784366004612839565b611f36565b34801561079557600080fd5b506102ac6107a43660046127d8565b6007602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b3480156107ec57600080fd5b506103077f000000000000000000000000000000000000000000000000000000000000000081565b34801561082057600080fd5b5061033561082f366004612cab565b611f4b565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166108c6576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610913576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d8247612203565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d838383612278565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109d3576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84811415806109e25750848314155b15610a19576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610b1e576000868683818110610a3957610a39612d58565b9050602002016020810190610a4e91906127d8565b63ffffffff161115610ace57610ac9888883818110610a6f57610a6f612d58565b90506020020135878784818110610a8857610a88612d58565b9050602002016020810190610a9d91906127d8565b868685818110610aaf57610aaf612d58565b9050602002016020810190610ac49190612815565b612278565b610b16565b610b16888883818110610ae357610ae3612d58565b90506020020135858584818110610afc57610afc612d58565b9050602002016020810190610b119190612815565b6122b5565b600101610a1d565b5050505050505050565b604080517fa7d456f2444d46f78a51def7ecdf108d72f72da2e10ce355caa5e99a17bed2de6020820152309181019190915263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606082015260808101839052600060a082018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906397aba7f99060c00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401610c0c929190612d87565b602060405180830381865afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d9190612dfb565b9050610c797fb0a81253fa41a5cd7c5885c220c30d519a0d552984e0d69edda03449f69fa6db82612338565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558314610cdf576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055604051600081527f42a60e0dc12250ea896a8f5156f1f3aa4567cd2bd87a72bc097210dc02ec2e05906020015b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d92576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d8383836123a4565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dee576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d82826123e1565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e49576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e5233612467565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ea5576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610eb45750848314155b15610eeb576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610b1e576000868683818110610f0b57610f0b612d58565b9050602002016020810190610f2091906127d8565b63ffffffff161115610fa057610f9b888883818110610f4157610f41612d58565b90506020020135878784818110610f5a57610f5a612d58565b9050602002016020810190610f6f91906127d8565b868685818110610f8157610f81612d58565b9050602002016020810190610f969190612815565b6123a4565b610fe8565b610fe8888883818110610fb557610fb5612d58565b90506020020135858584818110610fce57610fce612d58565b9050602002016020810190610fe39190612815565b6123e1565b600101610eef565b600354600090859060ff168061101b575063ffffffff841660009081526004602052604090205460ff165b8061103f5750600086815260056020908152604080832088845290915290205460ff165b80611068575063ffffffff841660009081526008602052604090205467ffffffffffffffff8216105b156110775760009150506110b8565b7f00000000000000000000000000000000000000000000000000000000000000006110a28442612e18565b10156110b25760009150506110b8565b60019150505b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611112576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661120e576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6112198484846124df565b50505050565b604080517fc9c6c9004cdd87e14f6d7be800064bea944fdafc4e66c833d9da91c10d4ced356020820152309181019190915263ffffffff80841660608301527f000000000000000000000000000000000000000000000000000000000000000016608082015260a08101849052600060c082018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906397aba7f99060e00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161130b929190612d87565b602060405180830381865afa158015611328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134c9190612dfb565b90506113787fb0a81253fa41a5cd7c5885c220c30d519a0d552984e0d69edda03449f69fa6db82612338565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902080546001810190915584146113de576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8316600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051938452908301919091527f43b1a9ba48bea5f72f92aaaf96b18ec134518690384df35d04b1316ca68147e191015b60405180910390a150505050565b604080517f119101cda5c91f869cec4313411657e772bec4c5a184dd6ab7a60859e3d347836020820152309181019190915260e084811c6060830181905263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016608084015260a0830187905260c08301869052908201849052906000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906397aba7f9906101000160405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401611552929190612d87565b602060405180830381865afa15801561156f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115939190612dfb565b90506115c67f2125d1e225cadc5c8296e2cc1f96ee607770bf4a4a16131e62f6819937437c898363ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260409020805460018101909155861461162c576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260056020908152604080832087845282529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581518781529081018690527f876c775784dd569d1ecd6e1a52c87169c22c4e906a138c91a59f451fa0f431b5910160405180910390a1505050505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff16611777576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b63ffffffff861660008181526008602052604090819020859055517f0b04bb410000000000000000000000000000000000000000000000000000000081526004810191909152602481018690526044810185905273ffffffffffffffffffffffffffffffffffffffff83811660648301527f00000000000000000000000000000000000000000000000000000000000000001690630b04bb419060840160408051808303816000875af1158015611832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612e52565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff166118e3576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6040517f81403a0200000000000000000000000000000000000000000000000000000000815263ffffffff8416600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301527f000000000000000000000000000000000000000000000000000000000000000016906381403a0290604401600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16626186f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a239190612dfb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a87576040517f03c377c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b604080517f4623a5d5b82ed238c8ba6e51cffa4ddaf241150d9af32813faab00132f55a4566020820152309181019190915263ffffffff80841660608301527f000000000000000000000000000000000000000000000000000000000000000016608082015260a08101849052600160c082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906397aba7f99060e00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401611b76929190612d87565b602060405180830381865afa158015611b93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb79190612dfb565b9050611bea7f2125d1e225cadc5c8296e2cc1f96ee607770bf4a4a16131e62f6819937437c898463ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558414611c50576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff831660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558251938452908301527f43b1a9ba48bea5f72f92aaaf96b18ec134518690384df35d04b1316ca68147e1910161144c565b604080517fbdfa1b22b053b80e8209cb4421ce6b25b45bb164e02718501cb19a46c4df987c6020820152309181019190915263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016606082015260808101839052600160a082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906397aba7f99060c00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401611daa929190612d87565b602060405180830381865afa158015611dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611deb9190612dfb565b9050611e177fd66a896d5b3e8cd31bfd557e6ebdb5bba4561c7ce6573d5c6716876cbc83dbdd82612338565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558314611e7d576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556040519081527f42a60e0dc12250ea896a8f5156f1f3aa4567cd2bd87a72bc097210dc02ec2e0590602001610d34565b60005473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d82826122b5565b6000611f43848484612662565b949350505050565b604080517ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab66020820152309181019190915263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608301528616608082015260a081018790526fffffffffffffffffffffffffffffffff80861660c0830152841660e082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906397aba7f990610100016040516020818303038152906040528051906020012085856040518463ffffffff1660e01b815260040161205393929190612e81565b602060405180830381865afa158015612070573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120949190612dfb565b90506120c77f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38763ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260409020805460018101909155871461212d576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040908190206fffffffffffffffffffffffffffffffff878116908716700100000000000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000001617815590517faebc3dd035ce00dd026bd60872bea44979224507aa49434f67ec5f9ae924aaa3906121f1908990849063ffffffff929092168252546fffffffffffffffffffffffffffffffff8116602083015260801c604082015260600190565b60405180910390a15050505050505050565b600080600080600085875af190508061097d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016108bd565b61097d838360405160200161229d92919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661091d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018390526024016108bd565b61097d83836040516020016123c992919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff821661252c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016125735761097d8282612203565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036125c4576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d8383836126f0565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611219576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6000611f43848460405160200161268992919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016108bd565b803563ffffffff811681146127d357600080fd5b919050565b6000602082840312156127ea57600080fd5b6116e1826127bf565b73ffffffffffffffffffffffffffffffffffffffff81168114611a8757600080fd5b60006020828403121561282757600080fd5b8135612832816127f3565b9392505050565b60008060006060848603121561284e57600080fd5b8335925061285e602085016127bf565b9150604084013561286e816127f3565b809150509250925092565b60008083601f84011261288b57600080fd5b50813567ffffffffffffffff8111156128a357600080fd5b6020830191508360208260051b85010111156128be57600080fd5b9250929050565b600080600080600080606087890312156128de57600080fd5b863567ffffffffffffffff808211156128f657600080fd5b6129028a838b01612879565b9098509650602089013591508082111561291b57600080fd5b6129278a838b01612879565b9096509450604089013591508082111561294057600080fd5b5061294d89828a01612879565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261299f57600080fd5b813567ffffffffffffffff808211156129ba576129ba61295f565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612a0057612a0061295f565b81604052838152866020858801011115612a1957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a4c57600080fd5b82359150602083013567ffffffffffffffff811115612a6a57600080fd5b612a768582860161298e565b9150509250929050565b60008060408385031215612a9357600080fd5b823591506020830135612aa5816127f3565b809150509250929050565b600080600080600060a08688031215612ac857600080fd5b853594506020860135935060408601359250612ae6606087016127bf565b949793965091946080013592915050565b600080600060608486031215612b0c57600080fd5b8335612b17816127f3565b92506020840135612b27816127f3565b929592945050506040919091013590565b600080600060608486031215612b4d57600080fd5b83359250612b5d602085016127bf565b9150604084013567ffffffffffffffff811115612b7957600080fd5b612b858682870161298e565b9150509250925092565b60008060008060808587031215612ba557600080fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115612bd157600080fd5b612bdd8782880161298e565b91505092959194509250565b600080600080600060a08688031215612c0157600080fd5b612c0a866127bf565b94506020860135935060408601359250606086013591506080860135612c2f816127f3565b809150509295509295909350565b60008060408385031215612c5057600080fd5b612c59836127bf565b91506020830135612aa5816127f3565b60008060408385031215612c7c57600080fd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff811681146127d357600080fd5b60008060008060008060a08789031215612cc457600080fd5b86359550612cd4602088016127bf565b9450612ce260408801612c8b565b9350612cf060608801612c8b565b9250608087013567ffffffffffffffff80821115612d0d57600080fd5b818901915089601f830112612d2157600080fd5b813581811115612d3057600080fd5b8a6020828501011115612d4257600080fd5b6020830194508093505050509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b82815260006020604081840152835180604085015260005b81811015612dbb57858101830151858201606001528201612d9f565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b600060208284031215612e0d57600080fd5b8151612832816127f3565b818103818111156116e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008060408385031215612e6557600080fd5b8251612e70816127f3565b6020840151909250612aa5816127f3565b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019291505056fea2646970667358221220649979ad19e01f7ccf90de1e413b95cf5175c5ca9832141d226f7e90afad79bc64736f6c63430008130033000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c1836000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead
Deployed Bytecode
0x6080604052600436106102345760003560e01c80638da5cb5b11610138578063c6a261d2116100b0578063d5b8da731161007f578063ef7b769011610064578063ef7b769014610789578063efec6cd4146107e0578063f22b460e1461081457600080fd5b8063d5b8da7314610735578063ecb974841461076957600080fd5b8063c6a261d2146106a7578063c8779308146106db578063d39a38c1146106f5578063d547741f1461071557600080fd5b8063a9a541b211610107578063b349ba65116100ec578063b349ba651461060e578063b947aac614610657578063be94a4761461068757600080fd5b8063a9a541b2146105c0578063aac96557146105d357600080fd5b80638da5cb5b1461053557806391d14854146105605780639aefe4e014610580578063a0851863146105a057600080fd5b80632f2ff15d116101cb5780635b94db271161019a5780637c1388141161017f5780637c138814146104c857806382987d30146104f557806389ee87551461051557600080fd5b80635b94db27146104885780636ccae054146104a857600080fd5b80632f2ff15d146104035780633bd1adec1461042357806343fa97ca146104385780634c4081801461045857600080fd5b80631e867311116102075780631e8673111461035757806320f99c0a1461037757806325750e37146103c35780632e7eb258146103e357600080fd5b806306da42e0146102395780630cd55abf146102da578063164e68de146103155780631ba8e48414610337575b600080fd5b34801561024557600080fd5b506102ac6102543660046127d8565b63ffffffff166000908152600760209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff808216808552700100000000000000000000000000000000909204169290910182905291565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152015b60405180910390f35b3480156102e657600080fd5b506103076102f5366004612815565b60066020526000908152604090205481565b6040519081526020016102d1565b34801561032157600080fd5b50610335610330366004612815565b610834565b005b34801561034357600080fd5b50610335610352366004612839565b610921565b34801561036357600080fd5b506103356103723660046128c5565b610982565b34801561038357600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102d1565b3480156103cf57600080fd5b506103356103de366004612a39565b610b28565b3480156103ef57600080fd5b506103356103fe366004612839565b610d41565b34801561040f57600080fd5b5061033561041e366004612a80565b610d9d565b34801561042f57600080fd5b50610335610df8565b34801561044457600080fd5b506103356104533660046128c5565b610e54565b34801561046457600080fd5b50610478610473366004612ab0565b610ff0565b60405190151581526020016102d1565b34801561049457600080fd5b506103356104a3366004612815565b6110c1565b3480156104b457600080fd5b506103356104c3366004612af7565b611181565b3480156104d457600080fd5b506103076104e33660046127d8565b60086020526000908152604090205481565b34801561050157600080fd5b50610335610510366004612b38565b61121f565b34801561052157600080fd5b50610335610530366004612b8f565b61145a565b34801561054157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661039e565b34801561056c57600080fd5b5061047861057b366004612a80565b6116ad565b34801561058c57600080fd5b5061033561059b366004612be9565b6116ea565b3480156105ac57600080fd5b506103356105bb366004612c3d565b611856565b6103356105ce3660046127d8565b611995565b3480156105df57600080fd5b506104786105ee366004612c69565b600560209081526000928352604080842090915290825290205460ff1681565b34801561061a57600080fd5b506106427f000000000000000000000000000000000000000000000000000000000000009281565b60405163ffffffff90911681526020016102d1565b34801561066357600080fd5b506104786106723660046127d8565b60046020526000908152604090205460ff1681565b34801561069357600080fd5b506103356106a2366004612b38565b611a8a565b3480156106b357600080fd5b5061039e7f000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce81565b3480156106e757600080fd5b506003546104789060ff1681565b34801561070157600080fd5b50610335610710366004612a39565b611cc6565b34801561072157600080fd5b50610335610730366004612a80565b611edb565b34801561074157600080fd5b5061039e7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead81565b34801561077557600080fd5b50610478610784366004612839565b611f36565b34801561079557600080fd5b506102ac6107a43660046127d8565b6007602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b3480156107ec57600080fd5b506103077f0000000000000000000000000000000000000000000000000000000000001c2081565b34801561082057600080fd5b5061033561082f366004612cab565b611f4b565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166108c6576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216610913576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d8247612203565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d838383612278565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109d3576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84811415806109e25750848314155b15610a19576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610b1e576000868683818110610a3957610a39612d58565b9050602002016020810190610a4e91906127d8565b63ffffffff161115610ace57610ac9888883818110610a6f57610a6f612d58565b90506020020135878784818110610a8857610a88612d58565b9050602002016020810190610a9d91906127d8565b868685818110610aaf57610aaf612d58565b9050602002016020810190610ac49190612815565b612278565b610b16565b610b16888883818110610ae357610ae3612d58565b90506020020135858584818110610afc57610afc612d58565b9050602002016020810190610b119190612815565b6122b5565b600101610a1d565b5050505050505050565b604080517fa7d456f2444d46f78a51def7ecdf108d72f72da2e10ce355caa5e99a17bed2de6020820152309181019190915263ffffffff7f000000000000000000000000000000000000000000000000000000000000009216606082015260808101839052600060a082018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead16906397aba7f99060c00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401610c0c929190612d87565b602060405180830381865afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d9190612dfb565b9050610c797fb0a81253fa41a5cd7c5885c220c30d519a0d552984e0d69edda03449f69fa6db82612338565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558314610cdf576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055604051600081527f42a60e0dc12250ea896a8f5156f1f3aa4567cd2bd87a72bc097210dc02ec2e05906020015b60405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d92576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d8383836123a4565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dee576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d82826123e1565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e49576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e5233612467565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ea5576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610eb45750848314155b15610eeb576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610b1e576000868683818110610f0b57610f0b612d58565b9050602002016020810190610f2091906127d8565b63ffffffff161115610fa057610f9b888883818110610f4157610f41612d58565b90506020020135878784818110610f5a57610f5a612d58565b9050602002016020810190610f6f91906127d8565b868685818110610f8157610f81612d58565b9050602002016020810190610f969190612815565b6123a4565b610fe8565b610fe8888883818110610fb557610fb5612d58565b90506020020135858584818110610fce57610fce612d58565b9050602002016020810190610fe39190612815565b6123e1565b600101610eef565b600354600090859060ff168061101b575063ffffffff841660009081526004602052604090205460ff165b8061103f5750600086815260056020908152604080832088845290915290205460ff165b80611068575063ffffffff841660009081526008602052604090205467ffffffffffffffff8216105b156110775760009150506110b8565b7f0000000000000000000000000000000000000000000000000000000000001c206110a28442612e18565b10156110b25760009150506110b8565b60019150505b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611112576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661120e576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6112198484846124df565b50505050565b604080517fc9c6c9004cdd87e14f6d7be800064bea944fdafc4e66c833d9da91c10d4ced356020820152309181019190915263ffffffff80841660608301527f000000000000000000000000000000000000000000000000000000000000009216608082015260a08101849052600060c082018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead16906397aba7f99060e00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b815260040161130b929190612d87565b602060405180830381865afa158015611328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134c9190612dfb565b90506113787fb0a81253fa41a5cd7c5885c220c30d519a0d552984e0d69edda03449f69fa6db82612338565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260066020526040902080546001810190915584146113de576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8316600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051938452908301919091527f43b1a9ba48bea5f72f92aaaf96b18ec134518690384df35d04b1316ca68147e191015b60405180910390a150505050565b604080517f119101cda5c91f869cec4313411657e772bec4c5a184dd6ab7a60859e3d347836020820152309181019190915260e084811c6060830181905263ffffffff7f000000000000000000000000000000000000000000000000000000000000009216608084015260a0830187905260c08301869052908201849052906000907f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead73ffffffffffffffffffffffffffffffffffffffff16906397aba7f9906101000160405160208183030381529060405280519060200120856040518363ffffffff1660e01b8152600401611552929190612d87565b602060405180830381865afa15801561156f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115939190612dfb565b90506115c67f2125d1e225cadc5c8296e2cc1f96ee607770bf4a4a16131e62f6819937437c898363ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260409020805460018101909155861461162c576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260056020908152604080832087845282529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905581518781529081018690527f876c775784dd569d1ecd6e1a52c87169c22c4e906a138c91a59f451fa0f431b5910160405180910390a1505050505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff16611777576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b63ffffffff861660008181526008602052604090819020859055517f0b04bb410000000000000000000000000000000000000000000000000000000081526004810191909152602481018690526044810185905273ffffffffffffffffffffffffffffffffffffffff83811660648301527f000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce1690630b04bb419060840160408051808303816000875af1158015611832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612e52565b3360009081527f0f4a237b7f9e071a612ddea08a06576f25cc7dffe13a46307ee64fe2318b3c3e60205260409020547f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb19060ff166118e3576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6040517f81403a0200000000000000000000000000000000000000000000000000000000815263ffffffff8416600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301527f000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce16906381403a0290604401600060405180830381600087803b15801561197857600080fd5b505af115801561198c573d6000803e3d6000fd5b50505050505050565b7f000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce73ffffffffffffffffffffffffffffffffffffffff16626186f76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a239190612dfb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a87576040517f03c377c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b604080517f4623a5d5b82ed238c8ba6e51cffa4ddaf241150d9af32813faab00132f55a4566020820152309181019190915263ffffffff80841660608301527f000000000000000000000000000000000000000000000000000000000000009216608082015260a08101849052600160c082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead16906397aba7f99060e00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401611b76929190612d87565b602060405180830381865afa158015611b93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb79190612dfb565b9050611bea7f2125d1e225cadc5c8296e2cc1f96ee607770bf4a4a16131e62f6819937437c898463ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558414611c50576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff831660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558251938452908301527f43b1a9ba48bea5f72f92aaaf96b18ec134518690384df35d04b1316ca68147e1910161144c565b604080517fbdfa1b22b053b80e8209cb4421ce6b25b45bb164e02718501cb19a46c4df987c6020820152309181019190915263ffffffff7f000000000000000000000000000000000000000000000000000000000000009216606082015260808101839052600160a082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead16906397aba7f99060c00160405160208183030381529060405280519060200120846040518363ffffffff1660e01b8152600401611daa929190612d87565b602060405180830381865afa158015611dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611deb9190612dfb565b9050611e177fd66a896d5b3e8cd31bfd557e6ebdb5bba4561c7ce6573d5c6716876cbc83dbdd82612338565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090208054600181019091558314611e7d576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556040519081527f42a60e0dc12250ea896a8f5156f1f3aa4567cd2bd87a72bc097210dc02ec2e0590602001610d34565b60005473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091d82826122b5565b6000611f43848484612662565b949350505050565b604080517ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab66020820152309181019190915263ffffffff7f0000000000000000000000000000000000000000000000000000000000000092811660608301528616608082015260a081018790526fffffffffffffffffffffffffffffffff80861660c0830152841660e082015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead16906397aba7f990610100016040516020818303038152906040528051906020012085856040518463ffffffff1660e01b815260040161205393929190612e81565b602060405180830381865afa158015612070573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120949190612dfb565b90506120c77f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38763ffffffff16836125cf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600660205260409020805460018101909155871461212d576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040908190206fffffffffffffffffffffffffffffffff878116908716700100000000000000000000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000001617815590517faebc3dd035ce00dd026bd60872bea44979224507aa49434f67ec5f9ae924aaa3906121f1908990849063ffffffff929092168252546fffffffffffffffffffffffffffffffff8116602083015260801c604082015260600190565b60405180910390a15050505050505050565b600080600080600085875af190508061097d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016108bd565b61097d838360405160200161229d92919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661091d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018390526024016108bd565b61097d83836040516020016123c992919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff821661252c576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016125735761097d8282612203565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036125c4576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097d8383836126f0565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611219576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024016108bd565b6000611f43848460405160200161268992919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016108bd565b803563ffffffff811681146127d357600080fd5b919050565b6000602082840312156127ea57600080fd5b6116e1826127bf565b73ffffffffffffffffffffffffffffffffffffffff81168114611a8757600080fd5b60006020828403121561282757600080fd5b8135612832816127f3565b9392505050565b60008060006060848603121561284e57600080fd5b8335925061285e602085016127bf565b9150604084013561286e816127f3565b809150509250925092565b60008083601f84011261288b57600080fd5b50813567ffffffffffffffff8111156128a357600080fd5b6020830191508360208260051b85010111156128be57600080fd5b9250929050565b600080600080600080606087890312156128de57600080fd5b863567ffffffffffffffff808211156128f657600080fd5b6129028a838b01612879565b9098509650602089013591508082111561291b57600080fd5b6129278a838b01612879565b9096509450604089013591508082111561294057600080fd5b5061294d89828a01612879565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261299f57600080fd5b813567ffffffffffffffff808211156129ba576129ba61295f565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612a0057612a0061295f565b81604052838152866020858801011115612a1957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612a4c57600080fd5b82359150602083013567ffffffffffffffff811115612a6a57600080fd5b612a768582860161298e565b9150509250929050565b60008060408385031215612a9357600080fd5b823591506020830135612aa5816127f3565b809150509250929050565b600080600080600060a08688031215612ac857600080fd5b853594506020860135935060408601359250612ae6606087016127bf565b949793965091946080013592915050565b600080600060608486031215612b0c57600080fd5b8335612b17816127f3565b92506020840135612b27816127f3565b929592945050506040919091013590565b600080600060608486031215612b4d57600080fd5b83359250612b5d602085016127bf565b9150604084013567ffffffffffffffff811115612b7957600080fd5b612b858682870161298e565b9150509250925092565b60008060008060808587031215612ba557600080fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115612bd157600080fd5b612bdd8782880161298e565b91505092959194509250565b600080600080600060a08688031215612c0157600080fd5b612c0a866127bf565b94506020860135935060408601359250606086013591506080860135612c2f816127f3565b809150509295509295909350565b60008060408385031215612c5057600080fd5b612c59836127bf565b91506020830135612aa5816127f3565b60008060408385031215612c7c57600080fd5b50508035926020909101359150565b80356fffffffffffffffffffffffffffffffff811681146127d357600080fd5b60008060008060008060a08789031215612cc457600080fd5b86359550612cd4602088016127bf565b9450612ce260408801612c8b565b9350612cf060608801612c8b565b9250608087013567ffffffffffffffff80821115612d0d57600080fd5b818901915089601f830112612d2157600080fd5b813581811115612d3057600080fd5b8a6020828501011115612d4257600080fd5b6020830194508093505050509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b82815260006020604081840152835180604085015260005b81811015612dbb57858101830151858201606001528201612d9f565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b600060208284031215612e0d57600080fd5b8151612832816127f3565b818103818111156116e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008060408385031215612e6557600080fd5b8251612e70816127f3565b6020840151909250612aa5816127f3565b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019291505056fea2646970667358221220649979ad19e01f7ccf90de1e413b95cf5175c5ca9832141d226f7e90afad79bc64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c1836000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce00000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000001c20000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead
-----Decoded View---------------
Arg [0] : owner_ (address): 0xB0BBff6311B7F245761A7846d3Ce7B1b100C1836
Arg [1] : socket_ (address): 0xbe7241e9D11EC2D1Ac86CE217c4A37b7aD1701cE
Arg [2] : chainSlug_ (uint32): 146
Arg [3] : timeoutInSeconds_ (uint256): 7200
Arg [4] : signatureVerifier_ (address): 0xc8a4D2fd77c155fd52e65Ab07F337aBF84495Ead
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c1836
Arg [1] : 000000000000000000000000be7241e9d11ec2d1ac86ce217c4a37b7ad1701ce
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000092
Arg [3] : 0000000000000000000000000000000000000000000000000000000000001c20
Arg [4] : 000000000000000000000000c8a4d2fd77c155fd52e65ab07f337abf84495ead
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
AVAX | 100.00% | $19.86 | 1.057 | $20.99 |
Loading...
Loading
Loading...
Loading
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.