Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ExecutionManagerDF
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 999999
- EVM Version
- default
- Verified at
- 2024-10-23T11:04:21.554152Z
Constructor Arguments
0x00000000000000000000000044a44837894b5edc2bde64567fc62599b3b88f4c0000000000000000000000000000000000000000000000000000000000028c610000000000000000000000005c4186d343eef952c9ed886e45f8243edf0a503f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f
Arg [0] (address) : 0x44a44837894b5edc2bde64567fc62599b3b88f4c
Arg [1] (uint32) : 167009
Arg [2] (address) : 0x5c4186d343eef952c9ed886e45f8243edf0a503f
Arg [3] (address) : 0xef1ae2f8b4e18afdddf1ca92037772891100a39f
contracts/ExecutionManagerDF.sol
// SPDX-License-Identifier: GPL-3.0-only // Sources flattened with hardhat v2.12.2 https://hardhat.org // 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 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 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/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/utils/SigIdentifiers.sol pragma solidity 0.8.19; // contains unique identifiers which are hashes of strings, they help in making signature digest unique // hence preventing signature replay attacks // default switchboards bytes32 constant TRIP_PATH_SIG_IDENTIFIER = keccak256("TRIP_PATH"); bytes32 constant TRIP_PROPOSAL_SIG_IDENTIFIER = keccak256("TRIP_PROPOSAL"); bytes32 constant TRIP_GLOBAL_SIG_IDENTIFIER = keccak256("TRIP_GLOBAL"); bytes32 constant UN_TRIP_PATH_SIG_IDENTIFIER = keccak256("UN_TRIP_PATH"); bytes32 constant UN_TRIP_GLOBAL_SIG_IDENTIFIER = keccak256("UN_TRIP_GLOBAL"); // native switchboards bytes32 constant TRIP_NATIVE_SIG_IDENTIFIER = keccak256("TRIP_NATIVE"); bytes32 constant UN_TRIP_NATIVE_SIG_IDENTIFIER = keccak256("UN_TRIP_NATIVE"); // value threshold, price and fee updaters bytes32 constant FEES_UPDATE_SIG_IDENTIFIER = keccak256("FEES_UPDATE"); bytes32 constant RELATIVE_NATIVE_TOKEN_PRICE_UPDATE_SIG_IDENTIFIER = keccak256( "RELATIVE_NATIVE_TOKEN_PRICE_UPDATE" ); bytes32 constant MSG_VALUE_MIN_THRESHOLD_SIG_IDENTIFIER = keccak256( "MSG_VALUE_MIN_THRESHOLD_UPDATE" ); bytes32 constant MSG_VALUE_MAX_THRESHOLD_SIG_IDENTIFIER = keccak256( "MSG_VALUE_MAX_THRESHOLD_UPDATE" ); // 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/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/utils/AccessControlExtended.sol pragma solidity 0.8.19; /** * @title AccessControlExtended * @dev This contract extends the functionality of the AccessControl contract by adding * the ability to grant and revoke roles based on a combination of role name and a chain slug. * It also provides batch operations for granting and revoking roles. */ contract AccessControlExtended is AccessControl { /** * @dev Constructor that sets the owner of the contract. */ constructor(address owner_) AccessControl(owner_) {} /** * @dev thrown when array lengths are not equal */ error UnequalArrayLengths(); /** * @dev Checks if an address has the role. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param address_ The address to be granted the role. */ function _checkRoleWithSlug( bytes32 roleName_, uint256 chainSlug_, address address_ ) internal virtual { bytes32 roleHash = keccak256(abi.encode(roleName_, chainSlug_)); if (!_hasRole(roleHash, address_)) revert NoPermit(roleHash); } /** * @dev Grants a role to an address based on the role name and chain slug. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param grantee_ The address to be granted the role. */ function grantRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) external virtual onlyOwner { _grantRoleWithSlug(roleName_, chainSlug_, grantee_); } /** * @dev Grants multiple roles to multiple addresses in batch. * @param roleNames_ The names of the roles to grant. * @param slugs_ The slugs for chain specific roles. For roles which are not chain-specific, we can use slug = 0 * @param grantees_ The addresses to be granted the roles. */ function grantBatchRole( bytes32[] calldata roleNames_, uint32[] calldata slugs_, address[] calldata grantees_ ) external virtual onlyOwner { if ( roleNames_.length != grantees_.length || roleNames_.length != slugs_.length ) revert UnequalArrayLengths(); uint256 totalRoles = roleNames_.length; for (uint256 index = 0; index < totalRoles; ) { if (slugs_[index] > 0) _grantRoleWithSlug( roleNames_[index], slugs_[index], grantees_[index] ); else _grantRole(roleNames_[index], grantees_[index]); // inputs are controlled by owner unchecked { ++index; } } } /** * @dev Revokes multiple roles from multiple addresses in batch. * @param roleNames_ The names of the roles to revoke. * @param slugs_ The slugs for chain specific roles. For roles which are not chain-specific, we can use slug = 0 * @param grantees_ The addresses to be revoked the roles. */ function revokeBatchRole( bytes32[] calldata roleNames_, uint32[] calldata slugs_, address[] calldata grantees_ ) external virtual onlyOwner { if ( roleNames_.length != grantees_.length || roleNames_.length != slugs_.length ) revert UnequalArrayLengths(); uint256 totalRoles = roleNames_.length; for (uint256 index = 0; index < totalRoles; ) { if (slugs_[index] > 0) _revokeRoleWithSlug( roleNames_[index], slugs_[index], grantees_[index] ); else _revokeRole(roleNames_[index], grantees_[index]); // inputs are controlled by owner unchecked { ++index; } } } function _grantRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) internal { _grantRole(keccak256(abi.encode(roleName_, chainSlug_)), grantee_); } /** * @dev Checks if an address has a role based on the role name and chain slug. * @param roleName_ The name of the role. * @param chainSlug_ The chain slug associated with the role. * @param address_ The address to check for the role. * @return A boolean indicating whether the address has the specified role. */ function hasRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address address_ ) external view returns (bool) { return _hasRoleWithSlug(roleName_, chainSlug_, address_); } function _hasRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address address_ ) internal view returns (bool) { return _hasRole(keccak256(abi.encode(roleName_, chainSlug_)), address_); } /** * @dev Revokes roles from an address * @param roleName_ The names of the roles to revoke. * @param chainSlug_ The chain slug associated with the role. * @param grantee_ The addresses to be revoked the roles. */ function revokeRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address grantee_ ) external virtual onlyOwner { _revokeRoleWithSlug(roleName_, chainSlug_, grantee_); } function _revokeRoleWithSlug( bytes32 roleName_, uint32 chainSlug_, address revokee_ ) internal { _revokeRole(keccak256(abi.encode(roleName_, chainSlug_)), revokee_); } } // File contracts/ExecutionManagerDF.sol pragma solidity 0.8.19; /** * @title ExecutionManagerDF * @dev Implementation of the IExecutionManager interface, providing functions for executing cross-chain transactions and * managing execution and other fees. This contract also implements the AccessControl interface, allowing for role-based * access control. */ contract ExecutionManagerDF is IExecutionManager, AccessControlExtended { uint256 private constant PAYLOAD_LIMIT = 5000; ISignatureVerifier public immutable signatureVerifier__; ISocket public immutable socket__; uint32 public immutable chainSlug; /** * @notice Emitted when the executionFees is updated * @param siblingChainSlug The destination chain slug for which the executionFees is updated * @param executionFees The new executionFees */ event ExecutionFeesSet( uint32 siblingChainSlug, ExecutionFeesParam executionFees ); /** * @notice Emitted when the relativeNativeTokenPrice is updated * @param siblingChainSlug The destination chain slug for which the relativeNativeTokenPrice is updated * @param relativeNativeTokenPrice The new relativeNativeTokenPrice */ event RelativeNativeTokenPriceSet( uint256 siblingChainSlug, uint256 relativeNativeTokenPrice ); /** * @notice Emitted when the msgValueMaxThresholdSet is updated * @param siblingChainSlug The destination chain slug for which the msgValueMaxThresholdSet is updated * @param msgValueMaxThresholdSet The new msgValueMaxThresholdSet */ event MsgValueMaxThresholdSet( uint256 siblingChainSlug, uint256 msgValueMaxThresholdSet ); /** * @notice Emitted when the msgValueMinThresholdSet is updated * @param siblingChainSlug The destination chain slug for which the msgValueMinThresholdSet is updated * @param msgValueMinThresholdSet The new msgValueMinThresholdSet */ event MsgValueMinThresholdSet( uint256 siblingChainSlug, uint256 msgValueMinThresholdSet ); /** * @notice Emitted when the execution fees is withdrawn * @param account The address to which fees is transferred * @param siblingChainSlug The destination chain slug for which the fees is withdrawn * @param amount The amount withdrawn */ event ExecutionFeesWithdrawn( address account, uint32 siblingChainSlug, uint256 amount ); /** * @notice Emitted when the transmission fees is withdrawn * @param transmitManager The address of transmit manager to which fees is transferred * @param siblingChainSlug The destination chain slug for which the fees is withdrawn * @param amount The amount withdrawn */ event TransmissionFeesWithdrawn( address transmitManager, uint32 siblingChainSlug, uint256 amount ); /** * @notice Emitted when the switchboard fees is withdrawn * @param switchboard The address of switchboard for which fees is claimed * @param siblingChainSlug The destination chain slug for which the fees is withdrawn * @param amount The amount withdrawn */ event SwitchboardFeesWithdrawn( address switchboard, uint32 siblingChainSlug, uint256 amount ); /** * @notice packs the total execution and transmission fees received for a sibling slug */ struct TotalExecutionAndTransmissionFees { uint128 totalExecutionFees; uint128 totalTransmissionFees; } // maps total fee collected with chain slug mapping(uint32 => TotalExecutionAndTransmissionFees) public totalExecutionAndTransmissionFees; // switchboard => chain slug => switchboard fees collected mapping(address => mapping(uint32 => uint128)) public totalSwitchboardFees; // transmitter => nextNonce mapping(address => uint256) public nextNonce; // transmit manager => chain slug => switchboard fees collected mapping(address => mapping(uint32 => uint128)) public transmissionMinFees; // relativeNativeTokenPrice is used to convert fees to destination terms when sending value along with message // destSlug => relativeNativePrice (stores (destnativeTokenPriceUSD*(1e18)/srcNativeTokenPriceUSD)) mapping(uint32 => uint256) public relativeNativeTokenPrice; // supported min amount of native value to send with message // chain slug => min msg value threshold mapping(uint32 => uint256) public msgValueMinThreshold; // supported max amount of native value to send with message // chain slug => max msg value threshold mapping(uint32 => uint256) public msgValueMaxThreshold; // remoteChainSlug => ExecutionFeesParam mapping(uint32 => ExecutionFeesParam) public executionFees; // triggered when nonce in signature is invalid error InvalidNonce(); // triggered when msg value less than min threshold error MsgValueTooLow(); // triggered when msg value more than max threshold error MsgValueTooHigh(); // triggered when msg value is not enough error InsufficientMsgValue(); // triggered when fees is not enough error InsufficientFees(); // triggered when msg value exceeds uint128 max value error InvalidMsgValue(); // triggered when fees exceeds uint128 max value error FeesTooHigh(); error OnlySocket(); error PayloadTooLarge(); /** * @dev Constructor for ExecutionManager contract * @param owner_ address of the contract owner * @param chainSlug_ chain slug, unique identifier of chain deployed on * @param signatureVerifier_ the signature verifier contract * @param socket_ the socket contract */ constructor( address owner_, uint32 chainSlug_, ISocket socket_, ISignatureVerifier signatureVerifier_ ) AccessControlExtended(owner_) { chainSlug = chainSlug_; signatureVerifier__ = signatureVerifier_; socket__ = ISocket(socket_); } /** * @notice Checks whether the provided signer address is an executor for the given packed message and signature * @param packedMessage Packed message to be executed * @param sig Signature of the message * @return executor Address of the executor * @return isValidExecutor Boolean value indicating whether the executor is valid or not */ function isExecutor( bytes32 packedMessage, bytes memory sig ) external view virtual override returns (address executor, bool isValidExecutor) { executor = signatureVerifier__.recoverSigner(packedMessage, sig); isValidExecutor = _hasRole(EXECUTOR_ROLE, executor); } /** * @notice updates the total fee used by an executor to execute a message * @dev to be used for accounting when onchain fee distribution for individual executors is implemented * @dev this function should be called by socket only * @inheritdoc IExecutionManager */ function updateExecutionFees( address, uint128, bytes32 ) external view override { if (msg.sender != address(socket__)) revert OnlySocket(); } /// @inheritdoc IExecutionManager function payAndCheckFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, bytes32, uint32 siblingChainSlug_, uint128 switchboardFees_, uint128 verificationOverheadFees_, address transmitManager_, address switchboard_, uint256 maxPacketLength_ ) external payable override returns (uint128 executionFee, uint128 transmissionFees) { if (msg.value >= type(uint128).max) revert InvalidMsgValue(); uint128 msgValue = uint128(msg.value); // transmission fees are per packet, so need to divide by number of messages per packet transmissionFees = transmissionMinFees[transmitManager_][siblingChainSlug_] / uint128(maxPacketLength_); uint128 minMsgExecutionFees = _getMinFees( minMsgGasLimit_, payloadSize_, executionParams_, siblingChainSlug_ ); uint128 minExecutionFees = minMsgExecutionFees + verificationOverheadFees_; if (msgValue < transmissionFees + switchboardFees_ + minExecutionFees) revert InsufficientFees(); // any extra fee is considered as executionFee executionFee = msgValue - transmissionFees - switchboardFees_; TotalExecutionAndTransmissionFees memory currentTotalFees = totalExecutionAndTransmissionFees[ siblingChainSlug_ ]; totalExecutionAndTransmissionFees[ siblingChainSlug_ ] = TotalExecutionAndTransmissionFees({ totalExecutionFees: currentTotalFees.totalExecutionFees + executionFee, totalTransmissionFees: currentTotalFees.totalTransmissionFees + transmissionFees }); totalSwitchboardFees[switchboard_][ siblingChainSlug_ ] += switchboardFees_; } /** * @notice function for getting the minimum fees required for executing msg on destination * @dev this function is called at source to calculate the execution cost. * @param gasLimit_ the gas limit needed for execution at destination * @param payloadSize_ byte length of payload. Currently only used to check max length, later on will be used for fees calculation. * @param executionParams_ Can be used for providing extra information. Currently used for msgValue * @param siblingChainSlug_ Sibling chain identifier * @return minExecutionFee : Minimum fees required for executing the transaction */ function getMinFees( uint256 gasLimit_, uint256 payloadSize_, bytes32 executionParams_, uint32 siblingChainSlug_ ) external view override returns (uint128 minExecutionFee) { minExecutionFee = _getMinFees( gasLimit_, payloadSize_, executionParams_, siblingChainSlug_ ); } /// @inheritdoc IExecutionManager function getExecutionTransmissionMinFees( uint256 minMsgGasLimit_, uint256 payloadSize_, bytes32 executionParams_, bytes32, uint32 siblingChainSlug_, address transmitManager_ ) external view override returns (uint128 minExecutionFee, uint128 transmissionFees) { minExecutionFee = _getMinFees( minMsgGasLimit_, payloadSize_, executionParams_, siblingChainSlug_ ); transmissionFees = transmissionMinFees[transmitManager_][ siblingChainSlug_ ]; } // decodes and validates the msg value if it is under given transfer limits and calculates // the total fees needed for execution for given payload size and msg value. function _getMinFees( uint256 msgGasLimit, uint256 payloadSize_, bytes32 executionParams_, uint32 siblingChainSlug_ ) internal view returns (uint128) { if (payloadSize_ > PAYLOAD_LIMIT) revert PayloadTooLarge(); uint256 totalNativeValue = _calculateExecutionFees( msgGasLimit, payloadSize_, siblingChainSlug_ ) + _calculateMsgValueFees(siblingChainSlug_, executionParams_); if (totalNativeValue >= type(uint128).max) revert FeesTooHigh(); return uint128(totalNativeValue); } function _calculateExecutionFees( uint256 msgGasLimit, uint256 payloadSize_, uint32 siblingChainSlug_ ) internal view returns (uint256 totalFees) { ExecutionFeesParam memory executionFeesParam = executionFees[ siblingChainSlug_ ]; // layer 2 fees depends on the payload size and how chain calculates the tx fees // to simplify, an overhead and perByteCost is updated on contract through external cron // and fees is calculated as : payloadSize * perByteCost + overhead // fees = gasLimit * gasLimit + perBytesCost * payloadLength + overhead totalFees = msgGasLimit * executionFeesParam.perGasCost + executionFeesParam.overhead + payloadSize_ * executionFeesParam.perByteCost; } function _calculateMsgValueFees( uint32 siblingChainSlug_, bytes32 executionParams_ ) internal view returns (uint256 msgValueRequiredOnSrcChain) { uint256 params = uint256(executionParams_); uint8 paramType = uint8(params >> 248); if (paramType == 0) return 0; uint256 msgValue = uint256(uint248(params)); if (msgValue < msgValueMinThreshold[siblingChainSlug_]) revert MsgValueTooLow(); if (msgValue > msgValueMaxThreshold[siblingChainSlug_]) revert MsgValueTooHigh(); msgValueRequiredOnSrcChain = (relativeNativeTokenPrice[siblingChainSlug_] * msgValue) / 1e18; } /** * @notice called by socket while executing message to validate if the msg value provided is enough * @param executionParams_ a bytes32 string where first byte gives param type (if value is 0 or not) * and remaining bytes give the msg value needed * @param msgValue_ msg.value to be sent with inbound */ function verifyParams( bytes32 executionParams_, uint256 msgValue_ ) external pure override { uint256 params = uint256(executionParams_); uint8 paramType = uint8(params >> 248); if (paramType == 0) return; uint256 expectedMsgValue = uint256(uint248(params)); if (msgValue_ < expectedMsgValue) revert InsufficientMsgValue(); } /** * @notice sets the minimum execution fees required for executing at `siblingChainSlug_` * @dev this function currently sets the price for a constant msg gas limit and payload size but this will be * updated in future to consider gas limit and payload size to return fees which will be close to * actual execution cost. * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param executionFees_ total fees where price in destination native token is converted to source native tokens * @param signature_ signature of fee updater */ function setExecutionFees( uint256 nonce_, uint32 siblingChainSlug_, ExecutionFeesParam calldata executionFees_, bytes calldata signature_ ) external override { address feesUpdater = signatureVerifier__.recoverSigner( keccak256( abi.encode( FEES_UPDATE_SIG_IDENTIFIER, address(this), chainSlug, siblingChainSlug_, nonce_, executionFees_ ) ), signature_ ); _checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, feesUpdater); // nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[feesUpdater]++) revert InvalidNonce(); } executionFees[siblingChainSlug_] = executionFees_; emit ExecutionFeesSet(siblingChainSlug_, executionFees_); } /** * @notice sets the relative token price for `siblingChainSlug_` * @dev this function is expected to be called frequently to match the original prices * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param relativeNativeTokenPrice_ relative price * @param signature_ signature of fee updater */ function setRelativeNativeTokenPrice( uint256 nonce_, uint32 siblingChainSlug_, uint256 relativeNativeTokenPrice_, bytes calldata signature_ ) external override { address feesUpdater = signatureVerifier__.recoverSigner( keccak256( abi.encode( RELATIVE_NATIVE_TOKEN_PRICE_UPDATE_SIG_IDENTIFIER, address(this), chainSlug, siblingChainSlug_, nonce_, relativeNativeTokenPrice_ ) ), signature_ ); _checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, feesUpdater); // nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[feesUpdater]++) revert InvalidNonce(); } relativeNativeTokenPrice[siblingChainSlug_] = relativeNativeTokenPrice_; emit RelativeNativeTokenPriceSet( siblingChainSlug_, relativeNativeTokenPrice_ ); } /** * @notice sets the min limit for msg value for `siblingChainSlug_` * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param msgValueMinThreshold_ min msg value * @param signature_ signature of fee updater */ function setMsgValueMinThreshold( uint256 nonce_, uint32 siblingChainSlug_, uint256 msgValueMinThreshold_, bytes calldata signature_ ) external override { address feesUpdater = signatureVerifier__.recoverSigner( keccak256( abi.encode( MSG_VALUE_MIN_THRESHOLD_SIG_IDENTIFIER, address(this), chainSlug, siblingChainSlug_, nonce_, msgValueMinThreshold_ ) ), signature_ ); _checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, feesUpdater); // nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[feesUpdater]++) revert InvalidNonce(); } msgValueMinThreshold[siblingChainSlug_] = msgValueMinThreshold_; emit MsgValueMinThresholdSet(siblingChainSlug_, msgValueMinThreshold_); } /** * @notice sets the max limit for msg value for `siblingChainSlug_` * @param nonce_ incremental id to prevent signature replay * @param siblingChainSlug_ sibling chain identifier * @param msgValueMaxThreshold_ max msg value * @param signature_ signature of fee updater */ function setMsgValueMaxThreshold( uint256 nonce_, uint32 siblingChainSlug_, uint256 msgValueMaxThreshold_, bytes calldata signature_ ) external override { address feesUpdater = signatureVerifier__.recoverSigner( keccak256( abi.encode( MSG_VALUE_MAX_THRESHOLD_SIG_IDENTIFIER, address(this), chainSlug, siblingChainSlug_, nonce_, msgValueMaxThreshold_ ) ), signature_ ); _checkRoleWithSlug(FEES_UPDATER_ROLE, siblingChainSlug_, feesUpdater); // nonce is used by gated roles and we don't expect nonce to reach the max value of uint256 unchecked { if (nonce_ != nextNonce[feesUpdater]++) revert InvalidNonce(); } msgValueMaxThreshold[siblingChainSlug_] = msgValueMaxThreshold_; emit MsgValueMaxThresholdSet(siblingChainSlug_, msgValueMaxThreshold_); } /** * @notice updates the transmission fee needed for transmission * @dev this function stores value against msg.sender hence expected to be called by transmit manager * @inheritdoc IExecutionManager */ function setTransmissionMinFees( uint32 remoteChainSlug_, uint128 fees_ ) external override { transmissionMinFees[msg.sender][remoteChainSlug_] = fees_; } /** * @notice withdraws fees for execution from contract * @param siblingChainSlug_ withdraw fees corresponding to this slug * @param amount_ withdraw amount * @param withdrawTo_ withdraw fees to the provided address */ function withdrawExecutionFees( uint32 siblingChainSlug_, uint128 amount_, address withdrawTo_ ) external onlyRole(WITHDRAW_ROLE) { if (withdrawTo_ == address(0)) revert ZeroAddress(); if ( totalExecutionAndTransmissionFees[siblingChainSlug_] .totalExecutionFees < amount_ ) revert InsufficientFees(); totalExecutionAndTransmissionFees[siblingChainSlug_] .totalExecutionFees -= amount_; SafeTransferLib.safeTransferETH(withdrawTo_, amount_); emit ExecutionFeesWithdrawn(withdrawTo_, siblingChainSlug_, amount_); } /** * @notice withdraws switchboard fees from contract * @param siblingChainSlug_ withdraw fees corresponding to this slug * @param amount_ withdraw amount */ function withdrawSwitchboardFees( uint32 siblingChainSlug_, address switchboard_, uint128 amount_ ) external override { if (totalSwitchboardFees[switchboard_][siblingChainSlug_] < amount_) revert InsufficientFees(); totalSwitchboardFees[switchboard_][siblingChainSlug_] -= amount_; ISwitchboard(switchboard_).receiveFees{value: amount_}( siblingChainSlug_ ); emit SwitchboardFeesWithdrawn(switchboard_, siblingChainSlug_, amount_); } /** * @dev this function gets the transmitManager address from the socket contract. If it is ever upgraded in socket, * @dev remove the fees from executionManager first, and then upgrade address at socket. * @notice withdraws transmission fees from contract * @param siblingChainSlug_ withdraw fees corresponding to this slug * @param amount_ withdraw amount */ function withdrawTransmissionFees( uint32 siblingChainSlug_, uint128 amount_ ) external override { if ( totalExecutionAndTransmissionFees[siblingChainSlug_] .totalTransmissionFees < amount_ ) revert InsufficientFees(); totalExecutionAndTransmissionFees[siblingChainSlug_] .totalTransmissionFees -= amount_; ITransmitManager tm = socket__.transmitManager__(); tm.receiveFees{value: amount_}(siblingChainSlug_); emit TransmissionFeesWithdrawn(address(tm), siblingChainSlug_, amount_); } /** * @notice Rescues funds from the contract if they are locked by mistake. * @param token_ The address of the token contract. * @param rescueTo_ The address where rescued tokens need to be sent. * @param amount_ The amount of tokens to be rescued. */ function rescueFunds( address token_, address rescueTo_, uint256 amount_ ) external onlyRole(RESCUE_ROLE) { RescueFundsLib.rescueFunds(token_, rescueTo_, amount_); } }
Compiler Settings
{"outputSelection":{"*":{"*":["*"]}},"optimizer":{"runs":999999,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"owner_","internalType":"address"},{"type":"uint32","name":"chainSlug_","internalType":"uint32"},{"type":"address","name":"socket_","internalType":"contract ISocket"},{"type":"address","name":"signatureVerifier_","internalType":"contract ISignatureVerifier"}]},{"type":"error","name":"FeesTooHigh","inputs":[]},{"type":"error","name":"InsufficientFees","inputs":[]},{"type":"error","name":"InsufficientMsgValue","inputs":[]},{"type":"error","name":"InvalidMsgValue","inputs":[]},{"type":"error","name":"InvalidNonce","inputs":[]},{"type":"error","name":"InvalidTokenAddress","inputs":[]},{"type":"error","name":"MsgValueTooHigh","inputs":[]},{"type":"error","name":"MsgValueTooLow","inputs":[]},{"type":"error","name":"NoPermit","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"error","name":"OnlyNominee","inputs":[]},{"type":"error","name":"OnlyOwner","inputs":[]},{"type":"error","name":"OnlySocket","inputs":[]},{"type":"error","name":"PayloadTooLarge","inputs":[]},{"type":"error","name":"UnequalArrayLengths","inputs":[]},{"type":"error","name":"ZeroAddress","inputs":[]},{"type":"event","name":"ExecutionFeesSet","inputs":[{"type":"uint32","name":"siblingChainSlug","internalType":"uint32","indexed":false},{"type":"tuple","name":"executionFees","internalType":"struct IExecutionManager.ExecutionFeesParam","indexed":false,"components":[{"type":"uint80","name":"perGasCost","internalType":"uint80"},{"type":"uint80","name":"perByteCost","internalType":"uint80"},{"type":"uint80","name":"overhead","internalType":"uint80"}]}],"anonymous":false},{"type":"event","name":"ExecutionFeesWithdrawn","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"uint32","name":"siblingChainSlug","internalType":"uint32","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MsgValueMaxThresholdSet","inputs":[{"type":"uint256","name":"siblingChainSlug","internalType":"uint256","indexed":false},{"type":"uint256","name":"msgValueMaxThresholdSet","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MsgValueMinThresholdSet","inputs":[{"type":"uint256","name":"siblingChainSlug","internalType":"uint256","indexed":false},{"type":"uint256","name":"msgValueMinThresholdSet","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerClaimed","inputs":[{"type":"address","name":"claimer","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerNominated","inputs":[{"type":"address","name":"nominee","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RelativeNativeTokenPriceSet","inputs":[{"type":"uint256","name":"siblingChainSlug","internalType":"uint256","indexed":false},{"type":"uint256","name":"relativeNativeTokenPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"grantee","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"revokee","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SwitchboardFeesWithdrawn","inputs":[{"type":"address","name":"switchboard","internalType":"address","indexed":false},{"type":"uint32","name":"siblingChainSlug","internalType":"uint32","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TransmissionFeesWithdrawn","inputs":[{"type":"address","name":"transmitManager","internalType":"address","indexed":false},{"type":"uint32","name":"siblingChainSlug","internalType":"uint32","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"chainSlug","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint80","name":"perGasCost","internalType":"uint80"},{"type":"uint80","name":"perByteCost","internalType":"uint80"},{"type":"uint80","name":"overhead","internalType":"uint80"}],"name":"executionFees","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"minExecutionFee","internalType":"uint128"},{"type":"uint128","name":"transmissionFees","internalType":"uint128"}],"name":"getExecutionTransmissionMinFees","inputs":[{"type":"uint256","name":"minMsgGasLimit_","internalType":"uint256"},{"type":"uint256","name":"payloadSize_","internalType":"uint256"},{"type":"bytes32","name":"executionParams_","internalType":"bytes32"},{"type":"bytes32","name":"","internalType":"bytes32"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"address","name":"transmitManager_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"minExecutionFee","internalType":"uint128"}],"name":"getMinFees","inputs":[{"type":"uint256","name":"gasLimit_","internalType":"uint256"},{"type":"uint256","name":"payloadSize_","internalType":"uint256"},{"type":"bytes32","name":"executionParams_","internalType":"bytes32"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantBatchRole","inputs":[{"type":"bytes32[]","name":"roleNames_","internalType":"bytes32[]"},{"type":"uint32[]","name":"slugs_","internalType":"uint32[]"},{"type":"address[]","name":"grantees_","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role_","internalType":"bytes32"},{"type":"address","name":"grantee_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRoleWithSlug","inputs":[{"type":"bytes32","name":"roleName_","internalType":"bytes32"},{"type":"uint32","name":"chainSlug_","internalType":"uint32"},{"type":"address","name":"grantee_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role_","internalType":"bytes32"},{"type":"address","name":"address_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRoleWithSlug","inputs":[{"type":"bytes32","name":"roleName_","internalType":"bytes32"},{"type":"uint32","name":"chainSlug_","internalType":"uint32"},{"type":"address","name":"address_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"executor","internalType":"address"},{"type":"bool","name":"isValidExecutor","internalType":"bool"}],"name":"isExecutor","inputs":[{"type":"bytes32","name":"packedMessage","internalType":"bytes32"},{"type":"bytes","name":"sig","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"msgValueMaxThreshold","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"msgValueMinThreshold","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextNonce","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"nominateOwner","inputs":[{"type":"address","name":"nominee_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"nominee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint128","name":"executionFee","internalType":"uint128"},{"type":"uint128","name":"transmissionFees","internalType":"uint128"}],"name":"payAndCheckFees","inputs":[{"type":"uint256","name":"minMsgGasLimit_","internalType":"uint256"},{"type":"uint256","name":"payloadSize_","internalType":"uint256"},{"type":"bytes32","name":"executionParams_","internalType":"bytes32"},{"type":"bytes32","name":"","internalType":"bytes32"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint128","name":"switchboardFees_","internalType":"uint128"},{"type":"uint128","name":"verificationOverheadFees_","internalType":"uint128"},{"type":"address","name":"transmitManager_","internalType":"address"},{"type":"address","name":"switchboard_","internalType":"address"},{"type":"uint256","name":"maxPacketLength_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"relativeNativeTokenPrice","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueFunds","inputs":[{"type":"address","name":"token_","internalType":"address"},{"type":"address","name":"rescueTo_","internalType":"address"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeBatchRole","inputs":[{"type":"bytes32[]","name":"roleNames_","internalType":"bytes32[]"},{"type":"uint32[]","name":"slugs_","internalType":"uint32[]"},{"type":"address[]","name":"grantees_","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role_","internalType":"bytes32"},{"type":"address","name":"revokee_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRoleWithSlug","inputs":[{"type":"bytes32","name":"roleName_","internalType":"bytes32"},{"type":"uint32","name":"chainSlug_","internalType":"uint32"},{"type":"address","name":"grantee_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setExecutionFees","inputs":[{"type":"uint256","name":"nonce_","internalType":"uint256"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"tuple","name":"executionFees_","internalType":"struct IExecutionManager.ExecutionFeesParam","components":[{"type":"uint80","name":"perGasCost","internalType":"uint80"},{"type":"uint80","name":"perByteCost","internalType":"uint80"},{"type":"uint80","name":"overhead","internalType":"uint80"}]},{"type":"bytes","name":"signature_","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMsgValueMaxThreshold","inputs":[{"type":"uint256","name":"nonce_","internalType":"uint256"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint256","name":"msgValueMaxThreshold_","internalType":"uint256"},{"type":"bytes","name":"signature_","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMsgValueMinThreshold","inputs":[{"type":"uint256","name":"nonce_","internalType":"uint256"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint256","name":"msgValueMinThreshold_","internalType":"uint256"},{"type":"bytes","name":"signature_","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRelativeNativeTokenPrice","inputs":[{"type":"uint256","name":"nonce_","internalType":"uint256"},{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint256","name":"relativeNativeTokenPrice_","internalType":"uint256"},{"type":"bytes","name":"signature_","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTransmissionMinFees","inputs":[{"type":"uint32","name":"remoteChainSlug_","internalType":"uint32"},{"type":"uint128","name":"fees_","internalType":"uint128"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ISignatureVerifier"}],"name":"signatureVerifier__","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ISocket"}],"name":"socket__","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"totalExecutionFees","internalType":"uint128"},{"type":"uint128","name":"totalTransmissionFees","internalType":"uint128"}],"name":"totalExecutionAndTransmissionFees","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"totalSwitchboardFees","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"","internalType":"uint128"}],"name":"transmissionMinFees","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"updateExecutionFees","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint128","name":"","internalType":"uint128"},{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"pure","outputs":[],"name":"verifyParams","inputs":[{"type":"bytes32","name":"executionParams_","internalType":"bytes32"},{"type":"uint256","name":"msgValue_","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawExecutionFees","inputs":[{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint128","name":"amount_","internalType":"uint128"},{"type":"address","name":"withdrawTo_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawSwitchboardFees","inputs":[{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"address","name":"switchboard_","internalType":"address"},{"type":"uint128","name":"amount_","internalType":"uint128"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawTransmissionFees","inputs":[{"type":"uint32","name":"siblingChainSlug_","internalType":"uint32"},{"type":"uint128","name":"amount_","internalType":"uint128"}]}]
Contract Creation Code
0x60e06040523480156200001157600080fd5b50604051620039a5380380620039a58339810160408190526200003491620000d5565b838080620000428162000069565b50505063ffffffff90921660c0526001600160a01b039182166080521660a0525062000145565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b6001600160a01b0381168114620000d257600080fd5b50565b60008060008060808587031215620000ec57600080fd5b8451620000f981620000bc565b602086015190945063ffffffff811681146200011457600080fd5b60408601519093506200012781620000bc565b60608601519092506200013a81620000bc565b939692955090935050565b60805160a05160c0516137e3620001c26000396000818161087d01528181610ce20152818161114f01528181611d150152611f3f0152600081816108c60152818161154e01526124d501526000818161091a01528181610d73015281816110f101528181611bec01528181611da60152611fd001526137e36000f3fe6080604052600436106102845760003560e01c80637644e7fa11610153578063aea3d96b116100cb578063d5b8da731161007f578063de8c4ff911610064578063de8c4ff914610986578063ecb97484146109a6578063f1f069d6146109c657600080fd5b8063d5b8da7314610908578063d81381d51461093c57600080fd5b8063b349ba65116100b0578063b349ba651461086b578063c6a261d2146108b4578063d547741f146108e857600080fd5b8063aea3d96b146107f4578063b0c342291461081457600080fd5b8063954d09c9116101225780639f102855116101075780639f10285514610794578063a1885700146107b4578063a56d92ce146107d457600080fd5b8063954d09c91461071b578063955b15901461076757600080fd5b80637644e7fa146106735780638da5cb5b146106a057806390d241f1146106cb57806391d14854146106eb57600080fd5b806338fe30251161020157806350a9cf67116101b55780636ccae0541161019a5780636ccae054146105f75780636e3c05621461061757806371c4717b1461063757600080fd5b806350a9cf67146105b75780635b94db27146105d757600080fd5b80633bd1adec116101e65780633bd1adec1461055557806343fa97ca1461056a5780634d1bf1891461058a57600080fd5b806338fe3025146104b65780633b13d3f1146104d657600080fd5b80631e867311116102585780632e7eb2581161023d5780632e7eb258146104565780632f2ff15d14610476578063308795b21461049657600080fd5b80631e867311146103ea57806320f99c0a1461040a57600080fd5b80626fc3e2146102895780630cd55abf146102f957806311cf8aa5146103345780631ba8e484146103c8575b600080fd5b34801561029557600080fd5b506102d36102a4366004612d27565b60046020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561030557600080fd5b50610326610314366004612d53565b60056020526000908152604090205481565b6040519081526020016102f0565b34801561034057600080fd5b5061039b61034f366004612d70565b600a6020526000908152604090205469ffffffffffffffffffff808216916a01000000000000000000008104821691740100000000000000000000000000000000000000009091041683565b6040805169ffffffffffffffffffff948516815292841660208401529216918101919091526060016102f0565b3480156103d457600080fd5b506103e86103e3366004612d8b565b6109e6565b005b3480156103f657600080fd5b506103e8610405366004612e17565b610a47565b34801561041657600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f0565b34801561046257600080fd5b506103e8610471366004612d8b565b610bed565b34801561048257600080fd5b506103e8610491366004612eb1565b610c49565b3480156104a257600080fd5b506103e86104b1366004612f23565b610ca8565b3480156104c257600080fd5b506102d36104d1366004612f8b565b610ede565b3480156104e257600080fd5b506103e86104f1366004612fea565b33600090815260066020908152604080832063ffffffff9590951683529390529190912080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909216919091179055565b34801561056157600080fd5b506103e8610ef5565b34801561057657600080fd5b506103e8610585366004612e17565b610f51565b34801561059657600080fd5b506103266105a5366004612d70565b60096020526000908152604090205481565b3480156105c357600080fd5b506103e86105d2366004613014565b6110ed565b3480156105e357600080fd5b506103e86105f2366004612d53565b6112eb565b34801561060357600080fd5b506103e8610612366004613090565b6113ab565b34801561062357600080fd5b506103e8610632366004612fea565b61144e565b61064a6106453660046130d1565b6116f3565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152016102f0565b34801561067f57600080fd5b5061032661068e366004612d70565b60086020526000908152604090205481565b3480156106ac57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610431565b3480156106d757600080fd5b506103e86106e636600461316e565b6119ac565b3480156106f757600080fd5b5061070b610706366004612eb1565b611baa565b60405190151581526020016102f0565b34801561072757600080fd5b5061073b6107363660046131e2565b611be7565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683529015156020830152016102f0565b34801561077357600080fd5b50610326610782366004612d70565b60076020526000908152604090205481565b3480156107a057600080fd5b506103e86107af366004612f23565b611cdb565b3480156107c057600080fd5b506103e86107cf366004612f23565b611f05565b3480156107e057600080fd5b506103e86107ef3660046132bb565b61212f565b34801561080057600080fd5b5061064a61080f3660046132dd565b6121a7565b34801561082057600080fd5b5061064a61082f366004612d70565b6003602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b34801561087757600080fd5b5061089f7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016102f0565b3480156108c057600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b3480156108f457600080fd5b506103e8610903366004612eb1565b612212565b34801561091457600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b34801561094857600080fd5b506102d3610957366004612d27565b60066020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b34801561099257600080fd5b506103e86109a1366004613339565b61226d565b3480156109b257600080fd5b5061070b6109c1366004612d8b565b6124a6565b3480156109d257600080fd5b506103e86109e1366004613365565b6124bd565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a37576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a4283838361252c565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a98576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610aa75750848314155b15610ade576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110610afe57610afe6133a3565b9050602002016020810190610b139190612d70565b63ffffffff161115610b9357610b8e888883818110610b3457610b346133a3565b90506020020135878784818110610b4d57610b4d6133a3565b9050602002016020810190610b629190612d70565b868685818110610b7457610b746133a3565b9050602002016020810190610b899190612d53565b61252c565b610bdb565b610bdb888883818110610ba857610ba86133a3565b90506020020135858584818110610bc157610bc16133a3565b9050602002016020810190610bd69190612d53565b612569565b600101610ae2565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c3e576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a428383836125ec565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c9a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612629565b5050565b604080517f5498237e9cba7720b9d4b88ac1ad78e4c78dae0cb7b6b33a329e330ca9349f8f602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991610daa918790879060e4016133d2565b602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190613426565b9050610e1e7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614610e84576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260086020908152604091829020879055815192835282018690527f9e2bb394655fb30d5d70b657711b435d31ad553885bfea5d029d96b4cc82dc7a91015b60405180910390a1505050505050565b6000610eec85858585612742565b95945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f46576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f4f336127ec565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fa2576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610fb15750848314155b15610fe8576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110611008576110086133a3565b905060200201602081019061101d9190612d70565b63ffffffff16111561109d5761109888888381811061103e5761103e6133a3565b90506020020135878784818110611057576110576133a3565b905060200201602081019061106c9190612d70565b86868581811061107e5761107e6133a3565b90506020020160208101906110939190612d53565b6125ec565b6110e5565b6110e58888838181106110b2576110b26133a3565b905060200201358585848181106110cb576110cb6133a3565b90506020020160208101906110e09190612d53565b612629565b600101610fec565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397aba7f97ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab6307f0000000000000000000000000000000000000000000000000000000000000000898b8a604051602001611186969594939291906134aa565b6040516020818303038152906040528051906020012085856040518463ffffffff1660e01b81526004016111bc939291906133d2565b602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613426565b90506112307f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611296576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff85166000908152600a6020526040902084906112b78282613501565b9050507fb2f6c1f8eb5fbd0c54cd0ffc1e20678d7e991cb8aed8471c1252cdc7d64549be8585604051610ece9291906135fb565b60005473ffffffffffffffffffffffffffffffffffffffff16331461133c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661143d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b611448848484612864565b50505050565b63ffffffff82166000908152600360205260409020546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000009092041610156114c6576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82166000908152600360205260409020805482919060109061151490849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166341805c246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db9190613426565b6040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8516600482015290915073ffffffffffffffffffffffffffffffffffffffff82169063a9a541b2906fffffffffffffffffffffffffffffffff8516906024016000604051808303818588803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8616815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8716918101919091527fb8fee8df7dff1cee6b16775bb2292a5341317514d9c5399dd2a62303e3f92c1a935060600191506116e69050565b60405180910390a1505050565b6000806fffffffffffffffffffffffffffffffff341061173f576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260066020908152604080832063ffffffff8c16845290915290205434906117959085906fffffffffffffffffffffffffffffffff166136a3565b915060006117a58e8e8e8d612742565b905060006117b389836136d2565b9050806117c08b866136d2565b6117ca91906136d2565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff161015611827576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b896118328585613644565b61183c9190613644565b63ffffffff8c166000908152600360209081526040918290208251808401845290546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041691810191909152815180830190925280519297509181906118ac9089906136d2565b6fffffffffffffffffffffffffffffffff1681526020018683602001516118d391906136d2565b6fffffffffffffffffffffffffffffffff90811690915263ffffffff8e1660008181526003602090815260408083208651968301518616700100000000000000000000000000000000029686169690961790955573ffffffffffffffffffffffffffffffffffffffff8d168252600481528482209282529190915291822080548e939192611963918591166136d2565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050509a509a98505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff871684529091529020546fffffffffffffffffffffffffffffffff80831691161015611a31576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff8716845290915281208054839290611a899084906fffffffffffffffffffffffffffffffff16613644565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8616600482015273ffffffffffffffffffffffffffffffffffffffff8516925063a9a541b2918416906024016000604051808303818588803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8716815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8616918101919091527fe7ea372fbcab98f6f74f62c16d1127e475529579f63121bf168773850739e3f9935060600191506116e69050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397aba7f985856040518363ffffffff1660e01b8152600401611c459291906136fb565b602060405180830381865afa158015611c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c869190613426565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f59aaad84481dba1ea935653b992572e94234e3bd8a15f7adf9511af432a4fd4f602052604090205490925060ff165b90509250929050565b604080517f097d8e0ecdafcc3ab6916c2b486af7d06325dcdf5bd46372f340eea8cffd674c602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991611ddd918790879060e4016133d2565b602060405180830381865afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190613426565b9050611e517f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611eb7576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260076020908152604091829020879055815192835282018690527fcaade52e9295f5cd4e1762d70bf40bf839fbbc232469ca3c7ac0de77d156d4889101610ece565b604080517f6ae815499d9e0b180f1f7632798b7dfd6565f2ed8e2745b19af5de7bde5e62aa602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916397aba7f991612007918790879060e4016133d2565b602060405180830381865afa158015612024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120489190613426565b905061207b7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902080546001810190915586146120e1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260096020908152604091829020879055815192835282018690527ff31f7eb11567a8d1fd792197d4328a9b4514b8fe89a70807e29132ce2b8e93f09101610ece565b8160f881901c60008190036121445750505050565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216808410156121a0576040517f78f38f7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806121b688888887612742565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260066020908152604080832063ffffffff9097168352959052939093205491976fffffffffffffffffffffffffffffffff909216965090945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612263576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612569565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166122fa576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b73ffffffffffffffffffffffffffffffffffffffff8216612347576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84166000908152600360205260409020546fffffffffffffffffffffffffffffffff808516911610156123ab576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8416600090815260036020526040812080548592906123e29084906fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061243482846fffffffffffffffffffffffffffffffff16612954565b6040805173ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff861660208201526fffffffffffffffffffffffffffffffff85168183015290517fb2d1c6b6dcf53eb15f8fb6c88a3642c4d7407333bcd0e16d6e5789f6beb51fb99181900360600190a150505050565b60006124b38484846129c9565b90505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a42576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838360405160200161255192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610a42838360405160200161261192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611448576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b6000611388841115612780576040517f492f620d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061278c8385612a57565b612797878786612b71565b6127a1919061376f565b90506fffffffffffffffffffffffffffffffff8110610eec576040517fc9034e1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff82166128b1576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016128f857610a428282612954565b8273ffffffffffffffffffffffffffffffffffffffff163b600003612949576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838383612c1a565b600080600080600085875af1905080610a42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401611434565b60006124b384846040516020016129f092919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60008160f881901c808303612a7157600092505050611be1565b63ffffffff85166000908152600860205260409020547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690811015612ae3576040517f508aaf0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260096020526040902054811115612b32576040517f5dffc92f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040902054670de0b6b3a764000090612b5d908390613782565b612b679190613799565b9695505050505050565b63ffffffff81166000908152600a602090815260408083208151606081018352905469ffffffffffffffffffff80821683526a01000000000000000000008204811694830185905274010000000000000000000000000000000000000000909104169181019190915290612be59085613782565b6040820151825169ffffffffffffffffffff91821691612c06911688613782565b612c10919061376f565b610eec919061376f565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401611434565b73ffffffffffffffffffffffffffffffffffffffff81168114612d0b57600080fd5b50565b803563ffffffff81168114612d2257600080fd5b919050565b60008060408385031215612d3a57600080fd5b8235612d4581612ce9565b9150611cd260208401612d0e565b600060208284031215612d6557600080fd5b81356124b681612ce9565b600060208284031215612d8257600080fd5b611bde82612d0e565b600080600060608486031215612da057600080fd5b83359250612db060208501612d0e565b91506040840135612dc081612ce9565b809150509250925092565b60008083601f840112612ddd57600080fd5b50813567ffffffffffffffff811115612df557600080fd5b6020830191508360208260051b8501011115612e1057600080fd5b9250929050565b60008060008060008060608789031215612e3057600080fd5b863567ffffffffffffffff80821115612e4857600080fd5b612e548a838b01612dcb565b90985096506020890135915080821115612e6d57600080fd5b612e798a838b01612dcb565b90965094506040890135915080821115612e9257600080fd5b50612e9f89828a01612dcb565b979a9699509497509295939492505050565b60008060408385031215612ec457600080fd5b823591506020830135612ed681612ce9565b809150509250929050565b60008083601f840112612ef357600080fd5b50813567ffffffffffffffff811115612f0b57600080fd5b602083019150836020828501011115612e1057600080fd5b600080600080600060808688031215612f3b57600080fd5b85359450612f4b60208701612d0e565b935060408601359250606086013567ffffffffffffffff811115612f6e57600080fd5b612f7a88828901612ee1565b969995985093965092949392505050565b60008060008060808587031215612fa157600080fd5b843593506020850135925060408501359150612fbf60608601612d0e565b905092959194509250565b80356fffffffffffffffffffffffffffffffff81168114612d2257600080fd5b60008060408385031215612ffd57600080fd5b61300683612d0e565b9150611cd260208401612fca565b600080600080600085870360c081121561302d57600080fd5b8635955061303d60208801612d0e565b945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561306f57600080fd5b5060408601925060a086013567ffffffffffffffff811115612f6e57600080fd5b6000806000606084860312156130a557600080fd5b83356130b081612ce9565b925060208401356130c081612ce9565b929592945050506040919091013590565b6000806000806000806000806000806101408b8d0312156130f157600080fd5b8a35995060208b0135985060408b0135975060608b0135965061311660808c01612d0e565b955061312460a08c01612fca565b945061313260c08c01612fca565b935060e08b013561314281612ce9565b92506101008b013561315381612ce9565b809250506101208b013590509295989b9194979a5092959850565b60008060006060848603121561318357600080fd5b61318c84612d0e565b9250602084013561319c81612ce9565b91506131aa60408501612fca565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156131f557600080fd5b82359150602083013567ffffffffffffffff8082111561321457600080fd5b818501915085601f83011261322857600080fd5b81358181111561323a5761323a6131b3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613280576132806131b3565b8160405282815288602084870101111561329957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156132ce57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156132f657600080fd5b8635955060208701359450604087013593506060870135925061331b60808801612d0e565b915060a087013561332b81612ce9565b809150509295509295509295565b60008060006060848603121561334e57600080fd5b61335784612d0e565b9250612db060208501612fca565b60008060006060848603121561337a57600080fd5b833561338581612ce9565b925061339360208501612fca565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b60006020828403121561343857600080fd5b81516124b681612ce9565b69ffffffffffffffffffff81168114612d0b57600080fd5b803561346681613443565b69ffffffffffffffffffff908116835260208201359061348582613443565b908116602084015260408201359061349c82613443565b808216604085015250505050565b86815273ffffffffffffffffffffffffffffffffffffffff8616602082015263ffffffff8581166040830152841660608201526080810183905261010081016134f660a083018461345b565b979650505050505050565b813561350c81613443565b69ffffffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffff000000000000000000008216178355602084013561355281613443565b73ffffffffffffffffffff000000000000000000008160501b16905080837fffffffffffffffffffffffff000000000000000000000000000000000000000084161717845560408501356135a581613443565b7dffffffffffffffffffff00000000000000000000000000000000000000008160a01b16847fffff0000000000000000000000000000000000000000000000000000000000008516178317178555505050505050565b63ffffffff83168152608081016124b6602083018461345b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6fffffffffffffffffffffffffffffffff82811682821603908082111561366d5761366d613615565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806136c6576136c6613674565b92169190910492915050565b6fffffffffffffffffffffffffffffffff81811683821601908082111561366d5761366d613615565b82815260006020604081840152835180604085015260005b8181101561372f57858101830151858201606001528201613713565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b80820180821115611be157611be1613615565b8082028115828204841417611be157611be1613615565b6000826137a8576137a8613674565b50049056fea2646970667358221220292c2e2bf30a9440f46947d47360cb503a712b032e39f687ce437e4f01c9c5ab64736f6c6343000813003300000000000000000000000044a44837894b5edc2bde64567fc62599b3b88f4c0000000000000000000000000000000000000000000000000000000000028c610000000000000000000000005c4186d343eef952c9ed886e45f8243edf0a503f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f
Deployed ByteCode
0x6080604052600436106102845760003560e01c80637644e7fa11610153578063aea3d96b116100cb578063d5b8da731161007f578063de8c4ff911610064578063de8c4ff914610986578063ecb97484146109a6578063f1f069d6146109c657600080fd5b8063d5b8da7314610908578063d81381d51461093c57600080fd5b8063b349ba65116100b0578063b349ba651461086b578063c6a261d2146108b4578063d547741f146108e857600080fd5b8063aea3d96b146107f4578063b0c342291461081457600080fd5b8063954d09c9116101225780639f102855116101075780639f10285514610794578063a1885700146107b4578063a56d92ce146107d457600080fd5b8063954d09c91461071b578063955b15901461076757600080fd5b80637644e7fa146106735780638da5cb5b146106a057806390d241f1146106cb57806391d14854146106eb57600080fd5b806338fe30251161020157806350a9cf67116101b55780636ccae0541161019a5780636ccae054146105f75780636e3c05621461061757806371c4717b1461063757600080fd5b806350a9cf67146105b75780635b94db27146105d757600080fd5b80633bd1adec116101e65780633bd1adec1461055557806343fa97ca1461056a5780634d1bf1891461058a57600080fd5b806338fe3025146104b65780633b13d3f1146104d657600080fd5b80631e867311116102585780632e7eb2581161023d5780632e7eb258146104565780632f2ff15d14610476578063308795b21461049657600080fd5b80631e867311146103ea57806320f99c0a1461040a57600080fd5b80626fc3e2146102895780630cd55abf146102f957806311cf8aa5146103345780631ba8e484146103c8575b600080fd5b34801561029557600080fd5b506102d36102a4366004612d27565b60046020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561030557600080fd5b50610326610314366004612d53565b60056020526000908152604090205481565b6040519081526020016102f0565b34801561034057600080fd5b5061039b61034f366004612d70565b600a6020526000908152604090205469ffffffffffffffffffff808216916a01000000000000000000008104821691740100000000000000000000000000000000000000009091041683565b6040805169ffffffffffffffffffff948516815292841660208401529216918101919091526060016102f0565b3480156103d457600080fd5b506103e86103e3366004612d8b565b6109e6565b005b3480156103f657600080fd5b506103e8610405366004612e17565b610a47565b34801561041657600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f0565b34801561046257600080fd5b506103e8610471366004612d8b565b610bed565b34801561048257600080fd5b506103e8610491366004612eb1565b610c49565b3480156104a257600080fd5b506103e86104b1366004612f23565b610ca8565b3480156104c257600080fd5b506102d36104d1366004612f8b565b610ede565b3480156104e257600080fd5b506103e86104f1366004612fea565b33600090815260066020908152604080832063ffffffff9590951683529390529190912080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff909216919091179055565b34801561056157600080fd5b506103e8610ef5565b34801561057657600080fd5b506103e8610585366004612e17565b610f51565b34801561059657600080fd5b506103266105a5366004612d70565b60096020526000908152604090205481565b3480156105c357600080fd5b506103e86105d2366004613014565b6110ed565b3480156105e357600080fd5b506103e86105f2366004612d53565b6112eb565b34801561060357600080fd5b506103e8610612366004613090565b6113ab565b34801561062357600080fd5b506103e8610632366004612fea565b61144e565b61064a6106453660046130d1565b6116f3565b604080516fffffffffffffffffffffffffffffffff9384168152929091166020830152016102f0565b34801561067f57600080fd5b5061032661068e366004612d70565b60086020526000908152604090205481565b3480156106ac57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610431565b3480156106d757600080fd5b506103e86106e636600461316e565b6119ac565b3480156106f757600080fd5b5061070b610706366004612eb1565b611baa565b60405190151581526020016102f0565b34801561072757600080fd5b5061073b6107363660046131e2565b611be7565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683529015156020830152016102f0565b34801561077357600080fd5b50610326610782366004612d70565b60076020526000908152604090205481565b3480156107a057600080fd5b506103e86107af366004612f23565b611cdb565b3480156107c057600080fd5b506103e86107cf366004612f23565b611f05565b3480156107e057600080fd5b506103e86107ef3660046132bb565b61212f565b34801561080057600080fd5b5061064a61080f3660046132dd565b6121a7565b34801561082057600080fd5b5061064a61082f366004612d70565b6003602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b34801561087757600080fd5b5061089f7f0000000000000000000000000000000000000000000000000000000000028c6181565b60405163ffffffff90911681526020016102f0565b3480156108c057600080fd5b506104317f0000000000000000000000005c4186d343eef952c9ed886e45f8243edf0a503f81565b3480156108f457600080fd5b506103e8610903366004612eb1565b612212565b34801561091457600080fd5b506104317f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f81565b34801561094857600080fd5b506102d3610957366004612d27565b60066020908152600092835260408084209091529082529020546fffffffffffffffffffffffffffffffff1681565b34801561099257600080fd5b506103e86109a1366004613339565b61226d565b3480156109b257600080fd5b5061070b6109c1366004612d8b565b6124a6565b3480156109d257600080fd5b506103e86109e1366004613365565b6124bd565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a37576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a4283838361252c565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a98576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610aa75750848314155b15610ade576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110610afe57610afe6133a3565b9050602002016020810190610b139190612d70565b63ffffffff161115610b9357610b8e888883818110610b3457610b346133a3565b90506020020135878784818110610b4d57610b4d6133a3565b9050602002016020810190610b629190612d70565b868685818110610b7457610b746133a3565b9050602002016020810190610b899190612d53565b61252c565b610bdb565b610bdb888883818110610ba857610ba86133a3565b90506020020135858584818110610bc157610bc16133a3565b9050602002016020810190610bd69190612d53565b612569565b600101610ae2565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c3e576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a428383836125ec565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c9a576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612629565b5050565b604080517f5498237e9cba7720b9d4b88ac1ad78e4c78dae0cb7b6b33a329e330ca9349f8f602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000028c61811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f16916397aba7f991610daa918790879060e4016133d2565b602060405180830381865afa158015610dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610deb9190613426565b9050610e1e7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614610e84576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260086020908152604091829020879055815192835282018690527f9e2bb394655fb30d5d70b657711b435d31ad553885bfea5d029d96b4cc82dc7a91015b60405180910390a1505050505050565b6000610eec85858585612742565b95945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f46576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f4f336127ec565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fa2576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8481141580610fb15750848314155b15610fe8576040517f11e86f7300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460005b81811015610be3576000868683818110611008576110086133a3565b905060200201602081019061101d9190612d70565b63ffffffff16111561109d5761109888888381811061103e5761103e6133a3565b90506020020135878784818110611057576110576133a3565b905060200201602081019061106c9190612d70565b86868581811061107e5761107e6133a3565b90506020020160208101906110939190612d53565b6125ec565b6110e5565b6110e58888838181106110b2576110b26133a3565b905060200201358585848181106110cb576110cb6133a3565b90506020020160208101906110e09190612d53565b612629565b600101610fec565b60007f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f73ffffffffffffffffffffffffffffffffffffffff166397aba7f97ff2deac1744cfd52ddfce21c5ff26abf413f6418dc4a35916e26daefd87e04ab6307f0000000000000000000000000000000000000000000000000000000000028c61898b8a604051602001611186969594939291906134aa565b6040516020818303038152906040528051906020012085856040518463ffffffff1660e01b81526004016111bc939291906133d2565b602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd9190613426565b90506112307f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611296576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff85166000908152600a6020526040902084906112b78282613501565b9050507fb2f6c1f8eb5fbd0c54cd0ffc1e20678d7e991cb8aed8471c1252cdc7d64549be8585604051610ece9291906135fb565b60005473ffffffffffffffffffffffffffffffffffffffff16331461133c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f4933f7bec34ee32db93e9f5cd7e0519781b395282211f4f6857489046ea38f7660205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661143d576040517f962f6333000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b611448848484612864565b50505050565b63ffffffff82166000908152600360205260409020546fffffffffffffffffffffffffffffffff8083167001000000000000000000000000000000009092041610156114c6576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82166000908152600360205260409020805482919060109061151490849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060007f0000000000000000000000005c4186d343eef952c9ed886e45f8243edf0a503f73ffffffffffffffffffffffffffffffffffffffff166341805c246040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db9190613426565b6040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8516600482015290915073ffffffffffffffffffffffffffffffffffffffff82169063a9a541b2906fffffffffffffffffffffffffffffffff8516906024016000604051808303818588803b15801561165e57600080fd5b505af1158015611672573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8616815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8716918101919091527fb8fee8df7dff1cee6b16775bb2292a5341317514d9c5399dd2a62303e3f92c1a935060600191506116e69050565b60405180910390a1505050565b6000806fffffffffffffffffffffffffffffffff341061173f576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260066020908152604080832063ffffffff8c16845290915290205434906117959085906fffffffffffffffffffffffffffffffff166136a3565b915060006117a58e8e8e8d612742565b905060006117b389836136d2565b9050806117c08b866136d2565b6117ca91906136d2565b6fffffffffffffffffffffffffffffffff16836fffffffffffffffffffffffffffffffff161015611827576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b896118328585613644565b61183c9190613644565b63ffffffff8c166000908152600360209081526040918290208251808401845290546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041691810191909152815180830190925280519297509181906118ac9089906136d2565b6fffffffffffffffffffffffffffffffff1681526020018683602001516118d391906136d2565b6fffffffffffffffffffffffffffffffff90811690915263ffffffff8e1660008181526003602090815260408083208651968301518616700100000000000000000000000000000000029686169690961790955573ffffffffffffffffffffffffffffffffffffffff8d168252600481528482209282529190915291822080548e939192611963918591166136d2565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550505050509a509a98505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff871684529091529020546fffffffffffffffffffffffffffffffff80831691161015611a31576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260046020908152604080832063ffffffff8716845290915281208054839290611a899084906fffffffffffffffffffffffffffffffff16613644565b82546101009290920a6fffffffffffffffffffffffffffffffff8181021990931691831602179091556040517fa9a541b200000000000000000000000000000000000000000000000000000000815263ffffffff8616600482015273ffffffffffffffffffffffffffffffffffffffff8516925063a9a541b2918416906024016000604051808303818588803b158015611b2257600080fd5b505af1158015611b36573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8716815263ffffffff881660208201526fffffffffffffffffffffffffffffffff8616918101919091527fe7ea372fbcab98f6f74f62c16d1127e475529579f63121bf168773850739e3f9935060600191506116e69050565b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b90505b92915050565b6000807f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f73ffffffffffffffffffffffffffffffffffffffff166397aba7f985856040518363ffffffff1660e01b8152600401611c459291906136fb565b602060405180830381865afa158015611c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c869190613426565b73ffffffffffffffffffffffffffffffffffffffff811660009081527f59aaad84481dba1ea935653b992572e94234e3bd8a15f7adf9511af432a4fd4f602052604090205490925060ff165b90509250929050565b604080517f097d8e0ecdafcc3ab6916c2b486af7d06325dcdf5bd46372f340eea8cffd674c602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000028c61811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f16916397aba7f991611ddd918790879060e4016133d2565b602060405180830381865afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190613426565b9050611e517f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604090208054600181019091558614611eb7576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260076020908152604091829020879055815192835282018690527fcaade52e9295f5cd4e1762d70bf40bf839fbbc232469ca3c7ac0de77d156d4889101610ece565b604080517f6ae815499d9e0b180f1f7632798b7dfd6565f2ed8e2745b19af5de7bde5e62aa602080830191909152308284015263ffffffff7f0000000000000000000000000000000000000000000000000000000000028c61811660608401528716608083015260a0820188905260c08083018790528351808403909101815260e083019384905280519101207f97aba7f90000000000000000000000000000000000000000000000000000000090925260009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef1ae2f8b4e18afdddf1ca92037772891100a39f16916397aba7f991612007918790879060e4016133d2565b602060405180830381865afa158015612024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120489190613426565b905061207b7f429672025b2dcb8754ca4b57943f34ac66900598787cb1f1e857291dedbf34d38663ffffffff16836126af565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040902080546001810190915586146120e1576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8516600081815260096020908152604091829020879055815192835282018690527ff31f7eb11567a8d1fd792197d4328a9b4514b8fe89a70807e29132ce2b8e93f09101610ece565b8160f881901c60008190036121445750505050565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216808410156121a0576040517f78f38f7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000806121b688888887612742565b73ffffffffffffffffffffffffffffffffffffffff909316600090815260066020908152604080832063ffffffff9097168352959052939093205491976fffffffffffffffffffffffffffffffff909216965090945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612263576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca48282612569565b3360009081527f9b7ec560033b826bc253a5f1a8b5e6a61c8d2a6e8731a9872b68296f6024c5ac60205260409020547f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec9060ff166122fa576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b73ffffffffffffffffffffffffffffffffffffffff8216612347576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84166000908152600360205260409020546fffffffffffffffffffffffffffffffff808516911610156123ab576040517f8d53e55300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8416600090815260036020526040812080548592906123e29084906fffffffffffffffffffffffffffffffff16613644565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061243482846fffffffffffffffffffffffffffffffff16612954565b6040805173ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff861660208201526fffffffffffffffffffffffffffffffff85168183015290517fb2d1c6b6dcf53eb15f8fb6c88a3642c4d7407333bcd0e16d6e5789f6beb51fb99181900360600190a150505050565b60006124b38484846129c9565b90505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005c4186d343eef952c9ed886e45f8243edf0a503f1614610a42576040517f503284dc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838360405160200161255192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b610a42838360405160200161261192919091825263ffffffff16602082015260400190565b60405160208183030381529060405280519060200120825b600082815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6040805160208082018690528183018590528251808303840181526060909201835281519181019190912060008181526002835283812073ffffffffffffffffffffffffffffffffffffffff861682529092529190205460ff16611448576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401611434565b6000611388841115612780576040517f492f620d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061278c8385612a57565b612797878786612b71565b6127a1919061376f565b90506fffffffffffffffffffffffffffffffff8110610eec576040517fc9034e1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b73ffffffffffffffffffffffffffffffffffffffff82166128b1576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016128f857610a428282612954565b8273ffffffffffffffffffffffffffffffffffffffff163b600003612949576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a42838383612c1a565b600080600080600085875af1905080610a42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401611434565b60006124b384846040516020016129f092919091825263ffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060009081526002835281812073ffffffffffffffffffffffffffffffffffffffff8716825290925290205460ff1690565b60008160f881901c808303612a7157600092505050611be1565b63ffffffff85166000908152600860205260409020547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690811015612ae3576040517f508aaf0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260096020526040902054811115612b32576040517f5dffc92f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8616600090815260076020526040902054670de0b6b3a764000090612b5d908390613782565b612b679190613799565b9695505050505050565b63ffffffff81166000908152600a602090815260408083208151606081018352905469ffffffffffffffffffff80821683526a01000000000000000000008204811694830185905274010000000000000000000000000000000000000000909104169181019190915290612be59085613782565b6040820151825169ffffffffffffffffffff91821691612c06911688613782565b612c10919061376f565b610eec919061376f565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611448576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401611434565b73ffffffffffffffffffffffffffffffffffffffff81168114612d0b57600080fd5b50565b803563ffffffff81168114612d2257600080fd5b919050565b60008060408385031215612d3a57600080fd5b8235612d4581612ce9565b9150611cd260208401612d0e565b600060208284031215612d6557600080fd5b81356124b681612ce9565b600060208284031215612d8257600080fd5b611bde82612d0e565b600080600060608486031215612da057600080fd5b83359250612db060208501612d0e565b91506040840135612dc081612ce9565b809150509250925092565b60008083601f840112612ddd57600080fd5b50813567ffffffffffffffff811115612df557600080fd5b6020830191508360208260051b8501011115612e1057600080fd5b9250929050565b60008060008060008060608789031215612e3057600080fd5b863567ffffffffffffffff80821115612e4857600080fd5b612e548a838b01612dcb565b90985096506020890135915080821115612e6d57600080fd5b612e798a838b01612dcb565b90965094506040890135915080821115612e9257600080fd5b50612e9f89828a01612dcb565b979a9699509497509295939492505050565b60008060408385031215612ec457600080fd5b823591506020830135612ed681612ce9565b809150509250929050565b60008083601f840112612ef357600080fd5b50813567ffffffffffffffff811115612f0b57600080fd5b602083019150836020828501011115612e1057600080fd5b600080600080600060808688031215612f3b57600080fd5b85359450612f4b60208701612d0e565b935060408601359250606086013567ffffffffffffffff811115612f6e57600080fd5b612f7a88828901612ee1565b969995985093965092949392505050565b60008060008060808587031215612fa157600080fd5b843593506020850135925060408501359150612fbf60608601612d0e565b905092959194509250565b80356fffffffffffffffffffffffffffffffff81168114612d2257600080fd5b60008060408385031215612ffd57600080fd5b61300683612d0e565b9150611cd260208401612fca565b600080600080600085870360c081121561302d57600080fd5b8635955061303d60208801612d0e565b945060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561306f57600080fd5b5060408601925060a086013567ffffffffffffffff811115612f6e57600080fd5b6000806000606084860312156130a557600080fd5b83356130b081612ce9565b925060208401356130c081612ce9565b929592945050506040919091013590565b6000806000806000806000806000806101408b8d0312156130f157600080fd5b8a35995060208b0135985060408b0135975060608b0135965061311660808c01612d0e565b955061312460a08c01612fca565b945061313260c08c01612fca565b935060e08b013561314281612ce9565b92506101008b013561315381612ce9565b809250506101208b013590509295989b9194979a5092959850565b60008060006060848603121561318357600080fd5b61318c84612d0e565b9250602084013561319c81612ce9565b91506131aa60408501612fca565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156131f557600080fd5b82359150602083013567ffffffffffffffff8082111561321457600080fd5b818501915085601f83011261322857600080fd5b81358181111561323a5761323a6131b3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715613280576132806131b3565b8160405282815288602084870101111561329957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156132ce57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156132f657600080fd5b8635955060208701359450604087013593506060870135925061331b60808801612d0e565b915060a087013561332b81612ce9565b809150509295509295509295565b60008060006060848603121561334e57600080fd5b61335784612d0e565b9250612db060208501612fca565b60008060006060848603121561337a57600080fd5b833561338581612ce9565b925061339360208501612fca565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b60006020828403121561343857600080fd5b81516124b681612ce9565b69ffffffffffffffffffff81168114612d0b57600080fd5b803561346681613443565b69ffffffffffffffffffff908116835260208201359061348582613443565b908116602084015260408201359061349c82613443565b808216604085015250505050565b86815273ffffffffffffffffffffffffffffffffffffffff8616602082015263ffffffff8581166040830152841660608201526080810183905261010081016134f660a083018461345b565b979650505050505050565b813561350c81613443565b69ffffffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffff000000000000000000008216178355602084013561355281613443565b73ffffffffffffffffffff000000000000000000008160501b16905080837fffffffffffffffffffffffff000000000000000000000000000000000000000084161717845560408501356135a581613443565b7dffffffffffffffffffff00000000000000000000000000000000000000008160a01b16847fffff0000000000000000000000000000000000000000000000000000000000008516178317178555505050505050565b63ffffffff83168152608081016124b6602083018461345b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6fffffffffffffffffffffffffffffffff82811682821603908082111561366d5761366d613615565b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806136c6576136c6613674565b92169190910492915050565b6fffffffffffffffffffffffffffffffff81811683821601908082111561366d5761366d613615565b82815260006020604081840152835180604085015260005b8181101561372f57858101830151858201606001528201613713565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509392505050565b80820180821115611be157611be1613615565b8082028115828204841417611be157611be1613615565b6000826137a8576137a8613674565b50049056fea2646970667358221220292c2e2bf30a9440f46947d47360cb503a712b032e39f687ce437e4f01c9c5ab64736f6c63430008130033