Overview
ETH Balance
ETH Value
$0.00Latest 5 from a total of 5 transactions
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.19;
import "./interfaces/ISwitchboard.sol";
import "./interfaces/ISocket.sol";
import "./interfaces/ISignatureVerifier.sol";
import "./libraries/RescueFundsLib.sol";
import "./utils/AccessControlExtended.sol";
import {WITHDRAW_ROLE, RESCUE_ROLE, EXECUTOR_ROLE, FEES_UPDATER_ROLE} from "./utils/AccessRoles.sol";
import {FEES_UPDATE_SIG_IDENTIFIER, RELATIVE_NATIVE_TOKEN_PRICE_UPDATE_SIG_IDENTIFIER, MSG_VALUE_MAX_THRESHOLD_SIG_IDENTIFIER, MSG_VALUE_MIN_THRESHOLD_SIG_IDENTIFIER} from "./utils/SigIdentifiers.sol";
/**
* @title ExecutionManagerDF
* @dev Implementation of the IExecutionManager interface, providing functions for executing cross-chain transactions and
* managing execution and other fees. This contract also implements the AccessControl interface, allowing for role-based
* access control.
*/
contract ExecutionManagerDF is IExecutionManager, AccessControlExtended {
uint256 private constant PAYLOAD_LIMIT = 5000;
ISignatureVerifier public immutable signatureVerifier__;
ISocket public immutable socket__;
uint32 public immutable chainSlug;
/**
* @notice Emitted when the executionFees is updated
* @param siblingChainSlug The destination chain slug for which the executionFees is updated
* @param executionFees The new executionFees
*/
event ExecutionFeesSet(
uint32 siblingChainSlug,
ExecutionFeesParam executionFees
);
/**
* @notice Emitted when the relativeNativeTokenPrice is updated
* @param siblingChainSlug The destination chain slug for which the relativeNativeTokenPrice is updated
* @param relativeNativeTokenPrice The new relativeNativeTokenPrice
*/
event RelativeNativeTokenPriceSet(
uint256 siblingChainSlug,
uint256 relativeNativeTokenPrice
);
/**
* @notice Emitted when the msgValueMaxThresholdSet is updated
* @param siblingChainSlug The destination chain slug for which the msgValueMaxThresholdSet is updated
* @param msgValueMaxThresholdSet The new msgValueMaxThresholdSet
*/
event MsgValueMaxThresholdSet(
uint256 siblingChainSlug,
uint256 msgValueMaxThresholdSet
);
/**
* @notice Emitted when the msgValueMinThresholdSet is updated
* @param siblingChainSlug The destination chain slug for which the msgValueMinThresholdSet is updated
* @param msgValueMinThresholdSet The new msgValueMinThresholdSet
*/
event MsgValueMinThresholdSet(
uint256 siblingChainSlug,
uint256 msgValueMinThresholdSet
);
/**
* @notice Emitted when the execution fees is withdrawn
* @param account The address to which fees is transferred
* @param siblingChainSlug The destination chain slug for which the fees is withdrawn
* @param amount The amount withdrawn
*/
event ExecutionFeesWithdrawn(
address account,
uint32 siblingChainSlug,
uint256 amount
);
/**
* @notice Emitted when the transmission fees is withdrawn
* @param transmitManager The address of transmit manager to which fees is transferred
* @param siblingChainSlug The destination chain slug for which the fees is withdrawn
* @param amount The amount withdrawn
*/
event TransmissionFeesWithdrawn(
address transmitManager,
uint32 siblingChainSlug,
uint256 amount
);
/**
* @notice Emitted when the switchboard fees is withdrawn
* @param switchboard The address of switchboard for which fees is claimed
* @param siblingChainSlug The destination chain slug for which the fees is withdrawn
* @param amount The amount withdrawn
*/
event SwitchboardFeesWithdrawn(
address switchboard,
uint32 siblingChainSlug,
uint256 amount
);
/**
* @notice packs the total execution and transmission fees received for a sibling slug
*/
struct TotalExecutionAndTransmissionFees {
uint128 totalExecutionFees;
uint128 totalTransmissionFees;
}
// maps total fee collected with chain slug
mapping(uint32 => TotalExecutionAndTransmissionFees)
public totalExecutionAndTransmissionFees;
// switchboard => chain slug => switchboard fees collected
mapping(address => mapping(uint32 => uint128)) public totalSwitchboardFees;
// transmitter => nextNonce
mapping(address => uint256) public nextNonce;
// transmit manager => chain slug => switchboard fees collected
mapping(address => mapping(uint32 => uint128)) public transmissionMinFees;
// relativeNativeTokenPrice is used to convert fees to destination terms when sending value along with message
// destSlug => relativeNativePrice (stores (destnativeTokenPriceUSD*(1e18)/srcNativeTokenPriceUSD))
mapping(uint32 => uint256) public relativeNativeTokenPrice;
// supported min amount of native value to send with message
// chain slug => min msg value threshold
mapping(uint32 => uint256) public msgValueMinThreshold;
// supported max amount of native value to send with message
// chain slug => max msg value threshold
mapping(uint32 => uint256) public msgValueMaxThreshold;
// remoteChainSlug => ExecutionFeesParam
mapping(uint32 => ExecutionFeesParam) public executionFees;
// triggered when nonce in signature is invalid
error InvalidNonce();
// triggered when msg value less than min threshold
error MsgValueTooLow();
// triggered when msg value more than max threshold
error MsgValueTooHigh();
// triggered when msg value is not enough
error InsufficientMsgValue();
// triggered when fees is not enough
error InsufficientFees();
// triggered when msg value exceeds uint128 max value
error InvalidMsgValue();
// triggered when fees exceeds uint128 max value
error FeesTooHigh();
error OnlySocket();
error PayloadTooLarge();
/**
* @dev Constructor for ExecutionManager contract
* @param owner_ address of the contract owner
* @param chainSlug_ chain slug, unique identifier of chain deployed on
* @param signatureVerifier_ the signature verifier contract
* @param socket_ the socket contract
*/
constructor(
address owner_,
uint32 chainSlug_,
ISocket socket_,
ISignatureVerifier signatureVerifier_
) AccessControlExtended(owner_) {
chainSlug = chainSlug_;
signatureVerifier__ = signatureVerifier_;
socket__ = ISocket(socket_);
}
/**
* @notice Checks whether the provided signer address is an executor for the given packed message and signature
* @param packedMessage Packed message to be executed
* @param sig Signature of the message
* @return executor Address of the executor
* @return isValidExecutor Boolean value indicating whether the executor is valid or not
*/
function isExecutor(
bytes32 packedMessage,
bytes memory sig
)
external
view
virtual
override
returns (address executor, bool isValidExecutor)
{
executor = signatureVerifier__.recoverSigner(packedMessage, sig);
isValidExecutor = _hasRole(EXECUTOR_ROLE, executor);
}
/**
* @notice updates the total fee used by an executor to execute a message
* @dev to be used for accounting when onchain fee distribution for individual executors is implemented
* @dev this function should be called by socket only
* @inheritdoc IExecutionManager
*/
function updateExecutionFees(
address,
uint128,
bytes32
) external view override {
if (msg.sender != address(socket__)) revert OnlySocket();
}
/// @inheritdoc IExecutionManager
function payAndCheckFees(
uint256 minMsgGasLimit_,
uint256 payloadSize_,
bytes32 executionParams_,
bytes32,
uint32 siblingChainSlug_,
uint128 switchboardFees_,
uint128 verificationOverheadFees_,
address transmitManager_,
address switchboard_,
uint256 maxPacketLength_
)
external
payable
override
returns (uint128 executionFee, uint128 transmissionFees)
{
if (msg.value >= type(uint128).max) revert InvalidMsgValue();
uint128 msgValue = uint128(msg.value);
// transmission fees are per packet, so need to divide by number of messages per packet
transmissionFees =
transmissionMinFees[transmitManager_][siblingChainSlug_] /
uint128(maxPacketLength_);
uint128 minMsgExecutionFees = _getMinFees(
minMsgGasLimit_,
payloadSize_,
executionParams_,
siblingChainSlug_
);
uint128 minExecutionFees = minMsgExecutionFees +
verificationOverheadFees_;
if (msgValue < transmissionFees + switchboardFees_ + minExecutionFees)
revert InsufficientFees();
// any extra fee is considered as executionFee
executionFee = msgValue - transmissionFees - switchboardFees_;
TotalExecutionAndTransmissionFees
memory currentTotalFees = totalExecutionAndTransmissionFees[
siblingChainSlug_
];
totalExecutionAndTransmissionFees[
siblingChainSlug_
] = TotalExecutionAndTransmissionFees({
totalExecutionFees: currentTotalFees.totalExecutionFees +
executionFee,
totalTransmissionFees: currentTotalFees.totalTransmissionFees +
transmissionFees
});
totalSwitchboardFees[switchboard_][
siblingChainSlug_
] += switchboardFees_;
}
/**
* @notice function for getting the minimum fees required for executing msg on destination
* @dev this function is called at source to calculate the execution cost.
* @param gasLimit_ the gas limit needed for execution at destination
* @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 getMinFees(
uint256 gasLimit_,
uint256 payloadSize_,
bytes32 executionParams_,
uint32 siblingChainSlug_
) external view override returns (uint128 minExecutionFee) {
minExecutionFee = _getMinFees(
gasLimit_,
payloadSize_,
executionParams_,
siblingChainSlug_
);
}
/// @inheritdoc IExecutionManager
function getExecutionTransmissionMinFees(
uint256 minMsgGasLimit_,
uint256 payloadSize_,
bytes32 executionParams_,
bytes32,
uint32 siblingChainSlug_,
address transmitManager_
)
external
view
override
returns (uint128 minExecutionFee, uint128 transmissionFees)
{
minExecutionFee = _getMinFees(
minMsgGasLimit_,
payloadSize_,
executionParams_,
siblingChainSlug_
);
transmissionFees = transmissionMinFees[transmitManager_][
siblingChainSlug_
];
}
// decodes and validates the msg value if it is under given transfer limits and calculates
// the total fees needed for execution for given payload size and msg value.
function _getMinFees(
uint256 msgGasLimit,
uint256 payloadSize_,
bytes32 executionParams_,
uint32 siblingChainSlug_
) internal view returns (uint128) {
if (payloadSize_ > PAYLOAD_LIMIT) revert PayloadTooLarge();
uint256 totalNativeValue = _calculateExecutionFees(
msgGasLimit,
payloadSize_,
siblingChainSlug_
) + _calculateMsgValueFees(siblingChainSlug_, executionParams_);
if (totalNativeValue >= type(uint128).max) revert FeesTooHigh();
return uint128(totalNativeValue);
}
function _calculateExecutionFees(
uint256 msgGasLimit,
uint256 payloadSize_,
uint32 siblingChainSlug_
) internal view returns (uint256 totalFees) {
ExecutionFeesParam memory executionFeesParam = executionFees[
siblingChainSlug_
];
// layer 2 fees depends on the payload size and how chain calculates the tx fees
// to simplify, an overhead and perByteCost is updated on contract through external cron
// and fees is calculated as : payloadSize * perByteCost + overhead
// fees = gasLimit * gasLimit + perBytesCost * payloadLength + overhead
totalFees =
msgGasLimit *
executionFeesParam.perGasCost +
executionFeesParam.overhead +
payloadSize_ *
executionFeesParam.perByteCost;
}
function _calculateMsgValueFees(
uint32 siblingChainSlug_,
bytes32 executionParams_
) internal view returns (uint256 msgValueRequiredOnSrcChain) {
uint256 params = uint256(executionParams_);
uint8 paramType = uint8(params >> 248);
if (paramType == 0) return 0;
uint256 msgValue = uint256(uint248(params));
if (msgValue < msgValueMinThreshold[siblingChainSlug_])
revert MsgValueTooLow();
if (msgValue > msgValueMaxThreshold[siblingChainSlug_])
revert MsgValueTooHigh();
msgValueRequiredOnSrcChain =
(relativeNativeTokenPrice[siblingChainSlug_] * msgValue) /
1e18;
}
/**
* @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 pure override {
uint256 params = uint256(executionParams_);
uint8 paramType = uint8(params >> 248);
if (paramType == 0) return;
uint256 expectedMsgValue = uint256(uint248(params));
if (msgValue_ < expectedMsgValue) revert InsufficientMsgValue();
}
/**
* @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 but this will be
* updated in future to consider gas limit and payload size to return fees which will be close to
* actual execution cost.
* @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 override {
address feesUpdater = signatureVerifier__.recoverSigner(
keccak256(
abi.encode(
FEES_UPDATE_SIG_IDENTIFIER,
address(this),
chainSlug,
siblingChainSlug_,
nonce_,
executionFees_
)
),
signature_
);
_checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, 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();
}
executionFees[siblingChainSlug_] = executionFees_;
emit ExecutionFeesSet(siblingChainSlug_, executionFees_);
}
/**
* @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 override {
address feesUpdater = signatureVerifier__.recoverSigner(
keccak256(
abi.encode(
RELATIVE_NATIVE_TOKEN_PRICE_UPDATE_SIG_IDENTIFIER,
address(this),
chainSlug,
siblingChainSlug_,
nonce_,
relativeNativeTokenPrice_
)
),
signature_
);
_checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, 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();
}
relativeNativeTokenPrice[siblingChainSlug_] = relativeNativeTokenPrice_;
emit RelativeNativeTokenPriceSet(
siblingChainSlug_,
relativeNativeTokenPrice_
);
}
/**
* @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 override {
address feesUpdater = signatureVerifier__.recoverSigner(
keccak256(
abi.encode(
MSG_VALUE_MIN_THRESHOLD_SIG_IDENTIFIER,
address(this),
chainSlug,
siblingChainSlug_,
nonce_,
msgValueMinThreshold_
)
),
signature_
);
_checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, 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();
}
msgValueMinThreshold[siblingChainSlug_] = msgValueMinThreshold_;
emit MsgValueMinThresholdSet(siblingChainSlug_, msgValueMinThreshold_);
}
/**
* @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 override {
address feesUpdater = signatureVerifier__.recoverSigner(
keccak256(
abi.encode(
MSG_VALUE_MAX_THRESHOLD_SIG_IDENTIFIER,
address(this),
chainSlug,
siblingChainSlug_,
nonce_,
msgValueMaxThreshold_
)
),
signature_
);
_checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, 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();
}
msgValueMaxThreshold[siblingChainSlug_] = msgValueMaxThreshold_;
emit MsgValueMaxThresholdSet(siblingChainSlug_, msgValueMaxThreshold_);
}
/**
* @notice updates the transmission fee needed for transmission
* @dev this function stores value against msg.sender hence expected to be called by transmit manager
* @inheritdoc IExecutionManager
*/
function setTransmissionMinFees(
uint32 remoteChainSlug_,
uint128 fees_
) external override {
transmissionMinFees[msg.sender][remoteChainSlug_] = fees_;
}
/**
* @notice withdraws fees for execution from contract
* @param siblingChainSlug_ withdraw fees corresponding to this slug
* @param amount_ withdraw amount
* @param withdrawTo_ withdraw fees to the provided address
*/
function withdrawExecutionFees(
uint32 siblingChainSlug_,
uint128 amount_,
address withdrawTo_
) external onlyRole(WITHDRAW_ROLE) {
if (withdrawTo_ == address(0)) revert ZeroAddress();
if (
totalExecutionAndTransmissionFees[siblingChainSlug_]
.totalExecutionFees < amount_
) revert InsufficientFees();
totalExecutionAndTransmissionFees[siblingChainSlug_]
.totalExecutionFees -= amount_;
SafeTransferLib.safeTransferETH(withdrawTo_, amount_);
emit ExecutionFeesWithdrawn(withdrawTo_, siblingChainSlug_, amount_);
}
/**
* @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 override {
if (totalSwitchboardFees[switchboard_][siblingChainSlug_] < amount_)
revert InsufficientFees();
totalSwitchboardFees[switchboard_][siblingChainSlug_] -= amount_;
ISwitchboard(switchboard_).receiveFees{value: amount_}(
siblingChainSlug_
);
emit SwitchboardFeesWithdrawn(switchboard_, siblingChainSlug_, amount_);
}
/**
* @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 override {
if (
totalExecutionAndTransmissionFees[siblingChainSlug_]
.totalTransmissionFees < amount_
) revert InsufficientFees();
totalExecutionAndTransmissionFees[siblingChainSlug_]
.totalTransmissionFees -= amount_;
ITransmitManager tm = socket__.transmitManager__();
tm.receiveFees{value: amount_}(siblingChainSlug_);
emit TransmissionFeesWithdrawn(address(tm), siblingChainSlug_, amount_);
}
/**
* @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_);
}
}// 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 "./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");
}
}{
"libraries": {},
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"contract ISocket","name":"socket_","type":"address"},{"internalType":"contract ISignatureVerifier","name":"signatureVerifier_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FeesTooHigh","type":"error"},{"inputs":[],"name":"InsufficientFees","type":"error"},{"inputs":[],"name":"InsufficientMsgValue","type":"error"},{"inputs":[],"name":"InvalidMsgValue","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[],"name":"MsgValueTooHigh","type":"error"},{"inputs":[],"name":"MsgValueTooLow","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NoPermit","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"OnlySocket","type":"error"},{"inputs":[],"name":"PayloadTooLarge","type":"error"},{"inputs":[],"name":"UnequalArrayLengths","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"siblingChainSlug","type":"uint32"},{"components":[{"internalType":"uint80","name":"perGasCost","type":"uint80"},{"internalType":"uint80","name":"perByteCost","type":"uint80"},{"internalType":"uint80","name":"overhead","type":"uint80"}],"indexed":false,"internalType":"struct IExecutionManager.ExecutionFeesParam","name":"executionFees","type":"tuple"}],"name":"ExecutionFeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint32","name":"siblingChainSlug","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExecutionFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"siblingChainSlug","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"msgValueMaxThresholdSet","type":"uint256"}],"name":"MsgValueMaxThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"siblingChainSlug","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"msgValueMinThresholdSet","type":"uint256"}],"name":"MsgValueMinThresholdSet","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":"uint256","name":"siblingChainSlug","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"relativeNativeTokenPrice","type":"uint256"}],"name":"RelativeNativeTokenPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"grantee","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"revokee","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"switchboard","type":"address"},{"indexed":false,"internalType":"uint32","name":"siblingChainSlug","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SwitchboardFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"transmitManager","type":"address"},{"indexed":false,"internalType":"uint32","name":"siblingChainSlug","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransmissionFeesWithdrawn","type":"event"},{"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":"executionFees","outputs":[{"internalType":"uint80","name":"perGasCost","type":"uint80"},{"internalType":"uint80","name":"perByteCost","type":"uint80"},{"internalType":"uint80","name":"overhead","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minMsgGasLimit_","type":"uint256"},{"internalType":"uint256","name":"payloadSize_","type":"uint256"},{"internalType":"bytes32","name":"executionParams_","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"address","name":"transmitManager_","type":"address"}],"name":"getExecutionTransmissionMinFees","outputs":[{"internalType":"uint128","name":"minExecutionFee","type":"uint128"},{"internalType":"uint128","name":"transmissionFees","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasLimit_","type":"uint256"},{"internalType":"uint256","name":"payloadSize_","type":"uint256"},{"internalType":"bytes32","name":"executionParams_","type":"bytes32"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"}],"name":"getMinFees","outputs":[{"internalType":"uint128","name":"minExecutionFee","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":"bytes32","name":"packedMessage","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"isExecutor","outputs":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"bool","name":"isValidExecutor","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"msgValueMaxThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"msgValueMinThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nominee_","type":"address"}],"name":"nominateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minMsgGasLimit_","type":"uint256"},{"internalType":"uint256","name":"payloadSize_","type":"uint256"},{"internalType":"bytes32","name":"executionParams_","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint128","name":"switchboardFees_","type":"uint128"},{"internalType":"uint128","name":"verificationOverheadFees_","type":"uint128"},{"internalType":"address","name":"transmitManager_","type":"address"},{"internalType":"address","name":"switchboard_","type":"address"},{"internalType":"uint256","name":"maxPacketLength_","type":"uint256"}],"name":"payAndCheckFees","outputs":[{"internalType":"uint128","name":"executionFee","type":"uint128"},{"internalType":"uint128","name":"transmissionFees","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"relativeNativeTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"siblingChainSlug_","type":"uint32"},{"components":[{"internalType":"uint80","name":"perGasCost","type":"uint80"},{"internalType":"uint80","name":"perByteCost","type":"uint80"},{"internalType":"uint80","name":"overhead","type":"uint80"}],"internalType":"struct IExecutionManager.ExecutionFeesParam","name":"executionFees_","type":"tuple"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setExecutionFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint256","name":"msgValueMaxThreshold_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setMsgValueMaxThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint256","name":"msgValueMinThreshold_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setMsgValueMinThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce_","type":"uint256"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint256","name":"relativeNativeTokenPrice_","type":"uint256"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"setRelativeNativeTokenPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"remoteChainSlug_","type":"uint32"},{"internalType":"uint128","name":"fees_","type":"uint128"}],"name":"setTransmissionMinFees","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":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"totalExecutionAndTransmissionFees","outputs":[{"internalType":"uint128","name":"totalExecutionFees","type":"uint128"},{"internalType":"uint128","name":"totalTransmissionFees","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"totalSwitchboardFees","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"transmissionMinFees","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"updateExecutionFees","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"executionParams_","type":"bytes32"},{"internalType":"uint256","name":"msgValue_","type":"uint256"}],"name":"verifyParams","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint128","name":"amount_","type":"uint128"},{"internalType":"address","name":"withdrawTo_","type":"address"}],"name":"withdrawExecutionFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"address","name":"switchboard_","type":"address"},{"internalType":"uint128","name":"amount_","type":"uint128"}],"name":"withdrawSwitchboardFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"uint128","name":"amount_","type":"uint128"}],"name":"withdrawTransmissionFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620039a5380380620039a58339810160408190526200003491620000d5565b838080620000428162000069565b50505063ffffffff90921660c0526001600160a01b039182166080521660a0525062000145565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b6001600160a01b0381168114620000d257600080fd5b50565b60008060008060808587031215620000ec57600080fd5b8451620000f981620000bc565b602086015190945063ffffffff811681146200011457600080fd5b60408601519093506200012781620000bc565b60608601519092506200013a81620000bc565b939692955090935050565b60805160a05160c0516137e3620001c26000396000818161087d01528181610ce20152818161114f01528181611d150152611f3f0152600081816108c60152818161154e01526124d501526000818161091a01528181610d73015281816110f101528181611bec01528181611da60152611fd001526137e36000f3fe6080604052600436106102845760003560e01c80637644e7fa11610153578063aea3d96b116100cb578063d5b8da731161007f578063de8c4ff911610064578063de8c4ff914610986578063ecb97484146109a6578063f1f069d6146109c657600080fd5b8063d5b8da7314610908578063d81381d51461093c57600080fd5b8063b349ba65116100b0578063b349ba651461086b578063c6a261d2146108b4578063d547741f146108e857600080fd5b8063aea3d96b146107f4578063b0c342291461081457600080fd5b8063954d09c9116101225780639f102855116101075780639f10285514610794578063a1885700146107b4578063a56d92ce146107d457600080fd5b8063954d09c91461071b578063955b15901461076757600080fd5b80637644e7fa146106735780638da5cb5b146106a057806390d241f1146106cb57806391d14854146106eb57600080fd5b806338fe30251161020157806350a9cf67116101b55780636ccae0541161019a5780636ccae054146105f75780636e3c05621461061757806371c4717b1461063757600080fd5b806350a9cf67146105b75780635b94db27146105d757600080fd5b80633bd1adec116101e65780633bd1adec1461055557806343fa97ca1461056a5780634d1bf1891461058a57600080fd5b806338fe3025146104b65780633b13d3f1146104d657600080fd5b80631e867311116102585780632e7eb2581161023d5780632e7eb258146104565780632f2ff15d14610476578063308795b21461049657600080fd5b80631e867311146103ea57806320f99c0a1461040a57600080fd5b80626fc3e2146102895780630cd55abf146102f957806311cf8aa5146103345780631ba8e484146103c8575b600080fd5b34801561029557600080fd5b506102d36102a4366004612d27565b60046020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561030557600080fd5b50610326610314366004612d53565b60056020526000908152604090205481565b6040519081526020016102f0565b34801561034057600080fd5b5061039b61034f366004612d70565b600a6020526000908152604090205469ffffffffffffffffffff808216916a01000000000000000000008104821691740100000000000000000000000000000000000000009091041683565b6040805169ffffffffffffffffffff948516815292841660208401529216918101919091526060016102f0565b3480156103d457600080fd5b506103e86103e3366004612d8b565b6109e6565b005b3480156103f657600080fd5b506103e8610405366004612e17565b610a47565b34801561041657600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f0565b34801561046257600080fd5b506103e8610471366004612d8b565b610bed565b34801561048257600080fd5b506103e8610491366004612eb1565b610c49565b3480156104a257600080fd5b506103e86104b1366004612f23565b610ca8565b3480156104c257600080fd5b506102d36104d1366004612f8b565b610ede565b3480156104e257600080fd5b506103e86104f1366004612fea565b33600090815260066020908152604080832063ffffffff9590951683529390529190912080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909216919091179055565b34801561056157600080fd5b506103e8610ef5565b34801561057657600080fd5b506103e8610585366004612e17565b610f51565b34801561059657600080fd5b506103266105a5366004612d70565b60096020526000908152604090205481565b3480156105c357600080fd5b506103e86105d2366004613014565b6110ed565b3480156105e357600080fd5b506103e86105f2366004612d53565b6112eb565b34801561060357600080fd5b506103e8610612366004613090565b6113ab565b34801561062357600080fd5b506103e8610632366004612fea565b61144e565b61064a6106453660046130d1565b6116f3565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152016102f0565b34801561067f57600080fd5b5061032661068e366004612d70565b60086020526000908152604090205481565b3480156106ac57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610431565b3480156106d757600080fd5b506103e86106e636600461316e565b6119ac565b3480156106f757600080fd5b5061070b610706366004612eb1565b611baa565b60405190151581526020016102f0565b34801561072757600080fd5b5061073b6107363660046131e2565b611be7565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683529015156020830152016102f0565b34801561077357600080fd5b50610326610782366004612d70565b60076020526000908152604090205481565b3480156107a057600080fd5b506103e86107af366004612f23565b611cdb565b3480156107c057600080fd5b506103e86107cf366004612f23565b611f05565b3480156107e057600080fd5b506103e86107ef3660046132bb565b61212f565b34801561080057600080fd5b5061064a61080f3660046132dd565b6121a7565b34801561082057600080fd5b5061064a61082f366004612d70565b6003602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b34801561087757600080fd5b5061089f7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016102f0565b3480156108c057600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b3480156108f457600080fd5b506103e8610903366004612eb1565b612212565b34801561091457600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b34801561094857600080fd5b506102d3610957366004612d27565b60066020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b34801561099257600080fd5b506103e86109a1366004613339565b61226d565b3480156109b257600080fd5b5061070b6109c1366004612d8b565b6124a6565b3480156109d257600080fd5b506103e86109e1366004613365565b6124bd565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a37576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a4283838361252c565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a98576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610aa75750848314155b15610ade576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110610afe57610afe6133a3565b9050602002016020810190610b139190612d70565b63ffffffff161115610b9357610b8e888883818110610b3457610b346133a3565b90506020020135878784818110610b4d57610b4d6133a3565b9050602002016020810190610b629190612d70565b868685818110610b7457610b746133a3565b9050602002016020810190610b899190612d53565b61252c565b610bdb565b610bdb888883818110610ba857610ba86133a3565b90506020020135858584818110610bc157610bc16133a3565b9050602002016020810190610bd69190612d53565b612569565b600101610ae2565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c3e576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a428383836125ec565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c9a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612629565b5050565b604080517f5498237e9cba7720b9d4b88ac1ad78e4c78dae0cb7b6b33a329e330ca9349f8f602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991610daa918790879060e4016133d2565b602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190613426565b9050610e1e7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614610e84576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260086020908152604091829020879055815192835282018690527f9e2bb394655fb30d5d70b657711b435d31ad553885bfea5d029d96b4cc82dc7a91015b60405180910390a1505050505050565b6000610eec85858585612742565b95945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f46576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f4f336127ec565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fa2576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610fb15750848314155b15610fe8576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110611008576110086133a3565b905060200201602081019061101d9190612d70565b63ffffffff16111561109d5761109888888381811061103e5761103e6133a3565b90506020020135878784818110611057576110576133a3565b905060200201602081019061106c9190612d70565b86868581811061107e5761107e6133a3565b90506020020160208101906110939190612d53565b6125ec565b6110e5565b6110e58888838181106110b2576110b26133a3565b905060200201358585848181106110cb576110cb6133a3565b90506020020160208101906110e09190612d53565b612629565b600101610fec565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397aba7f97ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab6307f0000000000000000000000000000000000000000000000000000000000000000898b8a604051602001611186969594939291906134aa565b6040516020818303038152906040528051906020012085856040518463ffffffff1660e01b81526004016111bc939291906133d2565b602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613426565b90506112307f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611296576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff85166000908152600a6020526040902084906112b78282613501565b9050507fb2f6c1f8eb5fbd0c54cd0ffc1e20678d7e991cb8aed8471c1252cdc7d64549be8585604051610ece9291906135fb565b60005473ffffffffffffffffffffffffffffffffffffffff16331461133c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661143d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b611448848484612864565b50505050565b63ffffffff82166000908152600360205260409020546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000009092041610156114c6576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82166000908152600360205260409020805482919060109061151490849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166341805c246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db9190613426565b6040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8516600482015290915073ffffffffffffffffffffffffffffffffffffffff82169063a9a541b2906fffffffffffffffffffffffffffffffff8516906024016000604051808303818588803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8616815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8716918101919091527fb8fee8df7dff1cee6b16775bb2292a5341317514d9c5399dd2a62303e3f92c1a935060600191506116e69050565b60405180910390a1505050565b6000806fffffffffffffffffffffffffffffffff341061173f576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260066020908152604080832063ffffffff8c16845290915290205434906117959085906fffffffffffffffffffffffffffffffff166136a3565b915060006117a58e8e8e8d612742565b905060006117b389836136d2565b9050806117c08b866136d2565b6117ca91906136d2565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff161015611827576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b896118328585613644565b61183c9190613644565b63ffffffff8c166000908152600360209081526040918290208251808401845290546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041691810191909152815180830190925280519297509181906118ac9089906136d2565b6fffffffffffffffffffffffffffffffff1681526020018683602001516118d391906136d2565b6fffffffffffffffffffffffffffffffff90811690915263ffffffff8e1660008181526003602090815260408083208651968301518616700100000000000000000000000000000000029686169690961790955573ffffffffffffffffffffffffffffffffffffffff8d168252600481528482209282529190915291822080548e939192611963918591166136d2565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050509a509a98505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff871684529091529020546fffffffffffffffffffffffffffffffff80831691161015611a31576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff8716845290915281208054839290611a899084906fffffffffffffffffffffffffffffffff16613644565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8616600482015273ffffffffffffffffffffffffffffffffffffffff8516925063a9a541b2918416906024016000604051808303818588803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8716815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8616918101919091527fe7ea372fbcab98f6f74f62c16d1127e475529579f63121bf168773850739e3f9935060600191506116e69050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397aba7f985856040518363ffffffff1660e01b8152600401611c459291906136fb565b602060405180830381865afa158015611c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c869190613426565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f59aaad84481dba1ea935653b992572e94234e3bd8a15f7adf9511af432a4fd4f602052604090205490925060ff165b90509250929050565b604080517f097d8e0ecdafcc3ab6916c2b486af7d06325dcdf5bd46372f340eea8cffd674c602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991611ddd918790879060e4016133d2565b602060405180830381865afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190613426565b9050611e517f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611eb7576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260076020908152604091829020879055815192835282018690527fcaade52e9295f5cd4e1762d70bf40bf839fbbc232469ca3c7ac0de77d156d4889101610ece565b604080517f6ae815499d9e0b180f1f7632798b7dfd6565f2ed8e2745b19af5de7bde5e62aa602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991612007918790879060e4016133d2565b602060405180830381865afa158015612024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120489190613426565b905061207b7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902080546001810190915586146120e1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260096020908152604091829020879055815192835282018690527ff31f7eb11567a8d1fd792197d4328a9b4514b8fe89a70807e29132ce2b8e93f09101610ece565b8160f881901c60008190036121445750505050565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216808410156121a0576040517f78f38f7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806121b688888887612742565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260066020908152604080832063ffffffff9097168352959052939093205491976fffffffffffffffffffffffffffffffff909216965090945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612263576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612569565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166122fa576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b73ffffffffffffffffffffffffffffffffffffffff8216612347576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84166000908152600360205260409020546fffffffffffffffffffffffffffffffff808516911610156123ab576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8416600090815260036020526040812080548592906123e29084906fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061243482846fffffffffffffffffffffffffffffffff16612954565b6040805173ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff861660208201526fffffffffffffffffffffffffffffffff85168183015290517fb2d1c6b6dcf53eb15f8fb6c88a3642c4d7407333bcd0e16d6e5789f6beb51fb99181900360600190a150505050565b60006124b38484846129c9565b90505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a42576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838360405160200161255192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610a42838360405160200161261192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611448576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b6000611388841115612780576040517f492f620d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061278c8385612a57565b612797878786612b71565b6127a1919061376f565b90506fffffffffffffffffffffffffffffffff8110610eec576040517fc9034e1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff82166128b1576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016128f857610a428282612954565b8273ffffffffffffffffffffffffffffffffffffffff163b600003612949576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838383612c1a565b600080600080600085875af1905080610a42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401611434565b60006124b384846040516020016129f092919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60008160f881901c808303612a7157600092505050611be1565b63ffffffff85166000908152600860205260409020547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690811015612ae3576040517f508aaf0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260096020526040902054811115612b32576040517f5dffc92f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040902054670de0b6b3a764000090612b5d908390613782565b612b679190613799565b9695505050505050565b63ffffffff81166000908152600a602090815260408083208151606081018352905469ffffffffffffffffffff80821683526a01000000000000000000008204811694830185905274010000000000000000000000000000000000000000909104169181019190915290612be59085613782565b6040820151825169ffffffffffffffffffff91821691612c06911688613782565b612c10919061376f565b610eec919061376f565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401611434565b73ffffffffffffffffffffffffffffffffffffffff81168114612d0b57600080fd5b50565b803563ffffffff81168114612d2257600080fd5b919050565b60008060408385031215612d3a57600080fd5b8235612d4581612ce9565b9150611cd260208401612d0e565b600060208284031215612d6557600080fd5b81356124b681612ce9565b600060208284031215612d8257600080fd5b611bde82612d0e565b600080600060608486031215612da057600080fd5b83359250612db060208501612d0e565b91506040840135612dc081612ce9565b809150509250925092565b60008083601f840112612ddd57600080fd5b50813567ffffffffffffffff811115612df557600080fd5b6020830191508360208260051b8501011115612e1057600080fd5b9250929050565b60008060008060008060608789031215612e3057600080fd5b863567ffffffffffffffff80821115612e4857600080fd5b612e548a838b01612dcb565b90985096506020890135915080821115612e6d57600080fd5b612e798a838b01612dcb565b90965094506040890135915080821115612e9257600080fd5b50612e9f89828a01612dcb565b979a9699509497509295939492505050565b60008060408385031215612ec457600080fd5b823591506020830135612ed681612ce9565b809150509250929050565b60008083601f840112612ef357600080fd5b50813567ffffffffffffffff811115612f0b57600080fd5b602083019150836020828501011115612e1057600080fd5b600080600080600060808688031215612f3b57600080fd5b85359450612f4b60208701612d0e565b935060408601359250606086013567ffffffffffffffff811115612f6e57600080fd5b612f7a88828901612ee1565b969995985093965092949392505050565b60008060008060808587031215612fa157600080fd5b843593506020850135925060408501359150612fbf60608601612d0e565b905092959194509250565b80356fffffffffffffffffffffffffffffffff81168114612d2257600080fd5b60008060408385031215612ffd57600080fd5b61300683612d0e565b9150611cd260208401612fca565b600080600080600085870360c081121561302d57600080fd5b8635955061303d60208801612d0e565b945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561306f57600080fd5b5060408601925060a086013567ffffffffffffffff811115612f6e57600080fd5b6000806000606084860312156130a557600080fd5b83356130b081612ce9565b925060208401356130c081612ce9565b929592945050506040919091013590565b6000806000806000806000806000806101408b8d0312156130f157600080fd5b8a35995060208b0135985060408b0135975060608b0135965061311660808c01612d0e565b955061312460a08c01612fca565b945061313260c08c01612fca565b935060e08b013561314281612ce9565b92506101008b013561315381612ce9565b809250506101208b013590509295989b9194979a5092959850565b60008060006060848603121561318357600080fd5b61318c84612d0e565b9250602084013561319c81612ce9565b91506131aa60408501612fca565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156131f557600080fd5b82359150602083013567ffffffffffffffff8082111561321457600080fd5b818501915085601f83011261322857600080fd5b81358181111561323a5761323a6131b3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613280576132806131b3565b8160405282815288602084870101111561329957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156132ce57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156132f657600080fd5b8635955060208701359450604087013593506060870135925061331b60808801612d0e565b915060a087013561332b81612ce9565b809150509295509295509295565b60008060006060848603121561334e57600080fd5b61335784612d0e565b9250612db060208501612fca565b60008060006060848603121561337a57600080fd5b833561338581612ce9565b925061339360208501612fca565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b60006020828403121561343857600080fd5b81516124b681612ce9565b69ffffffffffffffffffff81168114612d0b57600080fd5b803561346681613443565b69ffffffffffffffffffff908116835260208201359061348582613443565b908116602084015260408201359061349c82613443565b808216604085015250505050565b86815273ffffffffffffffffffffffffffffffffffffffff8616602082015263ffffffff8581166040830152841660608201526080810183905261010081016134f660a083018461345b565b979650505050505050565b813561350c81613443565b69ffffffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffff000000000000000000008216178355602084013561355281613443565b73ffffffffffffffffffff000000000000000000008160501b16905080837fffffffffffffffffffffffff000000000000000000000000000000000000000084161717845560408501356135a581613443565b7dffffffffffffffffffff00000000000000000000000000000000000000008160a01b16847fffff0000000000000000000000000000000000000000000000000000000000008516178317178555505050505050565b63ffffffff83168152608081016124b6602083018461345b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6fffffffffffffffffffffffffffffffff82811682821603908082111561366d5761366d613615565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806136c6576136c6613674565b92169190910492915050565b6fffffffffffffffffffffffffffffffff81811683821601908082111561366d5761366d613615565b82815260006020604081840152835180604085015260005b8181101561372f57858101830151858201606001528201613713565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b80820180821115611be157611be1613615565b8082028115828204841417611be157611be1613615565b6000826137a8576137a8613674565b50049056fea2646970667358221220e6d2c3169e883ad10fafef3baf5308e527309cdc464d9f72ce5cc29ba4fb38be64736f6c63430008130033000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c183600000000000000000000000000000000000000000000000000000000000b67d20000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df0000000000000000000000001cadcd88fc148d3966ede75d029937c886f66009
Deployed Bytecode
0x6080604052600436106102845760003560e01c80637644e7fa11610153578063aea3d96b116100cb578063d5b8da731161007f578063de8c4ff911610064578063de8c4ff914610986578063ecb97484146109a6578063f1f069d6146109c657600080fd5b8063d5b8da7314610908578063d81381d51461093c57600080fd5b8063b349ba65116100b0578063b349ba651461086b578063c6a261d2146108b4578063d547741f146108e857600080fd5b8063aea3d96b146107f4578063b0c342291461081457600080fd5b8063954d09c9116101225780639f102855116101075780639f10285514610794578063a1885700146107b4578063a56d92ce146107d457600080fd5b8063954d09c91461071b578063955b15901461076757600080fd5b80637644e7fa146106735780638da5cb5b146106a057806390d241f1146106cb57806391d14854146106eb57600080fd5b806338fe30251161020157806350a9cf67116101b55780636ccae0541161019a5780636ccae054146105f75780636e3c05621461061757806371c4717b1461063757600080fd5b806350a9cf67146105b75780635b94db27146105d757600080fd5b80633bd1adec116101e65780633bd1adec1461055557806343fa97ca1461056a5780634d1bf1891461058a57600080fd5b806338fe3025146104b65780633b13d3f1146104d657600080fd5b80631e867311116102585780632e7eb2581161023d5780632e7eb258146104565780632f2ff15d14610476578063308795b21461049657600080fd5b80631e867311146103ea57806320f99c0a1461040a57600080fd5b80626fc3e2146102895780630cd55abf146102f957806311cf8aa5146103345780631ba8e484146103c8575b600080fd5b34801561029557600080fd5b506102d36102a4366004612d27565b60046020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561030557600080fd5b50610326610314366004612d53565b60056020526000908152604090205481565b6040519081526020016102f0565b34801561034057600080fd5b5061039b61034f366004612d70565b600a6020526000908152604090205469ffffffffffffffffffff808216916a01000000000000000000008104821691740100000000000000000000000000000000000000009091041683565b6040805169ffffffffffffffffffff948516815292841660208401529216918101919091526060016102f0565b3480156103d457600080fd5b506103e86103e3366004612d8b565b6109e6565b005b3480156103f657600080fd5b506103e8610405366004612e17565b610a47565b34801561041657600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f0565b34801561046257600080fd5b506103e8610471366004612d8b565b610bed565b34801561048257600080fd5b506103e8610491366004612eb1565b610c49565b3480156104a257600080fd5b506103e86104b1366004612f23565b610ca8565b3480156104c257600080fd5b506102d36104d1366004612f8b565b610ede565b3480156104e257600080fd5b506103e86104f1366004612fea565b33600090815260066020908152604080832063ffffffff9590951683529390529190912080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909216919091179055565b34801561056157600080fd5b506103e8610ef5565b34801561057657600080fd5b506103e8610585366004612e17565b610f51565b34801561059657600080fd5b506103266105a5366004612d70565b60096020526000908152604090205481565b3480156105c357600080fd5b506103e86105d2366004613014565b6110ed565b3480156105e357600080fd5b506103e86105f2366004612d53565b6112eb565b34801561060357600080fd5b506103e8610612366004613090565b6113ab565b34801561062357600080fd5b506103e8610632366004612fea565b61144e565b61064a6106453660046130d1565b6116f3565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152016102f0565b34801561067f57600080fd5b5061032661068e366004612d70565b60086020526000908152604090205481565b3480156106ac57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610431565b3480156106d757600080fd5b506103e86106e636600461316e565b6119ac565b3480156106f757600080fd5b5061070b610706366004612eb1565b611baa565b60405190151581526020016102f0565b34801561072757600080fd5b5061073b6107363660046131e2565b611be7565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683529015156020830152016102f0565b34801561077357600080fd5b50610326610782366004612d70565b60076020526000908152604090205481565b3480156107a057600080fd5b506103e86107af366004612f23565b611cdb565b3480156107c057600080fd5b506103e86107cf366004612f23565b611f05565b3480156107e057600080fd5b506103e86107ef3660046132bb565b61212f565b34801561080057600080fd5b5061064a61080f3660046132dd565b6121a7565b34801561082057600080fd5b5061064a61082f366004612d70565b6003602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b34801561087757600080fd5b5061089f7f00000000000000000000000000000000000000000000000000000000000b67d281565b60405163ffffffff90911681526020016102f0565b3480156108c057600080fd5b506104317f0000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df81565b3480156108f457600080fd5b506103e8610903366004612eb1565b612212565b34801561091457600080fd5b506104317f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600981565b34801561094857600080fd5b506102d3610957366004612d27565b60066020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b34801561099257600080fd5b506103e86109a1366004613339565b61226d565b3480156109b257600080fd5b5061070b6109c1366004612d8b565b6124a6565b3480156109d257600080fd5b506103e86109e1366004613365565b6124bd565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a37576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a4283838361252c565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a98576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610aa75750848314155b15610ade576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110610afe57610afe6133a3565b9050602002016020810190610b139190612d70565b63ffffffff161115610b9357610b8e888883818110610b3457610b346133a3565b90506020020135878784818110610b4d57610b4d6133a3565b9050602002016020810190610b629190612d70565b868685818110610b7457610b746133a3565b9050602002016020810190610b899190612d53565b61252c565b610bdb565b610bdb888883818110610ba857610ba86133a3565b90506020020135858584818110610bc157610bc16133a3565b9050602002016020810190610bd69190612d53565b612569565b600101610ae2565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c3e576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a428383836125ec565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c9a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612629565b5050565b604080517f5498237e9cba7720b9d4b88ac1ad78e4c78dae0cb7b6b33a329e330ca9349f8f602080830191909152308284015263ffffffff7f00000000000000000000000000000000000000000000000000000000000b67d2811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600916916397aba7f991610daa918790879060e4016133d2565b602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190613426565b9050610e1e7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614610e84576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260086020908152604091829020879055815192835282018690527f9e2bb394655fb30d5d70b657711b435d31ad553885bfea5d029d96b4cc82dc7a91015b60405180910390a1505050505050565b6000610eec85858585612742565b95945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f46576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f4f336127ec565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fa2576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610fb15750848314155b15610fe8576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110611008576110086133a3565b905060200201602081019061101d9190612d70565b63ffffffff16111561109d5761109888888381811061103e5761103e6133a3565b90506020020135878784818110611057576110576133a3565b905060200201602081019061106c9190612d70565b86868581811061107e5761107e6133a3565b90506020020160208101906110939190612d53565b6125ec565b6110e5565b6110e58888838181106110b2576110b26133a3565b905060200201358585848181106110cb576110cb6133a3565b90506020020160208101906110e09190612d53565b612629565b600101610fec565b60007f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600973ffffffffffffffffffffffffffffffffffffffff166397aba7f97ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab6307f00000000000000000000000000000000000000000000000000000000000b67d2898b8a604051602001611186969594939291906134aa565b6040516020818303038152906040528051906020012085856040518463ffffffff1660e01b81526004016111bc939291906133d2565b602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613426565b90506112307f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611296576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff85166000908152600a6020526040902084906112b78282613501565b9050507fb2f6c1f8eb5fbd0c54cd0ffc1e20678d7e991cb8aed8471c1252cdc7d64549be8585604051610ece9291906135fb565b60005473ffffffffffffffffffffffffffffffffffffffff16331461133c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661143d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b611448848484612864565b50505050565b63ffffffff82166000908152600360205260409020546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000009092041610156114c6576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82166000908152600360205260409020805482919060109061151490849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060007f0000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df73ffffffffffffffffffffffffffffffffffffffff166341805c246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db9190613426565b6040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8516600482015290915073ffffffffffffffffffffffffffffffffffffffff82169063a9a541b2906fffffffffffffffffffffffffffffffff8516906024016000604051808303818588803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8616815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8716918101919091527fb8fee8df7dff1cee6b16775bb2292a5341317514d9c5399dd2a62303e3f92c1a935060600191506116e69050565b60405180910390a1505050565b6000806fffffffffffffffffffffffffffffffff341061173f576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260066020908152604080832063ffffffff8c16845290915290205434906117959085906fffffffffffffffffffffffffffffffff166136a3565b915060006117a58e8e8e8d612742565b905060006117b389836136d2565b9050806117c08b866136d2565b6117ca91906136d2565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff161015611827576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b896118328585613644565b61183c9190613644565b63ffffffff8c166000908152600360209081526040918290208251808401845290546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041691810191909152815180830190925280519297509181906118ac9089906136d2565b6fffffffffffffffffffffffffffffffff1681526020018683602001516118d391906136d2565b6fffffffffffffffffffffffffffffffff90811690915263ffffffff8e1660008181526003602090815260408083208651968301518616700100000000000000000000000000000000029686169690961790955573ffffffffffffffffffffffffffffffffffffffff8d168252600481528482209282529190915291822080548e939192611963918591166136d2565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050509a509a98505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff871684529091529020546fffffffffffffffffffffffffffffffff80831691161015611a31576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff8716845290915281208054839290611a899084906fffffffffffffffffffffffffffffffff16613644565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8616600482015273ffffffffffffffffffffffffffffffffffffffff8516925063a9a541b2918416906024016000604051808303818588803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8716815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8616918101919091527fe7ea372fbcab98f6f74f62c16d1127e475529579f63121bf168773850739e3f9935060600191506116e69050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b6000807f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600973ffffffffffffffffffffffffffffffffffffffff166397aba7f985856040518363ffffffff1660e01b8152600401611c459291906136fb565b602060405180830381865afa158015611c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c869190613426565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f59aaad84481dba1ea935653b992572e94234e3bd8a15f7adf9511af432a4fd4f602052604090205490925060ff165b90509250929050565b604080517f097d8e0ecdafcc3ab6916c2b486af7d06325dcdf5bd46372f340eea8cffd674c602080830191909152308284015263ffffffff7f00000000000000000000000000000000000000000000000000000000000b67d2811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600916916397aba7f991611ddd918790879060e4016133d2565b602060405180830381865afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190613426565b9050611e517f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611eb7576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260076020908152604091829020879055815192835282018690527fcaade52e9295f5cd4e1762d70bf40bf839fbbc232469ca3c7ac0de77d156d4889101610ece565b604080517f6ae815499d9e0b180f1f7632798b7dfd6565f2ed8e2745b19af5de7bde5e62aa602080830191909152308284015263ffffffff7f00000000000000000000000000000000000000000000000000000000000b67d2811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600916916397aba7f991612007918790879060e4016133d2565b602060405180830381865afa158015612024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120489190613426565b905061207b7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902080546001810190915586146120e1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260096020908152604091829020879055815192835282018690527ff31f7eb11567a8d1fd792197d4328a9b4514b8fe89a70807e29132ce2b8e93f09101610ece565b8160f881901c60008190036121445750505050565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216808410156121a0576040517f78f38f7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806121b688888887612742565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260066020908152604080832063ffffffff9097168352959052939093205491976fffffffffffffffffffffffffffffffff909216965090945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612263576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612569565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166122fa576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b73ffffffffffffffffffffffffffffffffffffffff8216612347576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84166000908152600360205260409020546fffffffffffffffffffffffffffffffff808516911610156123ab576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8416600090815260036020526040812080548592906123e29084906fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061243482846fffffffffffffffffffffffffffffffff16612954565b6040805173ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff861660208201526fffffffffffffffffffffffffffffffff85168183015290517fb2d1c6b6dcf53eb15f8fb6c88a3642c4d7407333bcd0e16d6e5789f6beb51fb99181900360600190a150505050565b60006124b38484846129c9565b90505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df1614610a42576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838360405160200161255192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610a42838360405160200161261192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611448576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b6000611388841115612780576040517f492f620d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061278c8385612a57565b612797878786612b71565b6127a1919061376f565b90506fffffffffffffffffffffffffffffffff8110610eec576040517fc9034e1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff82166128b1576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016128f857610a428282612954565b8273ffffffffffffffffffffffffffffffffffffffff163b600003612949576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838383612c1a565b600080600080600085875af1905080610a42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401611434565b60006124b384846040516020016129f092919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60008160f881901c808303612a7157600092505050611be1565b63ffffffff85166000908152600860205260409020547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690811015612ae3576040517f508aaf0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260096020526040902054811115612b32576040517f5dffc92f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040902054670de0b6b3a764000090612b5d908390613782565b612b679190613799565b9695505050505050565b63ffffffff81166000908152600a602090815260408083208151606081018352905469ffffffffffffffffffff80821683526a01000000000000000000008204811694830185905274010000000000000000000000000000000000000000909104169181019190915290612be59085613782565b6040820151825169ffffffffffffffffffff91821691612c06911688613782565b612c10919061376f565b610eec919061376f565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401611434565b73ffffffffffffffffffffffffffffffffffffffff81168114612d0b57600080fd5b50565b803563ffffffff81168114612d2257600080fd5b919050565b60008060408385031215612d3a57600080fd5b8235612d4581612ce9565b9150611cd260208401612d0e565b600060208284031215612d6557600080fd5b81356124b681612ce9565b600060208284031215612d8257600080fd5b611bde82612d0e565b600080600060608486031215612da057600080fd5b83359250612db060208501612d0e565b91506040840135612dc081612ce9565b809150509250925092565b60008083601f840112612ddd57600080fd5b50813567ffffffffffffffff811115612df557600080fd5b6020830191508360208260051b8501011115612e1057600080fd5b9250929050565b60008060008060008060608789031215612e3057600080fd5b863567ffffffffffffffff80821115612e4857600080fd5b612e548a838b01612dcb565b90985096506020890135915080821115612e6d57600080fd5b612e798a838b01612dcb565b90965094506040890135915080821115612e9257600080fd5b50612e9f89828a01612dcb565b979a9699509497509295939492505050565b60008060408385031215612ec457600080fd5b823591506020830135612ed681612ce9565b809150509250929050565b60008083601f840112612ef357600080fd5b50813567ffffffffffffffff811115612f0b57600080fd5b602083019150836020828501011115612e1057600080fd5b600080600080600060808688031215612f3b57600080fd5b85359450612f4b60208701612d0e565b935060408601359250606086013567ffffffffffffffff811115612f6e57600080fd5b612f7a88828901612ee1565b969995985093965092949392505050565b60008060008060808587031215612fa157600080fd5b843593506020850135925060408501359150612fbf60608601612d0e565b905092959194509250565b80356fffffffffffffffffffffffffffffffff81168114612d2257600080fd5b60008060408385031215612ffd57600080fd5b61300683612d0e565b9150611cd260208401612fca565b600080600080600085870360c081121561302d57600080fd5b8635955061303d60208801612d0e565b945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561306f57600080fd5b5060408601925060a086013567ffffffffffffffff811115612f6e57600080fd5b6000806000606084860312156130a557600080fd5b83356130b081612ce9565b925060208401356130c081612ce9565b929592945050506040919091013590565b6000806000806000806000806000806101408b8d0312156130f157600080fd5b8a35995060208b0135985060408b0135975060608b0135965061311660808c01612d0e565b955061312460a08c01612fca565b945061313260c08c01612fca565b935060e08b013561314281612ce9565b92506101008b013561315381612ce9565b809250506101208b013590509295989b9194979a5092959850565b60008060006060848603121561318357600080fd5b61318c84612d0e565b9250602084013561319c81612ce9565b91506131aa60408501612fca565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156131f557600080fd5b82359150602083013567ffffffffffffffff8082111561321457600080fd5b818501915085601f83011261322857600080fd5b81358181111561323a5761323a6131b3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613280576132806131b3565b8160405282815288602084870101111561329957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156132ce57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156132f657600080fd5b8635955060208701359450604087013593506060870135925061331b60808801612d0e565b915060a087013561332b81612ce9565b809150509295509295509295565b60008060006060848603121561334e57600080fd5b61335784612d0e565b9250612db060208501612fca565b60008060006060848603121561337a57600080fd5b833561338581612ce9565b925061339360208501612fca565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b60006020828403121561343857600080fd5b81516124b681612ce9565b69ffffffffffffffffffff81168114612d0b57600080fd5b803561346681613443565b69ffffffffffffffffffff908116835260208201359061348582613443565b908116602084015260408201359061349c82613443565b808216604085015250505050565b86815273ffffffffffffffffffffffffffffffffffffffff8616602082015263ffffffff8581166040830152841660608201526080810183905261010081016134f660a083018461345b565b979650505050505050565b813561350c81613443565b69ffffffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffff000000000000000000008216178355602084013561355281613443565b73ffffffffffffffffffff000000000000000000008160501b16905080837fffffffffffffffffffffffff000000000000000000000000000000000000000084161717845560408501356135a581613443565b7dffffffffffffffffffff00000000000000000000000000000000000000008160a01b16847fffff0000000000000000000000000000000000000000000000000000000000008516178317178555505050505050565b63ffffffff83168152608081016124b6602083018461345b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6fffffffffffffffffffffffffffffffff82811682821603908082111561366d5761366d613615565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806136c6576136c6613674565b92169190910492915050565b6fffffffffffffffffffffffffffffffff81811683821601908082111561366d5761366d613615565b82815260006020604081840152835180604085015260005b8181101561372f57858101830151858201606001528201613713565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b80820180821115611be157611be1613615565b8082028115828204841417611be157611be1613615565b6000826137a8576137a8613674565b50049056fea2646970667358221220e6d2c3169e883ad10fafef3baf5308e527309cdc464d9f72ce5cc29ba4fb38be64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c183600000000000000000000000000000000000000000000000000000000000b67d20000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df0000000000000000000000001cadcd88fc148d3966ede75d029937c886f66009
-----Decoded View---------------
Arg [0] : owner_ (address): 0xB0BBff6311B7F245761A7846d3Ce7B1b100C1836
Arg [1] : chainSlug_ (uint32): 747474
Arg [2] : socket_ (address): 0x0CC93650bF4D98237628DACf87f94E443956D8dF
Arg [3] : signatureVerifier_ (address): 0x1CAdCd88fC148D3966eDe75D029937C886f66009
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b0bbff6311b7f245761a7846d3ce7b1b100c1836
Arg [1] : 00000000000000000000000000000000000000000000000000000000000b67d2
Arg [2] : 0000000000000000000000000cc93650bf4d98237628dacf87f94e443956d8df
Arg [3] : 0000000000000000000000001cadcd88fc148d3966ede75d029937c886f66009
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.