Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 2477164 | 195 days ago | Contract Creation | 0 ETH | |||
| 2477164 | 195 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SocketSimulator
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
// Sources flattened with hardhat v2.12.2 https://hardhat.org
// File contracts/utils/Ownable.sol
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_);
}
}
// File contracts/utils/AccessControl.sol
pragma solidity 0.8.19;
/**
* @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_];
}
}
// File contracts/interfaces/IDecapacitor.sol
pragma solidity 0.8.19;
/**
* @title IDecapacitor interface
* @notice Interface for a contract that verifies if a packed message is part of a packet or not
*/
interface IDecapacitor {
/**
* @notice Returns true if packed message is part of root.
* @param root_ root hash of the packet.
* @param packedMessage_ packed message which needs to be verified.
* @param proof_ proof used to determine the inclusion
* @dev This function is kept as view instead of pure, as in future we may have stateful decapacitors
* @return isIncluded boolean indicating whether the message is included in the packet or not.
*/
function verifyMessageInclusion(
bytes32 root_,
bytes32 packedMessage_,
bytes calldata proof_
) external returns (bool isIncluded);
}
// File contracts/utils/AccessRoles.sol
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");
// File lib/solmate/src/tokens/ERC20.sol
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);
}
}
// File lib/solmate/src/utils/SafeTransferLib.sol
pragma solidity >=0.8.0;
/// @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");
}
}
// File contracts/libraries/RescueFundsLib.sol
pragma solidity 0.8.19;
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_);
}
}
}
// File contracts/decapacitors/SingleDecapacitor.sol
pragma solidity 0.8.19;
/**
* @title SingleDecapacitor
* @notice A decapacitor that verifies messages by checking if the packed message is equal to the root.
* @dev This contract inherits from the `IDecapacitor` interface, which
* defines the functions for verifying message inclusion.
*/
contract SingleDecapacitor is IDecapacitor, AccessControl {
/**
* @notice Initializes the SingleDecapacitor contract with an owner address.
* @param owner_ The address of the contract owner
*/
constructor(address owner_) AccessControl(owner_) {
_grantRole(RESCUE_ROLE, owner_);
}
/**
* @inheritdoc IDecapacitor
* @dev Just checks if root equals packed message since each packet has single message.
* @dev Proof is ignored in this capacitor.
*/
function verifyMessageInclusion(
bytes32 root_,
bytes32 packedMessage_,
bytes calldata /* proof */
) external pure override returns (bool isIncluded) {
return root_ == packedMessage_;
}
/**
* @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_);
}
}
// File contracts/interfaces/ITransmitManager.sol
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;
}
// File contracts/interfaces/IExecutionManager.sol
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;
}
// File contracts/interfaces/ISocket.sol
pragma solidity 0.8.19;
/**
* @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);
}
// File contracts/interfaces/IHasher.sol
pragma solidity 0.8.19;
/**
* @title IHasher
* @notice Interface for hasher contract that calculates the packed message
*/
interface IHasher {
/**
* @notice returns the bytes32 hash of the message packed
* @param srcChainSlug src chain slug
* @param srcPlug address of plug at source
* @param dstChainSlug remote chain slug
* @param dstPlug address of plug at remote
* @param messageDetails contains message details, see ISocket for more details
*/
function packMessage(
uint32 srcChainSlug,
address srcPlug,
uint32 dstChainSlug,
address dstPlug,
ISocket.MessageDetails memory messageDetails
) external returns (bytes32);
}
// File contracts/interfaces/ISignatureVerifier.sol
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);
}
// File contracts/interfaces/ISwitchboard.sol
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;
}
// File contracts/interfaces/ICapacitor.sol
pragma solidity 0.8.19;
/**
* @title ICapacitor
* @dev Interface for a Capacitor contract that stores and manages messages in packets
*/
interface ICapacitor {
/**
* @notice adds the packed message to a packet
* @dev this should be only executable by socket
* @param packedMessage the message packed with payload, fees and config
*/
function addPackedMessage(bytes32 packedMessage) external;
/**
* @notice returns the latest packet details which needs to be sealed
* @return root root hash of the latest packet which is not yet sealed
* @return packetCount latest packet id which is not yet sealed
*/
function getNextPacketToBeSealed()
external
view
returns (bytes32 root, uint64 packetCount);
/**
* @notice returns the root of packet for given id
* @param id the id assigned to packet
* @return root root hash corresponding to given id
*/
function getRootByCount(uint64 id) external view returns (bytes32 root);
/**
* @notice returns the maxPacketLength
* @return maxPacketLength of the capacitor
*/
function getMaxPacketLength()
external
view
returns (uint256 maxPacketLength);
/**
* @notice seals the packet
* @dev indicates the packet is ready to be shipped and no more messages can be added now.
* @dev this should be called by socket only
* @param batchSize_ used with packet batching capacitors
* @return root root hash of the packet
* @return packetCount id of the packed sealed
*/
function sealPacket(
uint256 batchSize_
) external returns (bytes32 root, uint64 packetCount);
}
// File contracts/capacitors/BaseCapacitor.sol
pragma solidity 0.8.19;
/**
* @title BaseCapacitor
* @dev Abstract base contract for the Capacitors. Implements shared functionality and provides
* access control.
*/
abstract contract BaseCapacitor is ICapacitor, AccessControl {
/// address of socket
address public immutable socket;
/// an incrementing count for the next packet that is being created
uint64 internal _nextPacketCount;
/// tracks the count of next packet that will be sealed
uint64 internal _nextSealCount;
/// maps the packet count with the root hash of that packet
mapping(uint64 => bytes32) internal _roots;
// Error triggered when not called by socket
error OnlySocket();
/**
* @dev Throws if called by any account other than the socket.
*/
modifier onlySocket() {
if (msg.sender != socket) revert OnlySocket();
_;
}
/**
* @dev Initializes the contract with the specified socket address.
* @param socket_ The address of the socket contract.
* @param owner_ The address of the owner of the capacitor contract.
*/
constructor(address socket_, address owner_) AccessControl(owner_) {
socket = socket_;
_grantRole(RESCUE_ROLE, owner_);
}
/**
* @dev Returns the count of the latest packet that finished filling.
* @dev Returns 0 in case 0 or 1 packets are filled, hence this case should be considered by the caller
* @return lastFilledPacket count of the latest packet.
*/
function getLastFilledPacket()
external
view
returns (uint256 lastFilledPacket)
{
return _nextPacketCount == 0 ? 0 : _nextPacketCount - 1;
}
/**
* @dev Rescues funds from the contract.
* @param token_ The address of the token to rescue.
* @param rescueTo_ The address of the user to rescue tokens for.
* @param amount_ The amount of tokens to rescue.
*/
function rescueFunds(
address token_,
address rescueTo_,
uint256 amount_
) external onlyRole(RESCUE_ROLE) {
RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);
}
}
// File contracts/capacitors/SingleCapacitor.sol
pragma solidity 0.8.19;
/**
* @title SingleCapacitor
* @notice A capacitor that adds a single message to each packet.
* @dev This contract inherits from the `BaseCapacitor` contract, which provides the
* basic storage and common function implementations.
*/
contract SingleCapacitor is BaseCapacitor {
// Error triggered when no new packet/message is there to be sealed
error NoPendingPacket();
/**
* @notice emitted when a new message is added to a packet
* @param packedMessage the message packed with payload, fees and config
* @param packetCount an incremental id assigned to each new packet created on this capacitor
* @param newRootHash Hash of full packet. Same as packedMessage since this capacitor has one message per packet.
*/
event MessageAdded(
bytes32 packedMessage,
uint64 packetCount,
bytes32 newRootHash
);
/**
* @dev Initializes the contract with the specified socket address.
* @param socket_ The address of the socket contract.
* @param owner_ The address of the owner of the capacitor contract.
*/
constructor(
address socket_,
address owner_
) BaseCapacitor(socket_, owner_) {}
/**
* @inheritdoc ICapacitor
*/
function getMaxPacketLength() external pure override returns (uint256) {
return 1;
}
/**
* @inheritdoc ICapacitor
*/
function addPackedMessage(
bytes32 packedMessage_
) external override onlySocket {
uint64 packetCount = _nextPacketCount++;
_roots[packetCount] = packedMessage_;
// as it is a single capacitor, here root and packed message are same
emit MessageAdded(packedMessage_, packetCount, packedMessage_);
}
/**
* @inheritdoc ICapacitor
*/
function sealPacket(
uint256
) external override onlySocket returns (bytes32, uint64) {
uint64 packetCount = _nextSealCount++;
if (_roots[packetCount] == bytes32(0)) revert NoPendingPacket();
bytes32 root = _roots[packetCount];
return (root, packetCount);
}
/**
* @inheritdoc ICapacitor
*/
function getNextPacketToBeSealed()
external
view
override
returns (bytes32, uint64)
{
uint64 toSeal = _nextSealCount;
return (_roots[toSeal], toSeal);
}
/**
* @dev Returns the root hash of the packet with the specified count.
* @param count_ The count of the packet.
* @return The root hash of the packet.
*/
function getRootByCount(
uint64 count_
) external view override returns (bytes32) {
return _roots[count_];
}
}
// File contracts/interfaces/IPlug.sol
pragma solidity 0.8.19;
/**
* @title IPlug
* @notice Interface for a plug contract that executes the message received from a source chain.
*/
interface IPlug {
/**
* @dev this should be only executable by socket
* @notice executes the message received from source chain
* @notice It is expected to have original sender checks in the destination plugs using payload
* @param srcChainSlug_ chain slug of source
* @param payload_ the data which is needed by plug at inbound call on remote
*/
function inbound(
uint32 srcChainSlug_,
bytes calldata payload_
) external payable;
}
// File contracts/mocks/fee-updater/SocketSimulator.sol
pragma solidity 0.8.19;
interface ISimulatorUtils {
function checkTransmitter(
uint32 siblingSlug_,
bytes32 digest_,
bytes calldata signature_
) external view returns (address, bool);
function updateExecutionFees(address, uint128, bytes32) external view;
function verifyParams(
bytes32 executionParams_,
uint256 msgValue_
) external pure;
function isExecutor(
bytes32 packedMessage,
bytes memory sig
) external view returns (address executor, bool isValidExecutor);
}
contract SocketSimulator is AccessControl {
ISimulatorUtils public utils__;
ISignatureVerifier public signatureVerifier__;
IHasher public hasher__;
SingleCapacitor public capacitor;
bytes32 public immutable version;
uint32 public immutable chainSlug;
uint32 public immutable siblingChain;
address constant plug = address(12345);
mapping(address => uint32) public capacitorToSlug;
mapping(bytes32 => uint256) public proposalCount;
mapping(bytes32 => mapping(uint256 => mapping(address => bytes32)))
public packetIdRoots;
mapping(bytes32 => mapping(uint256 => mapping(address => uint256)))
public rootProposedAt;
mapping(bytes32 => bool) public messageExecuted;
struct PlugConfig {
// address of the sibling plug on the remote chain
address siblingPlug;
// capacitor instance for the outbound plug connection
ICapacitor capacitor__;
// decapacitor instance for the inbound plug connection
IDecapacitor decapacitor__;
// inbound switchboard instance for the plug connection
ISwitchboard inboundSwitchboard__;
// outbound switchboard instance for the plug connection
ISwitchboard outboundSwitchboard__;
}
// plug => remoteChainSlug => (siblingPlug, capacitor__, decapacitor__, inboundSwitchboard__, outboundSwitchboard__)
mapping(address => mapping(uint32 => PlugConfig)) internal _plugConfigs;
error InvalidCapacitorAddress();
error InvalidPacketId();
error MessageAlreadyExecuted();
error LowGasLimit();
error ErrInSourceValidation();
error PacketNotProposed();
error NotExecutor();
error VerificationFailed();
error InvalidProof();
event Sealed(
address indexed transmitter,
bytes32 indexed packetId,
uint256 batchSize,
bytes32 root,
bytes signature
);
event PacketProposed(
address indexed transmitter,
bytes32 indexed packetId,
uint256 proposalCount,
bytes32 root,
address switchboard
);
event ExecutionSuccess(bytes32 msgId);
constructor(
uint32 chainSlug_,
uint32 siblingChainSlug_,
address hasher_,
address signatureVerifier_,
string memory version_
) AccessControl(msg.sender) {
chainSlug = chainSlug_;
siblingChain = siblingChainSlug_;
version = keccak256(bytes(version_));
hasher__ = IHasher(hasher_);
signatureVerifier__ = ISignatureVerifier(signatureVerifier_);
}
function setup(address switchboard_, address utils_) external onlyOwner {
utils__ = ISimulatorUtils(utils_);
bytes32 packedMessage = hasher__.packMessage(
chainSlug,
plug,
siblingChain,
plug,
ISocket.MessageDetails(
bytes32(
(uint256(chainSlug) << 224) |
(uint256(uint160(plug)) << 64) |
0
),
0,
12000,
bytes32(0),
bytes("")
)
);
capacitor = new SingleCapacitor(address(this), msg.sender);
PlugConfig storage plugConfig = _plugConfigs[plug][siblingChain];
capacitorToSlug[address(capacitor)] = siblingChain;
plugConfig.siblingPlug = plug;
plugConfig.capacitor__ = capacitor;
plugConfig.decapacitor__ = new SingleDecapacitor(msg.sender);
plugConfig.inboundSwitchboard__ = ISwitchboard(switchboard_);
plugConfig.outboundSwitchboard__ = ISwitchboard(switchboard_);
plugConfig.capacitor__.addPackedMessage(packedMessage);
packetIdRoots[_encodePacketId(address(capacitor), 0)][0][
switchboard_
] = bytes32("random");
}
/**
* @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 onlyOwner {
uint32 siblingChainSlug = capacitorToSlug[capacitorAddress_];
if (siblingChain == 0) revert InvalidCapacitorAddress();
(bytes32 root, uint64 packetCount) = ICapacitor(capacitorAddress_)
.sealPacket(batchSize_);
bytes32 packetId = _encodePacketId(capacitorAddress_, packetCount);
(address transmitter, bool isTransmitter) = utils__.checkTransmitter(
siblingChain,
keccak256(abi.encode(version, siblingChain, packetId, root)),
signature_
);
if (siblingChain == 0) revert InvalidCapacitorAddress();
emit Sealed(transmitter, packetId, batchSize_, root, signature_);
}
function proposeForSwitchboard(
bytes32 packetId_,
bytes32 root_,
address switchboard_,
bytes calldata signature_
) external payable onlyOwner {
if (packetId_ == bytes32(0)) revert InvalidPacketId();
(address transmitter, bool isTransmitter) = utils__.checkTransmitter(
_decodeChainSlug(packetId_),
keccak256(abi.encode(version, chainSlug, packetId_, root_)),
signature_
);
if (packetId_ == bytes32(0)) revert InvalidPacketId();
packetIdRoots[packetId_][proposalCount[packetId_]][
switchboard_
] = root_;
rootProposedAt[packetId_][proposalCount[packetId_]][
switchboard_
] = block.timestamp;
emit PacketProposed(
transmitter,
packetId_,
proposalCount[packetId_]++,
root_,
switchboard_
);
}
function execute(
ISocket.ExecutionDetails calldata executionDetails_,
ISocket.MessageDetails calldata messageDetails_
) external payable onlyOwner {
// make sure message is not executed already
if (messageExecuted[messageDetails_.msgId])
revert MessageAlreadyExecuted();
// update state to make sure no reentrancy
messageExecuted[messageDetails_.msgId] = true;
// make sure caller is calling with right gas limits
// we also make sure to give executors the ability to execute with higher gas limits
// than the minimum required
if (
executionDetails_.executionGasLimit < messageDetails_.minMsgGasLimit
) revert LowGasLimit();
if (executionDetails_.packetId == bytes32(0)) revert InvalidPacketId();
// extract chain slug from msgID
uint32 remoteSlug = _decodeChainSlug(messageDetails_.msgId);
// make sure packet and msg are for the same chain
if (_decodeChainSlug(executionDetails_.packetId) != remoteSlug)
revert ErrInSourceValidation();
// extract plug address from msgID
address localPlug = _decodePlug(messageDetails_.msgId);
// fetch required vars from plug config
PlugConfig memory plugConfig;
plugConfig.decapacitor__ = _plugConfigs[localPlug][remoteSlug]
.decapacitor__;
plugConfig.siblingPlug = _plugConfigs[localPlug][remoteSlug]
.siblingPlug;
plugConfig.inboundSwitchboard__ = _plugConfigs[localPlug][remoteSlug]
.inboundSwitchboard__;
// fetch packet root
bytes32 packetRoot = packetIdRoots[executionDetails_.packetId][
executionDetails_.proposalCount
][address(plugConfig.inboundSwitchboard__)];
// if (packetRoot == bytes32(0)) revert PacketNotProposed();
// create packed message
bytes32 packedMessage = hasher__.packMessage(
remoteSlug,
plugConfig.siblingPlug,
chainSlug,
localPlug,
messageDetails_
);
// make sure caller is executor
(address executor, bool isValidExecutor) = utils__.isExecutor(
packedMessage,
executionDetails_.signature
);
if (!isValidExecutor) revert NotExecutor();
// finally make sure executor params were respected by the executor
utils__.verifyParams(messageDetails_.executionParams, msg.value);
// verify message was part of the packet and
// authenticated by respective switchboard
_verify(
executionDetails_.packetId,
executionDetails_.proposalCount,
remoteSlug,
packedMessage,
packetRoot,
plugConfig,
executionDetails_.decapacitorProof
);
// execute message
_execute(
executor,
localPlug,
remoteSlug,
executionDetails_.executionGasLimit,
messageDetails_
);
}
////////////////////////////////////////////////////////
////////////////// INTERNAL FUNCS //////////////////////
////////////////////////////////////////////////////////
function _verify(
bytes32 packetId_,
uint256 proposalCount_,
uint32 remoteChainSlug_,
bytes32 packedMessage_,
bytes32 packetRoot_,
PlugConfig memory plugConfig_,
bytes memory decapacitorProof_
) internal {
// NOTE: is the the first un-trusted call in the system, another one is Plug.inbound
if (
!ISwitchboard(plugConfig_.inboundSwitchboard__).allowPacket(
packetRoot_,
packetId_,
proposalCount_,
remoteChainSlug_,
rootProposedAt[packetId_][proposalCount_][
address(plugConfig_.inboundSwitchboard__)
]
)
) revert VerificationFailed();
if (
!plugConfig_.decapacitor__.verifyMessageInclusion(
packetRoot_,
packetRoot_,
decapacitorProof_
)
) revert InvalidProof();
}
/**
* This function assumes localPlug_ will have code while executing. As the message
* execution failure is not blocking the system, it is not necessary to check if
* code exists in the given address.
*/
function _execute(
address executor_,
address localPlug_,
uint32 remoteChainSlug_,
uint256 executionGasLimit_,
ISocket.MessageDetails memory messageDetails_
) internal {
// NOTE: external un-trusted call
// IPlug(localPlug_).inbound{gas: executionGasLimit_, value: msg.value}(
// remoteChainSlug_,
// messageDetails_.payload
// );
utils__.updateExecutionFees(
executor_,
uint128(messageDetails_.executionFee),
messageDetails_.msgId
);
emit ExecutionSuccess(messageDetails_.msgId);
}
/**
* @dev Decodes the plug address from a given message id.
* @param id_ The ID of the msg to decode the plug from.
* @return plug_ The address of sibling plug decoded from the message ID.
*/
function _decodePlug(bytes32 id_) internal pure returns (address plug_) {
plug_ = address(uint160(uint256(id_) >> 64));
}
/**
* @dev Decodes the chain ID from a given packet/message ID.
* @param id_ The ID of the packet/msg to decode the chain slug from.
* @return chainSlug_ The chain slug decoded from the packet/message ID.
*/
function _decodeChainSlug(
bytes32 id_
) internal pure returns (uint32 chainSlug_) {
chainSlug_ = uint32(uint256(id_) >> 224);
}
function _encodePacketId(
address capacitorAddress_,
uint64 packetCount_
) internal view returns (bytes32) {
return
bytes32(
(uint256(chainSlug) << 224) |
(uint256(uint160(capacitorAddress_)) << 64) |
packetCount_
);
}
}{
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint32","name":"chainSlug_","type":"uint32"},{"internalType":"uint32","name":"siblingChainSlug_","type":"uint32"},{"internalType":"address","name":"hasher_","type":"address"},{"internalType":"address","name":"signatureVerifier_","type":"address"},{"internalType":"string","name":"version_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ErrInSourceValidation","type":"error"},{"inputs":[],"name":"InvalidCapacitorAddress","type":"error"},{"inputs":[],"name":"InvalidPacketId","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"LowGasLimit","type":"error"},{"inputs":[],"name":"MessageAlreadyExecuted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NoPermit","type":"error"},{"inputs":[],"name":"NotExecutor","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"PacketNotProposed","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"msgId","type":"bytes32"}],"name":"ExecutionSuccess","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":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"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":"switchboard","type":"address"}],"name":"PacketProposed","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":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"bytes32","name":"packetId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"batchSize","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"}],"name":"Sealed","type":"event"},{"inputs":[],"name":"capacitor","outputs":[{"internalType":"contract SingleCapacitor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"capacitorToSlug","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"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":[{"components":[{"internalType":"bytes32","name":"packetId","type":"bytes32"},{"internalType":"uint256","name":"proposalCount","type":"uint256"},{"internalType":"uint256","name":"executionGasLimit","type":"uint256"},{"internalType":"bytes","name":"decapacitorProof","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ISocket.ExecutionDetails","name":"executionDetails_","type":"tuple"},{"components":[{"internalType":"bytes32","name":"msgId","type":"bytes32"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"minMsgGasLimit","type":"uint256"},{"internalType":"bytes32","name":"executionParams","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"}],"internalType":"struct ISocket.MessageDetails","name":"messageDetails_","type":"tuple"}],"name":"execute","outputs":[],"stateMutability":"payable","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":"role_","type":"bytes32"},{"internalType":"address","name":"address_","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasher__","outputs":[{"internalType":"contract IHasher","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"messageExecuted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"packetIdRoots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"packetId_","type":"bytes32"},{"internalType":"bytes32","name":"root_","type":"bytes32"},{"internalType":"address","name":"switchboard_","type":"address"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"proposeForSwitchboard","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"revokee_","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"rootProposedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"batchSize_","type":"uint256"},{"internalType":"address","name":"capacitorAddress_","type":"address"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"seal","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"switchboard_","type":"address"},{"internalType":"address","name":"utils_","type":"address"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"siblingChain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"signatureVerifier__","outputs":[{"internalType":"contract ISignatureVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"utils__","outputs":[{"internalType":"contract ISimulatorUtils","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620041fe380380620041fe833981016040819052620000349162000130565b3380620000418162000095565b505063ffffffff94851660a0529290931660c0528151602090920191909120608052600580546001600160a01b039283166001600160a01b0319918216179091556004805492909316911617905562000250565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b805163ffffffff81168114620000fd57600080fd5b919050565b80516001600160a01b0381168114620000fd57600080fd5b634e487b7160e01b600052604160045260246000fd5b600080600080600060a086880312156200014957600080fd5b6200015486620000e8565b9450602062000165818801620000e8565b9450620001756040880162000102565b9350620001856060880162000102565b60808801519093506001600160401b0380821115620001a357600080fd5b818901915089601f830112620001b857600080fd5b815181811115620001cd57620001cd6200011a565b604051601f8201601f19908116603f01168101908382118183101715620001f857620001f86200011a565b816040528281528c868487010111156200021157600080fd5b600093505b8284101562000235578484018601518185018701529285019262000216565b60008684830101528096505050505050509295509295909350565b60805160a05160c051613f2a620002d46000396000818161042001528181610c1f01528181610d2f01528181611202015281816113a101526114860152600081816104b90152818161086201528181610b6f01528181610f180152818161131f015261168f0152600081816103520152818161137b01526116640152613f2a6000f3fe6080604052600436106200019f5760003560e01c806379cfc00611620000e7578063c85ce3251162000089578063dc3098631162000060578063dc3098631462000575578063ea93a509146200058c578063fbe346b914620005c057600080fd5b8063c85ce325146200050a578063d547741f1462000521578063d5b8da73146200054657600080fd5b806391d1485411620000be57806391d14854146200046f578063b349ba6514620004a5578063b396910614620004db57600080fd5b806379cfc00614620003db5780638c576140146200040c5780638da5cb5b146200044257600080fd5b80633bd1adec116200015157806354fd4d50116200012857806354fd4d50146200033e5780635b94db2714620003745780635febe7e7146200039957600080fd5b80633bd1adec14620002a65780633c45c0a214620002be5780634ad701bc14620002ed57600080fd5b80632d34ba7911620001865780632d34ba79146200020f5780632f2ff15d146200023457806335dd0668146200025957600080fd5b806320f99c0a14620001a4578063275c41c914620001f6575b600080fd5b348015620001b157600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6200020d6200020736600462001ce3565b620005ef565b005b3480156200021c57600080fd5b506200020d6200022e36600462001d74565b62000abe565b3480156200024157600080fd5b506200020d6200025336600462001db2565b62000fc2565b3480156200026657600080fd5b50620002906200027836600462001dda565b60076020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001620001ed565b348015620002b357600080fd5b506200020d62001024565b348015620002cb57600080fd5b50600354620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b348015620002fa57600080fd5b506200032f6200030c36600462001dfa565b600960209081526000938452604080852082529284528284209052825290205481565b604051908152602001620001ed565b3480156200034b57600080fd5b506200032f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156200038157600080fd5b506200020d6200039336600462001dda565b62001083565b348015620003a657600080fd5b506200032f620003b836600462001dfa565b600a60209081526000938452604080852082529284528284209052825290205481565b348015620003e857600080fd5b506200032f620003fa36600462001e36565b60086020526000908152604090205481565b3480156200041957600080fd5b50620002907f000000000000000000000000000000000000000000000000000000000000000081565b3480156200044f57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620001cc565b3480156200047c57600080fd5b50620004946200048e36600462001db2565b62001144565b6040519015158152602001620001ed565b348015620004b257600080fd5b50620002907f000000000000000000000000000000000000000000000000000000000000000081565b348015620004e857600080fd5b50600554620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b6200020d6200051b36600462001e9c565b6200117f565b3480156200052e57600080fd5b506200020d6200054036600462001db2565b62001548565b3480156200055357600080fd5b50600454620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b6200020d6200058636600462001efe565b620015a6565b3480156200059957600080fd5b5062000494620005ab36600462001e36565b600b6020526000908152604090205460ff1681565b348015620005cd57600080fd5b50600654620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000641576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356000908152600b602052604090205460ff16156200068d576040517f7448c64c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356000908152600b60205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558082013590830135101562000709576040517fd38edae000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813562000742576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803560e090811c908335901c811462000787576040517fb39fb5d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a08101825260008082526020808301829052828401828152606084018381526080850184905273ffffffffffffffffffffffffffffffffffffffff8835871c8181168652600c855287862063ffffffff8a1687528552878620600281015483169094528354821687526003909301548116825289358552600984528685208a85013586528452868520915181168552925284832054600554855196517f02ea1431000000000000000000000000000000000000000000000000000000008152929691949316916302ea1431916200088f918991907f0000000000000000000000000000000000000000000000000000000000000000908a908d9060040162001fb7565b6020604051808303816000875af1158015620008af573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008d59190620020a9565b600354909150600090819073ffffffffffffffffffffffffffffffffffffffff1663954d09c9846200090b60808d018d620020c3565b6040518463ffffffff1660e01b81526004016200092b939291906200212b565b6040805180830381865afa15801562000948573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200096e919062002166565b9150915080620009aa576040517fc32d1d7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546040517fa56d92ce00000000000000000000000000000000000000000000000000000000815260608a0135600482015234602482015273ffffffffffffffffffffffffffffffffffffffff9091169063a56d92ce9060440160006040518083038186803b15801562000a1e57600080fd5b505afa15801562000a33573d6000803e3d6000fd5b5050505062000a9689600001358a602001358986888a8f806060019062000a5b9190620020c3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200186292505050565b62000ab382878960408d013562000aad8d6200224d565b62001a44565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000b10576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116919091179091556005546040805160a08101825269303900000000000000007f000000000000000000000000000000000000000000000000000000000000000060e081901b7fffffffff000000000000000000000000000000000000000000000000000000001691909117825260006020808401829052612ee0848601526060840182905284519081018552818152608084015292517f02ea1431000000000000000000000000000000000000000000000000000000008152929493909316926302ea14319262000c4a92613039917f0000000000000000000000000000000000000000000000000000000000000000918391600401620023a0565b6020604051808303816000875af115801562000c6a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c909190620020a9565b9050303360405162000ca29062001cae565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000ce3573d6000803e3d6000fd5b506006805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835563ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660008181527fe3a1db8431810d76ef2dd325ca493d95a1140de84ad6ad09c30c9d76ebf565ca6020908152604080832094835260079091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155815483166130391782559254600182018054909316941693909317905551339062000de09062001cbc565b73ffffffffffffffffffffffffffffffffffffffff9091168152602001604051809103906000f08015801562000e1a573d6000803e3d6000fd5b506002820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560038301805482168784169081179091556004808501805490931690911790915560018301546040517f920ee8a80000000000000000000000000000000000000000000000000000000081529182018590529091169063920ee8a890602401600060405180830381600087803b15801562000edb57600080fd5b505af115801562000ef0573d6000803e3d6000fd5b50506006547fffffffff000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060e01b167bffffffffffffffffffffffffffffffffffffffff0000000000000000604092831b1617600090815260096020908152828220828052815282822073ffffffffffffffffffffffffffffffffffffffff999099168252979097529095207f72616e646f6d000000000000000000000000000000000000000000000000000090555050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462001014576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001020828262001b2d565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331462001076576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010813362001bb3565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314620010d5576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314620011d1576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526007602052604081205463ffffffff908116917f000000000000000000000000000000000000000000000000000000000000000090911690036200125d576040517f73d817fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd7c9eaac00000000000000000000000000000000000000000000000000000000815260048101869052600090819073ffffffffffffffffffffffffffffffffffffffff87169063d7c9eaac9060240160408051808303816000875af1158015620012cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012f5919062002431565b909250905060007fffffffff000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060e01b167bffffffffffffffffffffffffffffffffffffffff0000000000000000604089901b161767ffffffffffffffff831617600354604080517f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000063ffffffff8116928201929092526060810184905260808101879052929350600092839273ffffffffffffffffffffffffffffffffffffffff169163b7ee4eb99160a001604051602081830303815290604052805190602001208b8b6040518563ffffffff1660e01b81526004016200143d949392919062002465565b6040805180830381865afa1580156200145a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001480919062002166565b915091507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16600003620014e5576040517f73d817fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828273ffffffffffffffffffffffffffffffffffffffff167f4bf575a0e4ff12a13816954b1ce8b1e53f30e121ea4f107ac086ec29da524abe8c888c8c60405162001534949392919062002497565b60405180910390a350505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146200159a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001020828262001c2b565b60005473ffffffffffffffffffffffffffffffffffffffff163314620015f8576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8462001630576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354600090819073ffffffffffffffffffffffffffffffffffffffff1663b7ee4eb96200165e8960e01c90565b604080517f0000000000000000000000000000000000000000000000000000000000000000602082015263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001691810191909152606081018b9052608081018a905260a0016040516020818303038152906040528051906020012087876040518563ffffffff1660e01b815260040162001700949392919062002465565b6040805180830381865afa1580156200171d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001743919062002166565b90925090508662001780576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087815260096020908152604080832060088084528285208054865291845282852073ffffffffffffffffffffffffffffffffffffffff808c168088529186528487208d90558d8752600a86528487208454885286528487209187529085529285204290558b855290925281548a93918616927f4b8e305abfc214d75df6e3d0b37dc1b2e6e93726d472df847f312d190dcf8704926200182183620024b9565b9091555060408051918252602082018b905273ffffffffffffffffffffffffffffffffffffffff8a169082015260600160405180910390a350505050505050565b6060820180516000898152600a602090815260408083208b84528252808320945173ffffffffffffffffffffffffffffffffffffffff908116845294909152908190205490517f4c40818000000000000000000000000000000000000000000000000000000000815260048101879052602481018b9052604481018a905263ffffffff891660648201526084810191909152911690634c4081809060a401602060405180830381865afa1580156200191e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001944919062002519565b6200197b576040517f439cc0cd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816040015173ffffffffffffffffffffffffffffffffffffffff16632d095c438485846040518463ffffffff1660e01b8152600401620019be9392919062002537565b6020604051808303816000875af1158015620019de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a04919062002519565b62001a3b576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600354602082015182516040517ff1f069d600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301526fffffffffffffffffffffffffffffffff9093166024820152604481019190915291169063f1f069d69060640160006040518083038186803b15801562001ad757600080fd5b505afa15801562001aec573d6000803e3d6000fd5b505082516040519081527fdc29884a71d2bb98d3c53dc09718be05c7bfd142b7773a5c5cf2517629290ac09250602001905060405180910390a15050505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610edb806200255983390190565b610ac1806200343483390190565b600060a0828403121562001cdd57600080fd5b50919050565b6000806040838503121562001cf757600080fd5b823567ffffffffffffffff8082111562001d1057600080fd5b62001d1e8683870162001cca565b9350602085013591508082111562001d3557600080fd5b5062001d448582860162001cca565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811462001d7157600080fd5b50565b6000806040838503121562001d8857600080fd5b823562001d958162001d4e565b9150602083013562001da78162001d4e565b809150509250929050565b6000806040838503121562001dc657600080fd5b82359150602083013562001da78162001d4e565b60006020828403121562001ded57600080fd5b8135620011788162001d4e565b60008060006060848603121562001e1057600080fd5b8335925060208401359150604084013562001e2b8162001d4e565b809150509250925092565b60006020828403121562001e4957600080fd5b5035919050565b60008083601f84011262001e6357600080fd5b50813567ffffffffffffffff81111562001e7c57600080fd5b60208301915083602082850101111562001e9557600080fd5b9250929050565b6000806000806060858703121562001eb357600080fd5b84359350602085013562001ec78162001d4e565b9250604085013567ffffffffffffffff81111562001ee457600080fd5b62001ef28782880162001e50565b95989497509550505050565b60008060008060006080868803121562001f1757600080fd5b8535945060208601359350604086013562001f328162001d4e565b9250606086013567ffffffffffffffff81111562001f4f57600080fd5b62001f5d8882890162001e50565b969995985093965092949392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600063ffffffff808816835273ffffffffffffffffffffffffffffffffffffffff808816602085015281871660408501528086166060850152505060a06080830152823560a0830152602083013560c0830152604083013560e0830152606083013561010083015260808301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126200205557600080fd5b830160208101903567ffffffffffffffff8111156200207357600080fd5b8036038213156200208357600080fd5b60a06101208501526200209c6101408501828462001f6e565b9998505050505050505050565b600060208284031215620020bc57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620020f957600080fd5b83018035915067ffffffffffffffff8211156200211557600080fd5b60200191503681900382131562001e9557600080fd5b8381526040602082015260006200214760408301848662001f6e565b95945050505050565b805180151581146200216157600080fd5b919050565b600080604083850312156200217a57600080fd5b8251620021878162001d4e565b9150620021976020840162002150565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715620021f557620021f5620021a0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620022455762002245620021a0565b604052919050565b600060a082360312156200226057600080fd5b6200226a620021cf565b82358152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115620022a857600080fd5b9085019036601f830112620022bc57600080fd5b813581811115620022d157620022d1620021a0565b62002303847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601620021fb565b915080825236848285010111156200231a57600080fd5b808484018584013760009082019093019290925250608082015292915050565b6000815180845260005b81811015620023625760208185018101518683018201520162002344565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600063ffffffff808816835273ffffffffffffffffffffffffffffffffffffffff808816602085015281871660408501528086166060850152505060a06080830152825160a0830152602083015160c0830152604083015160e08301526060830151610100830152608083015160a0610120840152620024256101408401826200233a565b98975050505050505050565b600080604083850312156200244557600080fd5b82519150602083015167ffffffffffffffff8116811462001da757600080fd5b63ffffffff851681528360208201526060604082015260006200248d60608301848662001f6e565b9695505050505050565b8481528360208201526060604082015260006200248d60608301848662001f6e565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002512577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6000602082840312156200252c57600080fd5b620011788262002150565b8381528260208201526060604082015260006200214760608301846200233a56fe60a060405234801561001057600080fd5b50604051610edb380380610edb83398101604081905261002f91610148565b8181808061003c8161007e565b50506001600160a01b0382166080526100757fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f29253826100d1565b5050505061017b565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b60008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b80516001600160a01b038116811461014357600080fd5b919050565b6000806040838503121561015b57600080fd5b6101648361012c565b91506101726020840161012c565b90509250929050565b608051610d376101a4600039600081816101430152818161056301526106cb0152610d376000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80636ccae054116100975780639471651e116100665780639471651e14610215578063d1af313c1461025d578063d547741f14610287578063d7c9eaac1461029a57600080fd5b80636ccae054146101ae5780638da5cb5b146101c157806391d14854146101df578063920ee8a81461020257600080fd5b80632ff9f2c9116100d35780632ff9f2c91461017a5780633bd1adec1461018b5780635b94db27146101935780636afc0f38146101a657600080fd5b806320f99c0a146100fa57806322c8f6cd1461013e5780632f2ff15d14610165575b600080fd5b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101147f000000000000000000000000000000000000000000000000000000000000000081565b610178610173366004610bbd565b6102ad565b005b60015b604051908152602001610135565b61017861030c565b6101786101a1366004610be9565b610368565b61017d610428565b6101786101bc366004610c04565b61046d565b60005473ffffffffffffffffffffffffffffffffffffffff16610114565b6101f26101ed366004610bbd565b610510565b6040519015158152602001610135565b610178610210366004610c40565b61054b565b60035468010000000000000000900467ffffffffffffffff16600081815260046020526040902054905b6040805192835267ffffffffffffffff909116602083015201610135565b61017d61026b366004610c59565b67ffffffffffffffff1660009081526004602052604090205490565b610178610295366004610bbd565b610655565b61023f6102a8366004610c40565b6106b0565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102fe576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61030882826107da565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461035d576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61036633610860565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103b9576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b60035460009067ffffffffffffffff161561045b576003546104569060019067ffffffffffffffff16610cb2565b61045e565b60005b67ffffffffffffffff16905090565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff166104ff576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b61050a8484846108d8565b50505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146105ba576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805460009167ffffffffffffffff90911690826105d883610cda565b82546101009290920a67ffffffffffffffff818102199093169183160217909155811660008181526004602090815260409182902086905581518681529081019290925281018490529091507f9ed9683bfff0f737f91f20945e98c912976d94e76860b05b48b15bc0d589be1f9060600160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a6576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61030882826109cd565b6000803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610722576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380546000916801000000000000000090910467ffffffffffffffff1690600861074c83610cda565b82546101009290920a67ffffffffffffffff81810219909316918316021790915581166000908152600460205260409020549091506107b7576040517fa902392300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526004602052604090205492509050915091565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff8216610925576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016109715761096c8282610a50565b505050565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036109c2576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61096c838383610ac5565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600080600080600085875af190508061096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016104f6565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061050a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016104f6565b803573ffffffffffffffffffffffffffffffffffffffff81168114610bb857600080fd5b919050565b60008060408385031215610bd057600080fd5b82359150610be060208401610b94565b90509250929050565b600060208284031215610bfb57600080fd5b61054482610b94565b600080600060608486031215610c1957600080fd5b610c2284610b94565b9250610c3060208501610b94565b9150604084013590509250925092565b600060208284031215610c5257600080fd5b5035919050565b600060208284031215610c6b57600080fd5b813567ffffffffffffffff8116811461054457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff828116828216039080821115610cd357610cd3610c83565b5092915050565b600067ffffffffffffffff808316818103610cf757610cf7610c83565b600101939250505056fea26469706673582212200e9ad1c7907b958bd17050e3a3e7333638ad97b82c9cf9912b5a59c257132e1f64736f6c63430008130033608060405234801561001057600080fd5b50604051610ac1380380610ac183398101604081905261002f9161011b565b808061003a8161006d565b5061006790507fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f29253826100c0565b5061014b565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b60008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b60006020828403121561012d57600080fd5b81516001600160a01b038116811461014457600080fd5b9392505050565b6109678061015a6000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635b94db27116100765780638da5cb5b1161005b5780638da5cb5b1461015357806391d1485414610171578063d547741f1461018457600080fd5b80635b94db271461012d5780636ccae0541461014057600080fd5b806320f99c0a146100a85780632d095c43146100ec5780632f2ff15d146101105780633bd1adec14610125575b600080fd5b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101006100fa366004610805565b50501490565b60405190151581526020016100e3565b61012361011e3660046108ae565b610197565b005b6101236101f6565b61012361013b3660046108da565b610252565b61012361014e3660046108f5565b610312565b60005473ffffffffffffffffffffffffffffffffffffffff166100c2565b61010061017f3660046108ae565b6103b5565b6101236101923660046108ae565b6103f0565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101e8576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f2828261044b565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610247576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610250336104d1565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102a3576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff166103a4576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6103af848484610549565b50505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610441576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f2828261063e565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff8216610596576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016105e2576105dd82826106c1565b505050565b8273ffffffffffffffffffffffffffffffffffffffff163b600003610633576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105dd838383610736565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600080600080600085875af19050806105dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015260640161039b565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806103af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161039b565b6000806000806060858703121561081b57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561084157600080fd5b818701915087601f83011261085557600080fd5b81358181111561086457600080fd5b88602082850101111561087657600080fd5b95989497505060200194505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108a957600080fd5b919050565b600080604083850312156108c157600080fd5b823591506108d160208401610885565b90509250929050565b6000602082840312156108ec57600080fd5b6103e982610885565b60008060006060848603121561090a57600080fd5b61091384610885565b925061092160208501610885565b915060408401359050925092509256fea2646970667358221220b917ec53e94feb877107d694f6da6360b795610f2218c1647ae6a87c371e46bc64736f6c63430008130033a26469706673582212206353e8f81b902fedbacedaf67d3e2fe64b4bf64aee0a9db06d373987c950bd8e64736f6c6343000813003300000000000000000000000000000000000000000000000000000000000b67d200000000000000000000000000000000000000000000000000000000000b67d20000000000000000000000009b8c323468aec7a7cb041ced48f92559bff337050000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004494d4c4900000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106200019f5760003560e01c806379cfc00611620000e7578063c85ce3251162000089578063dc3098631162000060578063dc3098631462000575578063ea93a509146200058c578063fbe346b914620005c057600080fd5b8063c85ce325146200050a578063d547741f1462000521578063d5b8da73146200054657600080fd5b806391d1485411620000be57806391d14854146200046f578063b349ba6514620004a5578063b396910614620004db57600080fd5b806379cfc00614620003db5780638c576140146200040c5780638da5cb5b146200044257600080fd5b80633bd1adec116200015157806354fd4d50116200012857806354fd4d50146200033e5780635b94db2714620003745780635febe7e7146200039957600080fd5b80633bd1adec14620002a65780633c45c0a214620002be5780634ad701bc14620002ed57600080fd5b80632d34ba7911620001865780632d34ba79146200020f5780632f2ff15d146200023457806335dd0668146200025957600080fd5b806320f99c0a14620001a4578063275c41c914620001f6575b600080fd5b348015620001b157600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6200020d6200020736600462001ce3565b620005ef565b005b3480156200021c57600080fd5b506200020d6200022e36600462001d74565b62000abe565b3480156200024157600080fd5b506200020d6200025336600462001db2565b62000fc2565b3480156200026657600080fd5b50620002906200027836600462001dda565b60076020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001620001ed565b348015620002b357600080fd5b506200020d62001024565b348015620002cb57600080fd5b50600354620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b348015620002fa57600080fd5b506200032f6200030c36600462001dfa565b600960209081526000938452604080852082529284528284209052825290205481565b604051908152602001620001ed565b3480156200034b57600080fd5b506200032f7f484f1c5889188a0a81068ce8c49d8f7c3b3f1b0c1723b50ebd656a8d4f99e35681565b3480156200038157600080fd5b506200020d6200039336600462001dda565b62001083565b348015620003a657600080fd5b506200032f620003b836600462001dfa565b600a60209081526000938452604080852082529284528284209052825290205481565b348015620003e857600080fd5b506200032f620003fa36600462001e36565b60086020526000908152604090205481565b3480156200041957600080fd5b50620002907f00000000000000000000000000000000000000000000000000000000000b67d281565b3480156200044f57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620001cc565b3480156200047c57600080fd5b50620004946200048e36600462001db2565b62001144565b6040519015158152602001620001ed565b348015620004b257600080fd5b50620002907f00000000000000000000000000000000000000000000000000000000000b67d281565b348015620004e857600080fd5b50600554620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b6200020d6200051b36600462001e9c565b6200117f565b3480156200052e57600080fd5b506200020d6200054036600462001db2565b62001548565b3480156200055357600080fd5b50600454620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b6200020d6200058636600462001efe565b620015a6565b3480156200059957600080fd5b5062000494620005ab36600462001e36565b600b6020526000908152604090205460ff1681565b348015620005cd57600080fd5b50600654620001cc9073ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000641576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356000908152600b602052604090205460ff16156200068d576040517f7448c64c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356000908152600b60205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558082013590830135101562000709576040517fd38edae000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813562000742576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803560e090811c908335901c811462000787576040517fb39fb5d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a08101825260008082526020808301829052828401828152606084018381526080850184905273ffffffffffffffffffffffffffffffffffffffff8835871c8181168652600c855287862063ffffffff8a1687528552878620600281015483169094528354821687526003909301548116825289358552600984528685208a85013586528452868520915181168552925284832054600554855196517f02ea1431000000000000000000000000000000000000000000000000000000008152929691949316916302ea1431916200088f918991907f00000000000000000000000000000000000000000000000000000000000b67d2908a908d9060040162001fb7565b6020604051808303816000875af1158015620008af573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008d59190620020a9565b600354909150600090819073ffffffffffffffffffffffffffffffffffffffff1663954d09c9846200090b60808d018d620020c3565b6040518463ffffffff1660e01b81526004016200092b939291906200212b565b6040805180830381865afa15801562000948573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200096e919062002166565b9150915080620009aa576040517fc32d1d7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546040517fa56d92ce00000000000000000000000000000000000000000000000000000000815260608a0135600482015234602482015273ffffffffffffffffffffffffffffffffffffffff9091169063a56d92ce9060440160006040518083038186803b15801562000a1e57600080fd5b505afa15801562000a33573d6000803e3d6000fd5b5050505062000a9689600001358a602001358986888a8f806060019062000a5b9190620020c3565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200186292505050565b62000ab382878960408d013562000aad8d6200224d565b62001a44565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000b10576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116919091179091556005546040805160a08101825269303900000000000000007f00000000000000000000000000000000000000000000000000000000000b67d260e081901b7fffffffff000000000000000000000000000000000000000000000000000000001691909117825260006020808401829052612ee0848601526060840182905284519081018552818152608084015292517f02ea1431000000000000000000000000000000000000000000000000000000008152929493909316926302ea14319262000c4a92613039917f00000000000000000000000000000000000000000000000000000000000b67d2918391600401620023a0565b6020604051808303816000875af115801562000c6a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c909190620020a9565b9050303360405162000ca29062001cae565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000ce3573d6000803e3d6000fd5b506006805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835563ffffffff7f00000000000000000000000000000000000000000000000000000000000b67d21660008181527fe3a1db8431810d76ef2dd325ca493d95a1140de84ad6ad09c30c9d76ebf565ca6020908152604080832094835260079091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155815483166130391782559254600182018054909316941693909317905551339062000de09062001cbc565b73ffffffffffffffffffffffffffffffffffffffff9091168152602001604051809103906000f08015801562000e1a573d6000803e3d6000fd5b506002820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560038301805482168784169081179091556004808501805490931690911790915560018301546040517f920ee8a80000000000000000000000000000000000000000000000000000000081529182018590529091169063920ee8a890602401600060405180830381600087803b15801562000edb57600080fd5b505af115801562000ef0573d6000803e3d6000fd5b50506006547fffffffff000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000b67d260e01b167bffffffffffffffffffffffffffffffffffffffff0000000000000000604092831b1617600090815260096020908152828220828052815282822073ffffffffffffffffffffffffffffffffffffffff999099168252979097529095207f72616e646f6d000000000000000000000000000000000000000000000000000090555050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462001014576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001020828262001b2d565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331462001076576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010813362001bb3565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314620010d5576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314620011d1576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526007602052604081205463ffffffff908116917f00000000000000000000000000000000000000000000000000000000000b67d290911690036200125d576040517f73d817fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd7c9eaac00000000000000000000000000000000000000000000000000000000815260048101869052600090819073ffffffffffffffffffffffffffffffffffffffff87169063d7c9eaac9060240160408051808303816000875af1158015620012cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012f5919062002431565b909250905060007fffffffff000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000b67d260e01b167bffffffffffffffffffffffffffffffffffffffff0000000000000000604089901b161767ffffffffffffffff831617600354604080517f484f1c5889188a0a81068ce8c49d8f7c3b3f1b0c1723b50ebd656a8d4f99e35660208201527f00000000000000000000000000000000000000000000000000000000000b67d263ffffffff8116928201929092526060810184905260808101879052929350600092839273ffffffffffffffffffffffffffffffffffffffff169163b7ee4eb99160a001604051602081830303815290604052805190602001208b8b6040518563ffffffff1660e01b81526004016200143d949392919062002465565b6040805180830381865afa1580156200145a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001480919062002166565b915091507f00000000000000000000000000000000000000000000000000000000000b67d263ffffffff16600003620014e5576040517f73d817fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828273ffffffffffffffffffffffffffffffffffffffff167f4bf575a0e4ff12a13816954b1ce8b1e53f30e121ea4f107ac086ec29da524abe8c888c8c60405162001534949392919062002497565b60405180910390a350505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146200159a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001020828262001c2b565b60005473ffffffffffffffffffffffffffffffffffffffff163314620015f8576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8462001630576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354600090819073ffffffffffffffffffffffffffffffffffffffff1663b7ee4eb96200165e8960e01c90565b604080517f484f1c5889188a0a81068ce8c49d8f7c3b3f1b0c1723b50ebd656a8d4f99e356602082015263ffffffff7f00000000000000000000000000000000000000000000000000000000000b67d21691810191909152606081018b9052608081018a905260a0016040516020818303038152906040528051906020012087876040518563ffffffff1660e01b815260040162001700949392919062002465565b6040805180830381865afa1580156200171d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001743919062002166565b90925090508662001780576040517fb21147c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087815260096020908152604080832060088084528285208054865291845282852073ffffffffffffffffffffffffffffffffffffffff808c168088529186528487208d90558d8752600a86528487208454885286528487209187529085529285204290558b855290925281548a93918616927f4b8e305abfc214d75df6e3d0b37dc1b2e6e93726d472df847f312d190dcf8704926200182183620024b9565b9091555060408051918252602082018b905273ffffffffffffffffffffffffffffffffffffffff8a169082015260600160405180910390a350505050505050565b6060820180516000898152600a602090815260408083208b84528252808320945173ffffffffffffffffffffffffffffffffffffffff908116845294909152908190205490517f4c40818000000000000000000000000000000000000000000000000000000000815260048101879052602481018b9052604481018a905263ffffffff891660648201526084810191909152911690634c4081809060a401602060405180830381865afa1580156200191e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001944919062002519565b6200197b576040517f439cc0cd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816040015173ffffffffffffffffffffffffffffffffffffffff16632d095c438485846040518463ffffffff1660e01b8152600401620019be9392919062002537565b6020604051808303816000875af1158015620019de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a04919062002519565b62001a3b576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600354602082015182516040517ff1f069d600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff89811660048301526fffffffffffffffffffffffffffffffff9093166024820152604481019190915291169063f1f069d69060640160006040518083038186803b15801562001ad757600080fd5b505afa15801562001aec573d6000803e3d6000fd5b505082516040519081527fdc29884a71d2bb98d3c53dc09718be05c7bfd142b7773a5c5cf2517629290ac09250602001905060405180910390a15050505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610edb806200255983390190565b610ac1806200343483390190565b600060a0828403121562001cdd57600080fd5b50919050565b6000806040838503121562001cf757600080fd5b823567ffffffffffffffff8082111562001d1057600080fd5b62001d1e8683870162001cca565b9350602085013591508082111562001d3557600080fd5b5062001d448582860162001cca565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff8116811462001d7157600080fd5b50565b6000806040838503121562001d8857600080fd5b823562001d958162001d4e565b9150602083013562001da78162001d4e565b809150509250929050565b6000806040838503121562001dc657600080fd5b82359150602083013562001da78162001d4e565b60006020828403121562001ded57600080fd5b8135620011788162001d4e565b60008060006060848603121562001e1057600080fd5b8335925060208401359150604084013562001e2b8162001d4e565b809150509250925092565b60006020828403121562001e4957600080fd5b5035919050565b60008083601f84011262001e6357600080fd5b50813567ffffffffffffffff81111562001e7c57600080fd5b60208301915083602082850101111562001e9557600080fd5b9250929050565b6000806000806060858703121562001eb357600080fd5b84359350602085013562001ec78162001d4e565b9250604085013567ffffffffffffffff81111562001ee457600080fd5b62001ef28782880162001e50565b95989497509550505050565b60008060008060006080868803121562001f1757600080fd5b8535945060208601359350604086013562001f328162001d4e565b9250606086013567ffffffffffffffff81111562001f4f57600080fd5b62001f5d8882890162001e50565b969995985093965092949392505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600063ffffffff808816835273ffffffffffffffffffffffffffffffffffffffff808816602085015281871660408501528086166060850152505060a06080830152823560a0830152602083013560c0830152604083013560e0830152606083013561010083015260808301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126200205557600080fd5b830160208101903567ffffffffffffffff8111156200207357600080fd5b8036038213156200208357600080fd5b60a06101208501526200209c6101408501828462001f6e565b9998505050505050505050565b600060208284031215620020bc57600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620020f957600080fd5b83018035915067ffffffffffffffff8211156200211557600080fd5b60200191503681900382131562001e9557600080fd5b8381526040602082015260006200214760408301848662001f6e565b95945050505050565b805180151581146200216157600080fd5b919050565b600080604083850312156200217a57600080fd5b8251620021878162001d4e565b9150620021976020840162002150565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715620021f557620021f5620021a0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620022455762002245620021a0565b604052919050565b600060a082360312156200226057600080fd5b6200226a620021cf565b82358152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115620022a857600080fd5b9085019036601f830112620022bc57600080fd5b813581811115620022d157620022d1620021a0565b62002303847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601620021fb565b915080825236848285010111156200231a57600080fd5b808484018584013760009082019093019290925250608082015292915050565b6000815180845260005b81811015620023625760208185018101518683018201520162002344565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600063ffffffff808816835273ffffffffffffffffffffffffffffffffffffffff808816602085015281871660408501528086166060850152505060a06080830152825160a0830152602083015160c0830152604083015160e08301526060830151610100830152608083015160a0610120840152620024256101408401826200233a565b98975050505050505050565b600080604083850312156200244557600080fd5b82519150602083015167ffffffffffffffff8116811462001da757600080fd5b63ffffffff851681528360208201526060604082015260006200248d60608301848662001f6e565b9695505050505050565b8481528360208201526060604082015260006200248d60608301848662001f6e565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002512577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6000602082840312156200252c57600080fd5b620011788262002150565b8381528260208201526060604082015260006200214760608301846200233a56fe60a060405234801561001057600080fd5b50604051610edb380380610edb83398101604081905261002f91610148565b8181808061003c8161007e565b50506001600160a01b0382166080526100757fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f29253826100d1565b5050505061017b565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b60008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b80516001600160a01b038116811461014357600080fd5b919050565b6000806040838503121561015b57600080fd5b6101648361012c565b91506101726020840161012c565b90509250929050565b608051610d376101a4600039600081816101430152818161056301526106cb0152610d376000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80636ccae054116100975780639471651e116100665780639471651e14610215578063d1af313c1461025d578063d547741f14610287578063d7c9eaac1461029a57600080fd5b80636ccae054146101ae5780638da5cb5b146101c157806391d14854146101df578063920ee8a81461020257600080fd5b80632ff9f2c9116100d35780632ff9f2c91461017a5780633bd1adec1461018b5780635b94db27146101935780636afc0f38146101a657600080fd5b806320f99c0a146100fa57806322c8f6cd1461013e5780632f2ff15d14610165575b600080fd5b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101147f000000000000000000000000000000000000000000000000000000000000000081565b610178610173366004610bbd565b6102ad565b005b60015b604051908152602001610135565b61017861030c565b6101786101a1366004610be9565b610368565b61017d610428565b6101786101bc366004610c04565b61046d565b60005473ffffffffffffffffffffffffffffffffffffffff16610114565b6101f26101ed366004610bbd565b610510565b6040519015158152602001610135565b610178610210366004610c40565b61054b565b60035468010000000000000000900467ffffffffffffffff16600081815260046020526040902054905b6040805192835267ffffffffffffffff909116602083015201610135565b61017d61026b366004610c59565b67ffffffffffffffff1660009081526004602052604090205490565b610178610295366004610bbd565b610655565b61023f6102a8366004610c40565b6106b0565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102fe576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61030882826107da565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461035d576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61036633610860565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103b9576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b60035460009067ffffffffffffffff161561045b576003546104569060019067ffffffffffffffff16610cb2565b61045e565b60005b67ffffffffffffffff16905090565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff166104ff576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b61050a8484846108d8565b50505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146105ba576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003805460009167ffffffffffffffff90911690826105d883610cda565b82546101009290920a67ffffffffffffffff818102199093169183160217909155811660008181526004602090815260409182902086905581518681529081019290925281018490529091507f9ed9683bfff0f737f91f20945e98c912976d94e76860b05b48b15bc0d589be1f9060600160405180910390a15050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106a6576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61030882826109cd565b6000803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610722576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380546000916801000000000000000090910467ffffffffffffffff1690600861074c83610cda565b82546101009290920a67ffffffffffffffff81810219909316918316021790915581166000908152600460205260409020549091506107b7576040517fa902392300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff811660009081526004602052604090205492509050915091565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff8216610925576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016109715761096c8282610a50565b505050565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036109c2576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61096c838383610ac5565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600080600080600085875af190508061096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c45440000000000000000000000000060448201526064016104f6565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061050a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016104f6565b803573ffffffffffffffffffffffffffffffffffffffff81168114610bb857600080fd5b919050565b60008060408385031215610bd057600080fd5b82359150610be060208401610b94565b90509250929050565b600060208284031215610bfb57600080fd5b61054482610b94565b600080600060608486031215610c1957600080fd5b610c2284610b94565b9250610c3060208501610b94565b9150604084013590509250925092565b600060208284031215610c5257600080fd5b5035919050565b600060208284031215610c6b57600080fd5b813567ffffffffffffffff8116811461054457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff828116828216039080821115610cd357610cd3610c83565b5092915050565b600067ffffffffffffffff808316818103610cf757610cf7610c83565b600101939250505056fea26469706673582212200e9ad1c7907b958bd17050e3a3e7333638ad97b82c9cf9912b5a59c257132e1f64736f6c63430008130033608060405234801561001057600080fd5b50604051610ac1380380610ac183398101604081905261002f9161011b565b808061003a8161006d565b5061006790507fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f29253826100c0565b5061014b565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b60008281526002602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b60006020828403121561012d57600080fd5b81516001600160a01b038116811461014457600080fd5b9392505050565b6109678061015a6000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635b94db27116100765780638da5cb5b1161005b5780638da5cb5b1461015357806391d1485414610171578063d547741f1461018457600080fd5b80635b94db271461012d5780636ccae0541461014057600080fd5b806320f99c0a146100a85780632d095c43146100ec5780632f2ff15d146101105780633bd1adec14610125575b600080fd5b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101006100fa366004610805565b50501490565b60405190151581526020016100e3565b61012361011e3660046108ae565b610197565b005b6101236101f6565b61012361013b3660046108da565b610252565b61012361014e3660046108f5565b610312565b60005473ffffffffffffffffffffffffffffffffffffffff166100c2565b61010061017f3660046108ae565b6103b5565b6101236101923660046108ae565b6103f0565b60005473ffffffffffffffffffffffffffffffffffffffff1633146101e8576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f2828261044b565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610247576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610250336104d1565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102a3576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff166103a4576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b6103af848484610549565b50505050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610441576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f2828261063e565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff8216610596576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016105e2576105dd82826106c1565b505050565b8273ffffffffffffffffffffffffffffffffffffffff163b600003610633576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105dd838383610736565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b600080600080600085875af19050806105dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c454400000000000000000000000000604482015260640161039b565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806103af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161039b565b6000806000806060858703121561081b57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561084157600080fd5b818701915087601f83011261085557600080fd5b81358181111561086457600080fd5b88602082850101111561087657600080fd5b95989497505060200194505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108a957600080fd5b919050565b600080604083850312156108c157600080fd5b823591506108d160208401610885565b90509250929050565b6000602082840312156108ec57600080fd5b6103e982610885565b60008060006060848603121561090a57600080fd5b61091384610885565b925061092160208501610885565b915060408401359050925092509256fea2646970667358221220b917ec53e94feb877107d694f6da6360b795610f2218c1647ae6a87c371e46bc64736f6c63430008130033a26469706673582212206353e8f81b902fedbacedaf67d3e2fe64b4bf64aee0a9db06d373987c950bd8e64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000b67d200000000000000000000000000000000000000000000000000000000000b67d20000000000000000000000009b8c323468aec7a7cb041ced48f92559bff337050000000000000000000000001cadcd88fc148d3966ede75d029937c886f6600900000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000004494d4c4900000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : chainSlug_ (uint32): 747474
Arg [1] : siblingChainSlug_ (uint32): 747474
Arg [2] : hasher_ (address): 0x9B8c323468AEC7A7Cb041CeD48F92559bFF33705
Arg [3] : signatureVerifier_ (address): 0x1CAdCd88fC148D3966eDe75D029937C886f66009
Arg [4] : version_ (string): IMLI
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000b67d2
Arg [1] : 00000000000000000000000000000000000000000000000000000000000b67d2
Arg [2] : 0000000000000000000000009b8c323468aec7a7cb041ced48f92559bff33705
Arg [3] : 0000000000000000000000001cadcd88fc148d3966ede75d029937c886f66009
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [6] : 494d4c4900000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.