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