Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multi Chain
Multichain Addresses
7 addresses found via
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
9501990 | 44 days 20 hrs ago | 0 ETH | ||||
9501990 | 44 days 20 hrs ago | 0 ETH | ||||
9501990 | 44 days 20 hrs ago | 0 ETH | ||||
9501990 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501977 | 44 days 20 hrs ago | 0 ETH | ||||
9501975 | 44 days 20 hrs ago | 0 ETH | ||||
9501975 | 44 days 20 hrs ago | 0 ETH | ||||
9501975 | 44 days 20 hrs ago | 0 ETH | ||||
9501975 | 44 days 20 hrs ago | 0 ETH | ||||
9501974 | 44 days 21 hrs ago | 0 ETH | ||||
9501974 | 44 days 21 hrs ago | 0 ETH | ||||
9501974 | 44 days 21 hrs ago | 0 ETH | ||||
9501974 | 44 days 21 hrs ago | 0 ETH | ||||
9501972 | 44 days 21 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
StateBridge
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; // Optimism interface for cross domain messaging import {ICrossDomainMessenger} from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; import {IOpWorldID} from "./interfaces/IOpWorldID.sol"; import {IPolygonWorldID} from "./interfaces/IPolygonWorldID.sol"; import {IRootHistory} from "./interfaces/IRootHistory.sol"; import {Ownable2Step} from "openzeppelin-contracts/access/Ownable2Step.sol"; import {ICrossDomainOwnable3} from "./interfaces/ICrossDomainOwnable3.sol"; import {FxBaseRootTunnel} from "fx-portal/contracts/tunnel/FxBaseRootTunnel.sol"; /// @title World ID State Bridge /// @author Worldcoin /// @notice Distributes new World ID Identity Manager roots to World ID supported networks /// @dev This contract lives on Ethereum mainnet and is called by the World ID Identity Manager contract /// in the registerIdentities method contract StateBridge is FxBaseRootTunnel, Ownable2Step { /////////////////////////////////////////////////////////////////// /// STORAGE /// /////////////////////////////////////////////////////////////////// /// @notice The address of the OPWorldID contract on Optimism address public immutable opWorldIDAddress; /// @notice address for Optimism's Ethereum mainnet L1CrossDomainMessenger contract address internal immutable opCrossDomainMessengerAddress; /// @notice The address of the BaseWorldID contract on Base address public immutable baseWorldIDAddress; /// @notice address for Base's Ethereum mainnet L1CrossDomainMessenger contract address internal immutable baseCrossDomainMessengerAddress; /// @notice worldID Address address public immutable worldIDAddress; /// @notice Amount of gas purchased on Optimism for _sendRootToOptimism uint32 internal gasLimitSendRootOptimism; /// @notice Amount of gas purchased on Optimism for setRootHistoryExpiryOptimism uint32 internal gasLimitSetRootHistoryExpiryOptimism; /// @notice Amount of gas purchased on Optimism for transferOwnershipOptimism uint32 internal gasLimitTransferOwnershipOptimism; /// @notice Amount of gas purchased on Base for _sendRootToBase uint32 internal gasLimitSendRootBase; /// @notice Amount of gas purchased on Base for setRootHistoryExpiryBase uint32 internal gasLimitSetRootHistoryExpiryBase; /// @notice Amount of gas purchased on Base for transferOwnershipBase uint32 internal gasLimitTransferOwnershipBase; /////////////////////////////////////////////////////////////////// /// EVENTS /// /////////////////////////////////////////////////////////////////// /// @notice Emmitted when the the StateBridge gives ownership of the OPWorldID contract /// to the WorldID Identity Manager contract away /// @param previousOwner The previous owner of the OPWorldID contract /// @param newOwner The new owner of the OPWorldID contract /// @param isLocal Whether the ownership transfer is local (Optimism EOA/contract) or an Ethereum EOA or contract event OwnershipTransferredOptimism( address indexed previousOwner, address indexed newOwner, bool isLocal ); /// @notice Emmitted when the the StateBridge gives ownership of the OPWorldID contract /// to the WorldID Identity Manager contract away /// @param previousOwner The previous owner of the OPWorldID contract /// @param newOwner The new owner of the OPWorldID contract /// @param isLocal Whether the ownership transfer is local (Base EOA/contract) or an Ethereum EOA or contract event OwnershipTransferredBase( address indexed previousOwner, address indexed newOwner, bool isLocal ); /// @notice Emmitted when the the StateBridge sets the root history expiry for OpWorldID and PolygonWorldID /// @param rootHistoryExpiry The new root history expiry event SetRootHistoryExpiry(uint256 rootHistoryExpiry); /// @notice Emmitted when a root is sent to OpWorldID and PolygonWorldID /// @param root The latest WorldID Identity Manager root. /// @param timestamp The Ethereum block timestamp of the latest WorldID Identity Manager root. event RootSentMultichain(uint256 root, uint128 timestamp); /// @notice Emmitted when the the StateBridge sets the gas limit for sendRootOptimism /// @param _opGasLimit The new opGasLimit for sendRootOptimism event SetGasLimitSendRootOptimism(uint32 _opGasLimit); /// @notice Emmitted when the the StateBridge sets the gas limit for setRootHistoryExpiryOptimism /// @param _opGasLimit The new opGasLimit for setRootHistoryExpiryOptimism event SetGasLimitSetRootHistoryExpiryOptimism(uint32 _opGasLimit); /// @notice Emmitted when the the StateBridge sets the gas limit for transferOwnershipOptimism /// @param _opGasLimit The new opGasLimit for transferOwnershipOptimism event SetGasLimitTransferOwnershipOptimism(uint32 _opGasLimit); /// @notice Emmitted when the the StateBridge sets the gas limit for sendRootBase /// @param _baseGasLimit The new baseGasLimit for sendRootBase event SetGasLimitSendRootBase(uint32 _baseGasLimit); /// @notice Emmitted when the the StateBridge sets the gas limit for setRootHistoryExpiryBase /// @param _baseGasLimit The new baseGasLimit for setRootHistoryExpiryBase event SetGasLimitSetRootHistoryExpiryBase(uint32 _baseGasLimit); /// @notice Emmitted when the the StateBridge sets the gas limit for transferOwnershipBase /// @param _baseGasLimit The new baseGasLimit for transferOwnershipBase event SetGasLimitTransferOwnershipBase(uint32 _baseGasLimit); /////////////////////////////////////////////////////////////////// /// ERRORS /// /////////////////////////////////////////////////////////////////// /// @notice Thrown when the caller of `sendRootMultichain` is not the WorldID Identity Manager contract. error NotWorldIDIdentityManager(); /// @notice Thrown when an attempt is made to renounce ownership. error CannotRenounceOwnership(); /////////////////////////////////////////////////////////////////// /// MODIFIERS /// /////////////////////////////////////////////////////////////////// modifier onlyWorldIDIdentityManager() { if (msg.sender != worldIDAddress) { revert NotWorldIDIdentityManager(); } _; } /////////////////////////////////////////////////////////////////// /// CONSTRUCTOR /// /////////////////////////////////////////////////////////////////// /// @notice constructor /// @param _checkpointManager address of the checkpoint manager contract /// @param _fxRoot address of Polygon's fxRoot contract, part of the FxPortal bridge (Goerli or Mainnet) /// @param _worldIDIdentityManager Deployment address of the WorldID Identity Manager contract /// @param _opWorldIDAddress Address of the Optimism contract that will receive the new root and timestamp /// @param _opCrossDomainMessenger L1CrossDomainMessenger contract used to communicate with the Optimism network /// @param _baseWorldIDAddress Address of the Base contract that will receive the new root and timestamp /// @param _baseCrossDomainMessenger L1CrossDomainMessenger contract used to communicate with the Base OP-Stack network constructor( address _checkpointManager, address _fxRoot, address _worldIDIdentityManager, address _opWorldIDAddress, address _opCrossDomainMessenger, address _baseWorldIDAddress, address _baseCrossDomainMessenger ) FxBaseRootTunnel(_checkpointManager, _fxRoot) { opWorldIDAddress = _opWorldIDAddress; worldIDAddress = _worldIDIdentityManager; baseWorldIDAddress = _baseWorldIDAddress; opCrossDomainMessengerAddress = _opCrossDomainMessenger; baseCrossDomainMessengerAddress = _baseCrossDomainMessenger; gasLimitSendRootOptimism = 100000; gasLimitSetRootHistoryExpiryOptimism = 100000; gasLimitTransferOwnershipOptimism = 100000; gasLimitSendRootBase = 100000; gasLimitSetRootHistoryExpiryBase = 100000; gasLimitTransferOwnershipBase = 100000; } /////////////////////////////////////////////////////////////////// /// PUBLIC API /// /////////////////////////////////////////////////////////////////// /// @notice Sends the latest WorldID Identity Manager root to all chains. /// @dev Calls this method on the L1 Proxy contract to relay roots and timestamps to WorldID supported chains. /// @param root The latest WorldID Identity Manager root. function sendRootMultichain(uint256 root) external onlyWorldIDIdentityManager { uint128 timestamp = uint128(block.timestamp); _sendRootToOptimism(root, timestamp); _sendRootToPolygon(root, timestamp); _sendRootToBase(root, timestamp); // add other chains here emit RootSentMultichain(root, timestamp); } /// @notice Sets the root history expiry for OpWorldID (on Optimism) and PolygonWorldID (on Polygon) /// @param expiryTime The new root history expiry for OpWorldID and PolygonWorldID function setRootHistoryExpiry(uint256 expiryTime) public onlyWorldIDIdentityManager { setRootHistoryExpiryOptimism(expiryTime); setRootHistoryExpiryPolygon(expiryTime); setRootHistoryExpiryBase(expiryTime); emit SetRootHistoryExpiry(expiryTime); } /////////////////////////////////////////////////////////////////// /// OPTIMISM /// /////////////////////////////////////////////////////////////////// /// @notice Sends the latest WorldID Identity Manager root to all chains. /// @dev Calls this method on the L1 Proxy contract to relay roots and timestamps to WorldID supported chains. /// @param root The latest WorldID Identity Manager root. /// @param timestamp The Ethereum block timestamp of the latest WorldID Identity Manager root. function _sendRootToOptimism(uint256 root, uint128 timestamp) internal { // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. bytes memory message = abi.encodeCall(IOpWorldID.receiveRoot, (root, timestamp)); ICrossDomainMessenger(opCrossDomainMessengerAddress).sendMessage( // Contract address on Optimism opWorldIDAddress, message, gasLimitSendRootOptimism ); } /// @notice Adds functionality to the StateBridge to transfer ownership /// of OpWorldID to another contract on L1 or to a local Optimism EOA /// @param _owner new owner (EOA or contract) /// @param _isLocal true if new owner is on Optimism, false if it is a cross-domain owner function transferOwnershipOptimism(address _owner, bool _isLocal) public onlyOwner { bytes memory message; // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. message = abi.encodeCall(ICrossDomainOwnable3.transferOwnership, (_owner, _isLocal)); ICrossDomainMessenger(opCrossDomainMessengerAddress).sendMessage( // Contract address on Optimism opWorldIDAddress, message, gasLimitTransferOwnershipOptimism ); emit OwnershipTransferredOptimism(owner(), _owner, _isLocal); } /// @notice Adds functionality to the StateBridge to set the root history expiry on OpWorldID /// @param _rootHistoryExpiry new root history expiry function setRootHistoryExpiryOptimism(uint256 _rootHistoryExpiry) internal { bytes memory message; // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. message = abi.encodeCall(IRootHistory.setRootHistoryExpiry, (_rootHistoryExpiry)); ICrossDomainMessenger(opCrossDomainMessengerAddress).sendMessage( // Contract address on Optimism opWorldIDAddress, message, gasLimitSetRootHistoryExpiryOptimism ); } /////////////////////////////////////////////////////////////////// /// OP GAS LIMIT /// /////////////////////////////////////////////////////////////////// /// @notice Sets the gas limit for the Optimism sendRootMultichain method /// @param _opGasLimit The new gas limit for the sendRootMultichain method function setGasLimitSendRootOptimism(uint32 _opGasLimit) external onlyOwner { gasLimitSendRootOptimism = _opGasLimit; emit SetGasLimitSendRootOptimism(_opGasLimit); } /// @notice Sets the gas limit for the Optimism setRootHistoryExpiry method /// @param _opGasLimit The new gas limit for the setRootHistoryExpiry method function setGasLimitSetRootHistoryExpiryOptimism(uint32 _opGasLimit) external onlyOwner { gasLimitSetRootHistoryExpiryOptimism = _opGasLimit; emit SetGasLimitSetRootHistoryExpiryOptimism(_opGasLimit); } /// @notice Sets the gas limit for the transferOwnershipOptimism method /// @param _opGasLimit The new gas limit for the transferOwnershipOptimism method function setGasLimitTransferOwnershipOptimism(uint32 _opGasLimit) external onlyOwner { gasLimitTransferOwnershipOptimism = _opGasLimit; emit SetGasLimitTransferOwnershipOptimism(_opGasLimit); } /////////////////////////////////////////////////////////////////// /// BASE /// /////////////////////////////////////////////////////////////////// /// @notice Sends the latest WorldID Identity Manager root to all chains. /// @dev Calls this method on the L1 Proxy contract to relay roots and timestamps to WorldID supported chains. /// @param root The latest WorldID Identity Manager root. /// @param timestamp The Ethereum block timestamp of the latest WorldID Identity Manager root. function _sendRootToBase(uint256 root, uint128 timestamp) internal { // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. bytes memory message = abi.encodeCall(IOpWorldID.receiveRoot, (root, timestamp)); ICrossDomainMessenger(baseCrossDomainMessengerAddress).sendMessage( // Contract address on Base baseWorldIDAddress, message, gasLimitSendRootBase ); } /// @notice Adds functionality to the StateBridge to transfer ownership /// of OpWorldID to another contract on L1 or to a local Base EOA /// @param _owner new owner (EOA or contract) /// @param _isLocal true if new owner is on Base, false if it is a cross-domain owner function transferOwnershipBase(address _owner, bool _isLocal) public onlyOwner { bytes memory message; // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. message = abi.encodeCall(ICrossDomainOwnable3.transferOwnership, (_owner, _isLocal)); ICrossDomainMessenger(baseCrossDomainMessengerAddress).sendMessage( // Contract address on Base baseWorldIDAddress, message, gasLimitTransferOwnershipBase ); emit OwnershipTransferredBase(owner(), _owner, _isLocal); } /// @notice Adds functionality to the StateBridge to set the root history expiry on OpWorldID /// @param _rootHistoryExpiry new root history expiry function setRootHistoryExpiryBase(uint256 _rootHistoryExpiry) internal { bytes memory message; // The `encodeCall` function is strongly typed, so this checks that we are passing the // correct data to the optimism bridge. message = abi.encodeCall(IRootHistory.setRootHistoryExpiry, (_rootHistoryExpiry)); ICrossDomainMessenger(baseCrossDomainMessengerAddress).sendMessage( // Contract address on Base baseWorldIDAddress, message, gasLimitSetRootHistoryExpiryBase ); } /////////////////////////////////////////////////////////////////// /// BASE GAS LIMIT /// /////////////////////////////////////////////////////////////////// /// @notice Sets the gas limit for the Base sendRootMultichain method /// @param _baseGasLimit The new gas limit for the sendRootMultichain method function setGasLimitSendRootBase(uint32 _baseGasLimit) external onlyOwner { gasLimitSendRootBase = _baseGasLimit; emit SetGasLimitSendRootBase(_baseGasLimit); } /// @notice Sets the gas limit for the Base setRootHistoryExpiry method /// @param _baseGasLimit The new gas limit for the setRootHistoryExpiry method function setGasLimitSetRootHistoryExpiryBase(uint32 _baseGasLimit) external onlyOwner { gasLimitSetRootHistoryExpiryBase = _baseGasLimit; emit SetGasLimitSetRootHistoryExpiryBase(_baseGasLimit); } /// @notice Sets the gas limit for the transferOwnershipBase method /// @param _baseGasLimit The new gas limit for the transferOwnershipBase method function setGasLimitTransferOwnershipBase(uint32 _baseGasLimit) external onlyOwner { gasLimitTransferOwnershipBase = _baseGasLimit; emit SetGasLimitTransferOwnershipBase(_baseGasLimit); } /////////////////////////////////////////////////////////////////// /// POLYGON /// /////////////////////////////////////////////////////////////////// /// @notice Sends root and timestamp to Polygon's StateChild contract (PolygonWorldID) /// @param root The latest WorldID Identity Manager root to be sent to Polygon /// @param timestamp The Ethereum block timestamp of the latest WorldID Identity Manager root function _sendRootToPolygon(uint256 root, uint128 timestamp) internal { bytes memory message; message = abi.encodeCall(IPolygonWorldID.receiveRoot, (root, timestamp)); /// @notice FxBaseRootTunnel method to send bytes payload to FxBaseChildTunnel contract _sendMessageToChild(message); } /// @notice Sets the root history expiry for PolygonWorldID /// @param _rootHistoryExpiry The new root history expiry function setRootHistoryExpiryPolygon(uint256 _rootHistoryExpiry) internal { bytes memory message; message = abi.encodeCall(IRootHistory.setRootHistoryExpiry, (_rootHistoryExpiry)); /// @notice FxBaseRootTunnel method to send bytes payload to FxBaseChildTunnel contract _sendMessageToChild(message); } /// @notice boilerplate function to satisfy FxBaseRootTunnel inheritance (not going to be used) function _processMessageFromChild(bytes memory) internal override { /// WorldID 🌎🆔 State Bridge } /////////////////////////////////////////////////////////////////////////////// /// ADDRESS MANAGEMENT /// /////////////////////////////////////////////////////////////////////////////// /// @notice Sets the `fxChildTunnel` address if not already set. /// @dev This implementation replicates the logic from `FxBaseRootTunnel` due to the inability /// to call `external` superclass methods when overriding them. /// /// @param _fxChildTunnel The address of the child (non-L1) tunnel contract. /// /// @custom:reverts string If the root tunnel has already been set. function setFxChildTunnel(address _fxChildTunnel) public virtual override onlyOwner { require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET"); fxChildTunnel = _fxChildTunnel; } /////////////////////////////////////////////////////////////////// /// OWNERSHIP /// /////////////////////////////////////////////////////////////////// /// @notice Ensures that ownership of WorldID implementations cannot be renounced. /// @dev This function is intentionally not `virtual` as we do not want it to be possible to /// renounce ownership for any WorldID implementation. /// @dev This function is marked as `onlyOwner` to maintain the access restriction from the base /// contract. function renounceOwnership() public view override onlyOwner { revert CannotRenounceOwnership(); } }
// SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.9.0; /** * @title ICrossDomainMessenger */ interface ICrossDomainMessenger { /********** * Events * **********/ event SentMessage( address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit ); event RelayedMessage(bytes32 indexed msgHash); event FailedRelayedMessage(bytes32 indexed msgHash); /************* * Variables * *************/ function xDomainMessageSender() external view returns (address); /******************** * Public Functions * ********************/ /** * Sends a cross domain message to the target messenger. * @param _target Target contract address. * @param _message Message to send to the target. * @param _gasLimit Gas limit for the provided message. */ function sendMessage( address _target, bytes calldata _message, uint32 _gasLimit ) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @title Interface for the OpWorldID contract /// @author Worldcoin /// @custom:usage abi.encodeCall(IOpWorldID.receiveRoot, (_newRoot, _supersedeTimestamp)); interface IOpWorldID { //////////////////////////////////////////////////////////////////////////////// /// ROOT MIRRORING /// /////////////////////////////////////////////////////////////////////////////// /// @notice This function is called by the state bridge contract when it forwards a new root to /// the bridged WorldID. /// @dev This function can revert if Optimism's CrossDomainMessenger stops processing proofs /// or if OPLabs stops submitting them. Next iteration of Optimism's cross-domain messaging, will be /// fully permissionless for message-passing, so this will not be an issue. /// Sequencer needs to include changes to the CrossDomainMessenger contract on L1, not economically penalized /// if messages are not included, however the fraud prover (Cannon) can force the sequencer to include it. /// /// @param newRoot The value of the new root. /// @param supersedeTimestamp The value of the L1 timestamp at the time that `newRoot` became /// the current root. This timestamp is associated with the latest root at the time of /// the call being inserted into the root history. /// /// @custom:reverts CannotOverwriteRoot If the root already exists in the root history. /// @custom:reverts string If the caller is not the owner. function receiveRoot(uint256 newRoot, uint128 supersedeTimestamp) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @title Interface for the PolygonWorldID contract /// @author Worldcoin /// @notice Interface for the CrossDomainOwnable contract for the Optimism L2 /// @custom:usage abi.encodeCall(IPolygonWorldID.receiveRoot, (_newRoot, _supersedeTimestamp)); interface IPolygonWorldID { //////////////////////////////////////////////////////////////////////////////// /// ROOT MIRRORING /// /////////////////////////////////////////////////////////////////////////////// /// @notice This function is called by the state bridge contract when it forwards a new root to /// the bridged WorldID. /// /// @param newRoot The value of the new root. /// @param supersedeTimestamp The value of the L1 timestamp at the time that `newRoot` became /// the current root. This timestamp is associated with the latest root at the time of /// the call being inserted into the root history. /// /// @custom:reverts CannotOverwriteRoot If the root already exists in the root history. /// @custom:reverts string If the caller is not the owner. function receiveRoot(uint256 newRoot, uint128 supersedeTimestamp) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @title Interface for WorldID setRooHistoryExpiry /// @author Worldcoin /// @notice Interface for WorldID setRooHistoryExpiry /// @dev Used in StateBridge to set the root history expiry time on Optimism (OPWorldID) /// @custom:usage abi.encodeCall(IRootHistory.setRootHistoryExpiry, (_expiryTime)); interface IRootHistory { /// @notice Sets the amount of time it takes for a root in the root history to expire. /// /// @param expiryTime The new amount of time it takes for a root to expire. /// /// @custom:reverts string If the caller is not the owner. function setRootHistoryExpiry(uint256 expiryTime) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() external { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
pragma solidity ^0.8.15; /// @title Optimism - CrossDomainOwnable3 Interface /// @author Worldcoin /// @notice Interface for the CrossDomainOwnable contract for the Optimism L2 /// @dev Adds functionality to the StateBridge to transfer ownership /// of OpWorldID to another contract on L1 or to a local Optimism EOA /// @custom:usage abi.encodeCall(ICrossDomainOwnable3.transferOwnership, (_owner, _isLocal)); interface ICrossDomainOwnable3 { /// @notice transfers owner to a cross-domain or local owner /// @param _owner new owner (EOA or contract) /// @param _isLocal true if new owner is on Optimism, false if it is a cross-domain owner function transferOwnership(address _owner, bool _isLocal) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {RLPReader} from "../lib/RLPReader.sol"; import {MerklePatriciaProof} from "../lib/MerklePatriciaProof.sol"; import {Merkle} from "../lib/Merkle.sol"; import "../lib/ExitPayloadReader.sol"; interface IFxStateSender { function sendMessageToChild(address _receiver, bytes calldata _data) external; } contract ICheckpointManager { struct HeaderBlock { bytes32 root; uint256 start; uint256 end; uint256 createdAt; address proposer; } /** * @notice mapping of checkpoint header numbers to block details * @dev These checkpoints are submited by plasma contracts */ mapping(uint256 => HeaderBlock) public headerBlocks; } abstract contract FxBaseRootTunnel { using RLPReader for RLPReader.RLPItem; using Merkle for bytes32; using ExitPayloadReader for bytes; using ExitPayloadReader for ExitPayloadReader.ExitPayload; using ExitPayloadReader for ExitPayloadReader.Log; using ExitPayloadReader for ExitPayloadReader.LogTopics; using ExitPayloadReader for ExitPayloadReader.Receipt; // keccak256(MessageSent(bytes)) bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036; // state sender contract IFxStateSender public fxRoot; // root chain manager ICheckpointManager public checkpointManager; // child tunnel contract which receives and sends messages address public fxChildTunnel; // storage to avoid duplicate exits mapping(bytes32 => bool) public processedExits; constructor(address _checkpointManager, address _fxRoot) { checkpointManager = ICheckpointManager(_checkpointManager); fxRoot = IFxStateSender(_fxRoot); } // set fxChildTunnel if not set already function setFxChildTunnel(address _fxChildTunnel) public virtual { require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET"); fxChildTunnel = _fxChildTunnel; } /** * @notice Send bytes message to Child Tunnel * @param message bytes message that will be sent to Child Tunnel * some message examples - * abi.encode(tokenId); * abi.encode(tokenId, tokenMetadata); * abi.encode(messageType, messageData); */ function _sendMessageToChild(bytes memory message) internal { fxRoot.sendMessageToChild(fxChildTunnel, message); } function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) { ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload(); bytes memory branchMaskBytes = payload.getBranchMaskAsBytes(); uint256 blockNumber = payload.getBlockNumber(); // checking if exit has already been processed // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex) bytes32 exitHash = keccak256( abi.encodePacked( blockNumber, // first 2 nibbles are dropped while generating nibble array // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only) // so converting to nibble array and then hashing it MerklePatriciaProof._getNibbleArray(branchMaskBytes), payload.getReceiptLogIndex() ) ); require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED"); processedExits[exitHash] = true; ExitPayloadReader.Receipt memory receipt = payload.getReceipt(); ExitPayloadReader.Log memory log = receipt.getLog(); // check child tunnel require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL"); bytes32 receiptRoot = payload.getReceiptRoot(); // verify receipt inclusion require( MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot), "FxRootTunnel: INVALID_RECEIPT_PROOF" ); // verify checkpoint inclusion _checkBlockMembershipInCheckpoint( blockNumber, payload.getBlockTime(), payload.getTxRoot(), receiptRoot, payload.getHeaderNumber(), payload.getBlockProof() ); ExitPayloadReader.LogTopics memory topics = log.getTopics(); require( bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig "FxRootTunnel: INVALID_SIGNATURE" ); // received message data bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message return message; } function _checkBlockMembershipInCheckpoint( uint256 blockNumber, uint256 blockTime, bytes32 txRoot, bytes32 receiptRoot, uint256 headerNumber, bytes memory blockProof ) private view returns (uint256) { (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber); require( keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership( blockNumber - startBlock, headerRoot, blockProof ), "FxRootTunnel: INVALID_HEADER" ); return createdAt; } /** * @notice receive message from L2 to L1, validated by proof * @dev This function verifies if the transaction actually happened on child chain * * @param inputData RLP encoded data of the reference tx containing following list of fields * 0 - headerNumber - Checkpoint header block number containing the reference tx * 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root * 2 - blockNumber - Block number containing the reference tx on child chain * 3 - blockTime - Reference tx block time * 4 - txRoot - Transactions root of block * 5 - receiptRoot - Receipts root of block * 6 - receipt - Receipt of the reference transaction * 7 - receiptProof - Merkle proof of the reference receipt * 8 - branchMask - 32 bits denoting the path of receipt in merkle tree * 9 - receiptLogIndex - Log Index to read from the receipt */ function receiveMessage(bytes memory inputData) public virtual { bytes memory message = _validateAndExtractMessage(inputData); _processMessageFromChild(message); } /** * @notice Process message received from Child Tunnel * @dev function needs to be implemented to handle message as per requirement * This is called by onStateReceive function. * Since it is called via a system call, any event will not be emitted during its execution. * @param message bytes message that was sent from Child Tunnel */ function _processMessageFromChild(bytes memory message) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
/* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ pragma solidity ^0.8.0; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint256 len; uint256 memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint256 nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint256 ptr = self.nextPtr; uint256 itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint256 memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param item RLP encoded bytes */ function rlpLen(RLPItem memory item) internal pure returns (uint256) { return item.len; } /* * @param item RLP encoded bytes */ function payloadLen(RLPItem memory item) internal pure returns (uint256) { return item.len - _payloadOffset(item.memPtr); } /* * @param item RLP encoded list in bytes */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint256 items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 dataLen; for (uint256 i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint256 memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { uint256 offset = _payloadOffset(item.memPtr); uint256 memPtr = item.memPtr + offset; uint256 len = item.len - offset; // data length return (memPtr, len); } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint256 memPtr, uint256 len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint256 ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint256 result; uint256 memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } return result == 0 ? false : true; } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(uint160(toUint(item))); } function toUint(RLPItem memory item) internal pure returns (uint256) { require(item.len > 0 && item.len <= 33); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; uint256 result; uint256 memPtr = item.memPtr + offset; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint256) { // one byte prefix require(item.len == 33); uint256 result; uint256 memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; // data length bytes memory result = new bytes(len); uint256 destPtr; assembly { destPtr := add(0x20, result) } copy(item.memPtr + offset, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint256) { if (item.len == 0) return 0; uint256 count = 0; uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint256 memPtr) private pure returns (uint256) { uint256 itemLen; uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint256 memPtr) private pure returns (uint256) { uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy( uint256 src, uint256 dest, uint256 len ) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len == 0) return; // left over bytes. Mask is used to remove unwanted bytes from the word uint256 mask = 256**(WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {RLPReader} from "./RLPReader.sol"; library MerklePatriciaProof { /* * @dev Verifies a merkle patricia proof. * @param value The terminating value in the trie. * @param encodedPath The path in the trie leading to value. * @param rlpParentNodes The rlp encoded stack of nodes. * @param root The root hash of the trie. * @return The boolean validity of the proof. */ function verify( bytes memory value, bytes memory encodedPath, bytes memory rlpParentNodes, bytes32 root ) internal pure returns (bool) { RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes); RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item); bytes memory currentNode; RLPReader.RLPItem[] memory currentNodeList; bytes32 nodeKey = root; uint256 pathPtr = 0; bytes memory path = _getNibbleArray(encodedPath); if (path.length == 0) { return false; } for (uint256 i = 0; i < parentNodes.length; i++) { if (pathPtr > path.length) { return false; } currentNode = RLPReader.toRlpBytes(parentNodes[i]); if (nodeKey != keccak256(currentNode)) { return false; } currentNodeList = RLPReader.toList(parentNodes[i]); if (currentNodeList.length == 17) { if (pathPtr == path.length) { if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) { return true; } else { return false; } } uint8 nextPathNibble = uint8(path[pathPtr]); if (nextPathNibble > 16) { return false; } nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble])); pathPtr += 1; } else if (currentNodeList.length == 2) { uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr); if (pathPtr + traversed == path.length) { //leaf node if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) { return true; } else { return false; } } //extension node if (traversed == 0) { return false; } pathPtr += traversed; nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1])); } else { return false; } } } function _nibblesToTraverse( bytes memory encodedPartialPath, bytes memory path, uint256 pathPtr ) private pure returns (uint256) { uint256 len = 0; // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath // and slicedPath have elements that are each one hex character (1 nibble) bytes memory partialPath = _getNibbleArray(encodedPartialPath); bytes memory slicedPath = new bytes(partialPath.length); // pathPtr counts nibbles in path // partialPath.length is a number of nibbles for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) { bytes1 pathNibble = path[i]; slicedPath[i - pathPtr] = pathNibble; } if (keccak256(partialPath) == keccak256(slicedPath)) { len = partialPath.length; } else { len = 0; } return len; } // bytes b must be hp encoded function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) { bytes memory nibbles = ""; if (b.length > 0) { uint8 offset; uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b)); if (hpNibble == 1 || hpNibble == 3) { nibbles = new bytes(b.length * 2 - 1); bytes1 oddNibble = _getNthNibbleOfBytes(1, b); nibbles[0] = oddNibble; offset = 1; } else { nibbles = new bytes(b.length * 2 - 2); offset = 0; } for (uint256 i = offset; i < nibbles.length; i++) { nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b); } } return nibbles; } function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) { return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Merkle { function checkMembership( bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof ) internal pure returns (bool) { require(proof.length % 32 == 0, "Invalid proof length"); uint256 proofHeight = proof.length / 32; // Proof of size n means, height of the tree is n+1. // In a tree of height n+1, max #leafs possible is 2 ^ n require(index < 2**proofHeight, "Leaf index is too big"); bytes32 proofElement; bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { assembly { proofElement := mload(add(proof, i)) } if (index % 2 == 0) { computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } index = index / 2; } return computedHash == rootHash; } }
pragma solidity ^0.8.0; import {RLPReader} from "./RLPReader.sol"; library ExitPayloadReader { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; uint8 constant WORD_SIZE = 32; struct ExitPayload { RLPReader.RLPItem[] data; } struct Receipt { RLPReader.RLPItem[] data; bytes raw; uint256 logIndex; } struct Log { RLPReader.RLPItem data; RLPReader.RLPItem[] list; } struct LogTopics { RLPReader.RLPItem[] data; } // copy paste of private copy() from RLPReader to avoid changing of existing contracts function copy( uint256 src, uint256 dest, uint256 len ) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len == 0) return; // left over bytes. Mask is used to remove unwanted bytes from the word uint256 mask = 256**(WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) { RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList(); return ExitPayload(payloadData); } function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[0].toUint(); } function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[1].toBytes(); } function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[2].toUint(); } function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[3].toUint(); } function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[4].toUint()); } function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[5].toUint()); } function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) { receipt.raw = payload.data[6].toBytes(); RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem(); if (receiptItem.isList()) { // legacy tx receipt.data = receiptItem.toList(); } else { // pop first byte before parsting receipt bytes memory typedBytes = receipt.raw; bytes memory result = new bytes(typedBytes.length - 1); uint256 srcPtr; uint256 destPtr; assembly { srcPtr := add(33, typedBytes) destPtr := add(0x20, result) } copy(srcPtr, destPtr, result.length); receipt.data = result.toRlpItem().toList(); } receipt.logIndex = getReceiptLogIndex(payload); return receipt; } function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[7].toBytes(); } function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[8].toBytes(); } function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[8].toUint(); } function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[9].toUint(); } // Receipt methods function toBytes(Receipt memory receipt) internal pure returns (bytes memory) { return receipt.raw; } function getLog(Receipt memory receipt) internal pure returns (Log memory) { RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex]; return Log(logData, logData.toList()); } // Log methods function getEmitter(Log memory log) internal pure returns (address) { return RLPReader.toAddress(log.list[0]); } function getTopics(Log memory log) internal pure returns (LogTopics memory) { return LogTopics(log.list[1].toList()); } function getData(Log memory log) internal pure returns (bytes memory) { return log.list[2].toBytes(); } function toRlpBytes(Log memory log) internal pure returns (bytes memory) { return log.data.toRlpBytes(); } // LogTopics methods function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) { return topics.data[index]; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "@eth-optimism/contracts-bedrock/=node_modules/@eth-optimism/contracts-bedrock/", "@eth-optimism/contracts/=node_modules/@eth-optimism/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@prb/test/=lib/prb-test/src/", "@rari-capital/solmate/=lib/solmate/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "fx-portal/contracts/=lib/contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "prb-test/=lib/prb-test/src/", "semaphore-v3/=lib/semaphore-v3/", "semaphore/=lib/semaphore-v3/packages/contracts/contracts/", "solmate/=lib/solmate/", "src/=src/" ], "optimizer": { "enabled": true, "runs": 10000, "details": { "peephole": true, "inliner": true, "deduplicate": true, "cse": true, "yul": true } }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_checkpointManager","type":"address"},{"internalType":"address","name":"_fxRoot","type":"address"},{"internalType":"address","name":"_worldIDIdentityManager","type":"address"},{"internalType":"address","name":"_opWorldIDAddress","type":"address"},{"internalType":"address","name":"_opCrossDomainMessenger","type":"address"},{"internalType":"address","name":"_baseWorldIDAddress","type":"address"},{"internalType":"address","name":"_baseCrossDomainMessenger","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotRenounceOwnership","type":"error"},{"inputs":[],"name":"NotWorldIDIdentityManager","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"bool","name":"isLocal","type":"bool"}],"name":"OwnershipTransferredBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"bool","name":"isLocal","type":"bool"}],"name":"OwnershipTransferredOptimism","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"root","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"timestamp","type":"uint128"}],"name":"RootSentMultichain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"SetGasLimitSendRootBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"SetGasLimitSendRootOptimism","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"SetGasLimitSetRootHistoryExpiryBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"SetGasLimitSetRootHistoryExpiryOptimism","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"SetGasLimitTransferOwnershipBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"SetGasLimitTransferOwnershipOptimism","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rootHistoryExpiry","type":"uint256"}],"name":"SetRootHistoryExpiry","type":"event"},{"inputs":[],"name":"SEND_MESSAGE_EVENT_SIG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"baseWorldIDAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpointManager","outputs":[{"internalType":"contract ICheckpointManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxChildTunnel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxRoot","outputs":[{"internalType":"contract IFxStateSender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"opWorldIDAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedExits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"inputData","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"root","type":"uint256"}],"name":"sendRootMultichain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fxChildTunnel","type":"address"}],"name":"setFxChildTunnel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"setGasLimitSendRootBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"setGasLimitSendRootOptimism","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"setGasLimitSetRootHistoryExpiryBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"setGasLimitSetRootHistoryExpiryOptimism","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_baseGasLimit","type":"uint32"}],"name":"setGasLimitTransferOwnershipBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_opGasLimit","type":"uint32"}],"name":"setGasLimitTransferOwnershipOptimism","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"expiryTime","type":"uint256"}],"name":"setRootHistoryExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_isLocal","type":"bool"}],"name":"transferOwnershipBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_isLocal","type":"bool"}],"name":"transferOwnershipOptimism","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"worldIDAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b506040516200377f3803806200377f833981016040819052620000359162000172565b600180546001600160a01b03808a166001600160a01b031992831617909255600080549289169290911691909117905562000077620000713390565b620000d9565b6001600160a01b0393841660805293831661010052821660c052811660a05290811660e05260058054909116690c3500000c3500000c3560a51b1790555050600680546001600160601b0319166a0186a0000186a0000186a017905562000207565b600580546001600160a01b0319169055620001008162000103602090811b62000f8717901c565b50565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b03811681146200016d57600080fd5b919050565b600080600080600080600060e0888a0312156200018e57600080fd5b620001998862000155565b9650620001a96020890162000155565b9550620001b96040890162000155565b9450620001c96060890162000155565b9350620001d96080890162000155565b9250620001e960a0890162000155565b9150620001f960c0890162000155565b905092959891949750929550565b60805160a05160c05160e051610100516134df620002a060003960008181610362015281816108d90152610cac01526000818161058201528181611345015261164c0152600081816101fc015281816105c401528181611372015261168e01526000818161077c015281816111300152611472015260008181610328015281816107be0152818161117201526114b401526134df6000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c8063972c4928116100ee578063ca35893111610097578063e03595f511610071578063e03595f5146103fd578063e30c397814610410578063f2fde38b1461042e578063f953cec71461044157600080fd5b8063ca358931146103b7578063d76ff34e146103ca578063de9b771f146103dd57600080fd5b8063b665a5b2116100c8578063b665a5b21461035d578063c0857ba014610384578063c70aa727146103a457600080fd5b8063972c492814610303578063ab6dab0d14610323578063aea4e49e1461034a57600080fd5b80634434766911610150578063715018a61161012a578063715018a6146102d557806379ba5097146102dd5780638da5cb5b146102e557600080fd5b8063443476691461027c578063607f2d421461028f578063712f8e73146102c257600080fd5b8063226bed8411610181578063226bed841461024357806332f0476714610256578063393170cf1461026957600080fd5b80630e387de6146101a85780631ade5313146101e257806321fc4a9d146101f7575b600080fd5b6101cf7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b6040519081526020015b60405180910390f35b6101f56101f0366004612e61565b610454565b005b61021e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d9565b6101f5610251366004612ea9565b6104c6565b6101f5610264366004612ea9565b6106c0565b6101f5610277366004612ee7565b6108c1565b6101f561028a366004612e61565b61099d565b6102b261029d366004612ee7565b60036020526000908152604090205460ff1681565b60405190151581526020016101d9565b6101f56102d0366004612e61565b610a26565b6101f5610aab565b6101f5610ae5565b60045473ffffffffffffffffffffffffffffffffffffffff1661021e565b60025461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b61021e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f5610358366004612f00565b610b9f565b61021e7f000000000000000000000000000000000000000000000000000000000000000081565b60015461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101f56103b2366004612ee7565b610c94565b6101f56103c5366004612e61565b610d4e565b6101f56103d8366004612e61565b610dd7565b60005461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101f561040b366004612e61565b610e50565b60055473ffffffffffffffffffffffffffffffffffffffff1661021e565b6101f561043c366004612f00565b610ec5565b6101f561044f366004612fa5565b610f75565b61045c610ffe565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff83169081179091556040519081527f6bef4f65b1092c540f74571b311af278a7bb6516268b41c947877d41a5490c47906020015b60405180910390a150565b6104ce610ffe565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152811515604482015260609060640160408051808303601f190181529181526020820180517fb242e534000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260065490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91610602917f00000000000000000000000000000000000000000000000000000000000000009186916801000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561061c57600080fd5b505af1158015610630573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff1661066a60045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167fbfcba8ae3206138777314b6c3f0d7d517ce8445a337df4eec8351111b968310c846040516106b3911515815260200190565b60405180910390a3505050565b6106c8610ffe565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152811515604482015260609060640160408051808303601f190181529181526020820180517fb242e534000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91610810917f00000000000000000000000000000000000000000000000000000000000000009186917c010000000000000000000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561082a57600080fd5b505af115801561083e573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff1661087860045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f8cc01bd124a3295d8d6fd630daf4804b0a85e7adf11d6242431fcefda0abd49f846040516106b3911515815260200190565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610930576040517feddebff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4261093b8282611081565b61094582826111f3565b61094f8282611283565b604080518381526fffffffffffffffffffffffffffffffff831660208201527fd4d83dbbd1b2b799521a08125aea58acd899c963b2e9b8ee0ca78b7e07c279a7910160405180910390a15050565b6109a5610ffe565b600580547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527fa6ad48bdee6467cd0e03ecc94ae21c2088f21ab2904bc9b218aa854c45d33445906020016104bb565b610a2e610ffe565b600580547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527f1f1bbd6eea04da4e228b4747a379a1acccfcf070d8ed9cf0e18afca54e7ce22d906020016104bb565b610ab3610ffe565b6040517f77aeb0ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554339073ffffffffffffffffffffffffffffffffffffffff168114610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610b9c816113a5565b50565b610ba7610ffe565b60025473ffffffffffffffffffffffffffffffffffffffff1615610c4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160448201527f4c52454144595f534554000000000000000000000000000000000000000000006064820152608401610b8a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d03576040517feddebff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0c816113d6565b610d1581611538565b610d1e816115b0565b6040518181527f9036872f40830f3909d8006c77be543a639ad4ebb34aff720498fcd12656a292906020016104bb565b610d56610ffe565b600580547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527fd6028463a2f56f40152fd9be7849e85ccea5ad358245727834ed73031ef9fea1906020016104bb565b610ddf610ffe565b600680547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff166801000000000000000063ffffffff8416908102919091179091556040519081527f284560d1ca7443d429f15e31f07cd827e372c4691b9751ee9e8528901c63f316906020016104bb565b610e58610ffe565b600680547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff1664010000000063ffffffff8416908102919091179091556040519081527fbc8b5074d5e8792b09de97f17fb3384a4c71d9c2fffedc6599c352ebdca50c19906020016104bb565b610ecd610ffe565b6005805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610f3060045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610f80826116c8565b90505b5050565b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60045473ffffffffffffffffffffffffffffffffffffffff16331461107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b8a565b565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260009060640160408051808303601f190181529181526020820180517fb52a6a7e000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691633dbb202b916111bc917f00000000000000000000000000000000000000000000000000000000000000009186917401000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b1580156111d657600080fd5b505af11580156111ea573d6000803e3d6000fd5b50505050505050565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260609060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb52a6a7e00000000000000000000000000000000000000000000000000000000179052905061127e81611a8c565b505050565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260009060640160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb52a6a7e0000000000000000000000000000000000000000000000000000000017905260065490517f3dbb202b00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691633dbb202b916111bc917f000000000000000000000000000000000000000000000000000000000000000091869163ffffffff90911690600401613081565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610b9c81610f87565b6060816040516024016113eb91815260200190565b60408051808303601f190181529181526020820180517fc70aa727000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91611502917f0000000000000000000000000000000000000000000000000000000000000000918691780100000000000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561151c57600080fd5b505af1158015611530573d6000803e3d6000fd5b505050505050565b60608160405160240161154d91815260200190565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc70aa727000000000000000000000000000000000000000000000000000000001790529050610f8381611a8c565b6060816040516024016115c591815260200190565b60408051808303601f190181529181526020820180517fc70aa727000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260065490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91611502917f000000000000000000000000000000000000000000000000000000000000000091869164010000000090910463ffffffff1690600401613081565b606060006116d583611b1d565b905060006116e282611b7c565b905060006116ef83611bab565b90506000816116fd84611bd4565b61170686611dc2565b604051602001611718939291906130c6565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff16156117cf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560448201527f53534544000000000000000000000000000000000000000000000000000000006064820152608401610b8a565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561180f85611dde565b9050600061181c82611f28565b905061182781611fb8565b60025473ffffffffffffffffffffffffffffffffffffffff9081169116146118d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460448201527f554e4e454c0000000000000000000000000000000000000000000000000000006064820152608401610b8a565b60006118dc87611fe1565b90506118fc6118ec846020015190565b876118f68a611ffd565b84612019565b611988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260448201527f4f4f4600000000000000000000000000000000000000000000000000000000006064820152608401610b8a565b6119b685611995896122cc565b61199e8a6122e8565b846119a88c612304565b6119b18d612320565b61233c565b5060006119c2836124a2565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0366119f86119f38360006124de565b612516565b14611a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e4154555245006044820152606401610b8a565b6000611a6a84612591565b806020019051810190611a7d91906130f3565b9b9a5050505050505050505050565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b472047792611ae892911690859060040161316a565b600060405180830381600087803b158015611b0257600080fd5b505af1158015611b16573d6000803e3d6000fd5b5050505050565b6040805160208101909152606081526000611b67611b628460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b6125ad565b60408051602081019091529081529392505050565b6060611ba58260000151600881518110611b9857611b98613199565b60200260200101516126c3565b92915050565b6000611ba58260000151600281518110611bc757611bc7613199565b6020026020010151612516565b60408051602081019091526000815281516060919015611ba557600080611bfc600086612760565b60f81c90506001811480611c1357508060ff166003145b15611cd357600185516002611c2891906131f7565b611c329190613234565b67ffffffffffffffff811115611c4a57611c4a612f1d565b6040519080825280601f01601f191660200182016040528015611c74576020820181803683370190505b5092506000611c84600187612760565b90508084600081518110611c9a57611c9a613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001925050611d37565b600285516002611ce391906131f7565b611ced9190613234565b67ffffffffffffffff811115611d0557611d05612f1d565b6040519080825280601f01601f191660200182016040528015611d2f576020820181803683370190505b509250600091505b60ff82165b8351811015611db957611d66611d5560ff851683613234565b611d6090600261324b565b87612760565b848281518110611d7857611d78613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080611db181613263565b915050611d3c565b50505092915050565b6000611ba58260000151600981518110611bc757611bc7613199565b611e0260405180606001604052806060815260200160608152602001600081525090565b611e1c8260000151600681518110611b9857611b98613199565b602082810182905260408051808201825260008082529083015280518082019091528251815291810190820152611e52816127e1565b15611e6757611e60816125ad565b8252611f14565b60208201518051600090611e7d90600190613234565b67ffffffffffffffff811115611e9557611e95612f1d565b6040519080825280601f01601f191660200182016040528015611ebf576020820181803683370190505b509050600080836021019150826020019050611edd8282855161281c565b604080518082018252600080825260209182015281518083019092528451825280850190820152611f0d906125ad565b8652505050505b611f1d83611dc2565b604083015250919050565b604080516080810182526000918101828152606080830193909352815260208101919091526000611f768360000151600381518110611f6957611f69613199565b60200260200101516125ad565b836040015181518110611f8b57611f8b613199565b602002602001015190506040518060400160405280828152602001611faf836125ad565b90529392505050565b6000611ba58260200151600081518110611fd457611fd4613199565b60200260200101516128a7565b6000611ba58260000151600581518110611bc757611bc7613199565b6060611ba58260000151600781518110611b9857611b98613199565b60008061204d8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b9050600061205a826125ad565b90506060808560008061206c8b611bd4565b905080516000036120875760009750505050505050506122c4565b60005b86518110156122bb5781518311156120ad576000985050505050505050506122c4565b6120cf8782815181106120c2576120c2613199565b60200260200101516128c1565b9550858051906020012084146120f0576000985050505050505050506122c4565b612105878281518110611f6957611f69613199565b945084516011036121d75781518303612164578c8051906020012061213686601081518110611b9857611b98613199565b8051906020012003612153576001985050505050505050506122c4565b6000985050505050505050506122c4565b600082848151811061217857612178613199565b016020015160f81c9050601081111561219d57600099505050505050505050506122c4565b6121c2868260ff16815181106121b5576121b5613199565b6020026020010151612940565b94506121cf60018561324b565b9350506122a9565b84516002036121535760006122026121fb87600081518110611b9857611b98613199565b848661296e565b8351909150612211828661324b565b03612264578d8051906020012061223487600181518110611b9857611b98613199565b805190602001200361225257600199505050505050505050506122c4565b600099505050505050505050506122c4565b8060000361227e57600099505050505050505050506122c4565b612288818561324b565b93506122a0866001815181106121b5576121b5613199565b94506122a99050565b806122b381613263565b91505061208a565b50505050505050505b949350505050565b6000611ba58260000151600381518110611bc757611bc7613199565b6000611ba58260000151600481518110611bc757611bc7613199565b6000611ba58260000151600081518110611bc757611bc7613199565b6060611ba58260000151600181518110611b9857611b98613199565b6001546040517f41539d4a0000000000000000000000000000000000000000000000000000000081526004810184905260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a9060240160a060405180830381865afa1580156123b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d8919061329b565b509350509250925061242f828b6123ef9190613234565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a09092019092528051910120908588612aa6565b612495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f484541444552000000006044820152606401610b8a565b9998505050505050505050565b60408051602081019091526060815260405180602001604052806124d68460200151600181518110611f6957611f69613199565b905292915050565b6040805180820190915260008082526020820152825180518390811061250657612506613199565b6020026020010151905092915050565b80516000901580159061252b57508151602110155b61253457600080fd5b60006125438360200151612c53565b905060008184600001516125579190613234565b905060008083866020015161256c919061324b565b905080519150602083101561258857826020036101000a820491505b50949350505050565b6060611ba58260200151600281518110611b9857611b98613199565b60606125b8826127e1565b6125c157600080fd5b60006125cc83612cd5565b905060008167ffffffffffffffff8111156125e9576125e9612f1d565b60405190808252806020026020018201604052801561262e57816020015b60408051808201909152600080825260208201528152602001906001900390816126075790505b50905060006126408560200151612c53565b856020015161264f919061324b565b90506000805b848110156126b85761266683612d5a565b915060405180604001604052808381526020018481525084828151811061268f5761268f613199565b60209081029190910101526126a4828461324b565b9250806126b081613263565b915050612655565b509195945050505050565b80516060906126d157600080fd5b60006126e08360200151612c53565b905060008184600001516126f49190613234565b905060008167ffffffffffffffff81111561271157612711612f1d565b6040519080825280601f01601f19166020018201604052801561273b576020820181803683370190505b5090506000816020019050612588848760200151612759919061324b565b8285612e1c565b600061276d600284613317565b156127a75760108261278060028661332b565b8151811061279057612790613199565b01602001516127a2919060f81c61333f565b6127d7565b6010826127b560028661332b565b815181106127c5576127c5613199565b01602001516127d7919060f81c613361565b60f81b9392505050565b805160009081036127f457506000919050565b6020820151805160001a9060c0821015612812575060009392505050565b5060019392505050565b8060000361282957505050565b60208110612861578251825261284060208461324b565b925061284d60208361324b565b915061285a602082613234565b9050612829565b8060000361286e57505050565b6000600161287d836020613234565b612889906101006134a3565b6128939190613234565b935183518516941916939093179091525050565b80516000906015146128b857600080fd5b611ba582612516565b60606000826000015167ffffffffffffffff8111156128e2576128e2612f1d565b6040519080825280601f01601f19166020018201604052801561290c576020820181803683370190505b509050805160000361291e5792915050565b60008160200190506129398460200151828660000151612e1c565b5092915050565b805160009060211461295157600080fd5b60008083602001516001612965919061324b565b51949350505050565b6000808061297b86611bd4565b90506000815167ffffffffffffffff81111561299957612999612f1d565b6040519080825280601f01601f1916602001820160405280156129c3576020820181803683370190505b509050845b82516129d4908761324b565b811015612a775760008782815181106129ef576129ef613199565b01602001517fff000000000000000000000000000000000000000000000000000000000000001690508083612a248985613234565b81518110612a3457612a34613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080612a6f90613263565b9150506129c8565b508080519060200120828051906020012003612a965781519250612a9b565b600092505b509095945050505050565b600060208251612ab69190613317565b15612b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c69642070726f6f66206c656e6774680000000000000000000000006044820152606401610b8a565b600060208351612b2d919061332b565b9050612b3a8160026134a3565b8510612ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4c65616620696e64657820697320746f6f2062696700000000000000000000006044820152606401610b8a565b60008660205b85518111612c4557858101519250612bc1600289613317565b600003612bf9576040805160208101849052908101849052606001604051602081830303815290604052805190602001209150612c26565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012091505b612c3160028961332b565b9750612c3e60208261324b565b9050612ba8565b509094149695505050505050565b8051600090811a6080811015612c6c5750600092915050565b60b8811080612c87575060c08110801590612c87575060f881105b15612c955750600192915050565b60c0811015612cc957612caa600160b86134af565b612cb79060ff1682613234565b612cc290600161324b565b9392505050565b612caa600160f86134af565b80516000908103612ce857506000919050565b600080612cf88460200151612c53565b8460200151612d07919061324b565b9050600084600001518560200151612d1f919061324b565b90505b80821015612d5157612d3382612d5a565b612d3d908361324b565b915082612d4981613263565b935050612d22565b50909392505050565b80516000908190811a6080811015612d755760019150612939565b60b8811015612d9b57612d89608082613234565b612d9490600161324b565b9150612939565b60c0811015612dc85760b78103600185019450806020036101000a85510460018201810193505050612939565b60f8811015612ddc57612d8960c082613234565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b80600003612e2957505050565b602081106128615782518252612e4060208461324b565b9250612e4d60208361324b565b9150612e5a602082613234565b9050612e29565b600060208284031215612e7357600080fd5b813563ffffffff81168114612cc257600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610b9c57600080fd5b60008060408385031215612ebc57600080fd5b8235612ec781612e87565b915060208301358015158114612edc57600080fd5b809150509250929050565b600060208284031215612ef957600080fd5b5035919050565b600060208284031215612f1257600080fd5b8135612cc281612e87565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f7557612f75612f1d565b604052919050565b600067ffffffffffffffff821115612f9757612f97612f1d565b50601f01601f191660200190565b600060208284031215612fb757600080fd5b813567ffffffffffffffff811115612fce57600080fd5b8201601f81018413612fdf57600080fd5b8035612ff2612fed82612f7d565b612f4c565b81815285602083850101111561300757600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b83811015613040578181015183820152602001613028565b8381111561304f576000848401525b50505050565b6000815180845261306d816020860160208601613025565b601f01601f19169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006130b06060830185613055565b905063ffffffff83166040830152949350505050565b838152600083516130de816020850160208801613025565b60209201918201929092526040019392505050565b60006020828403121561310557600080fd5b815167ffffffffffffffff81111561311c57600080fd5b8201601f8101841361312d57600080fd5b805161313b612fed82612f7d565b81815285602083850101111561315057600080fd5b613161826020830160208601613025565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006122c46040830184613055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561322f5761322f6131c8565b500290565b600082821015613246576132466131c8565b500390565b6000821982111561325e5761325e6131c8565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613294576132946131c8565b5060010190565b600080600080600060a086880312156132b357600080fd5b8551945060208601519350604086015192506060860151915060808601516132da81612e87565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613326576133266132e8565b500690565b60008261333a5761333a6132e8565b500490565b600060ff831680613352576133526132e8565b8060ff84160691505092915050565b600060ff831680613374576133746132e8565b8060ff84160491505092915050565b600181815b808511156133dc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156133c2576133c26131c8565b808516156133cf57918102915b93841c9390800290613388565b509250929050565b6000826133f357506001611ba5565b8161340057506000611ba5565b816001811461341657600281146134205761343c565b6001915050611ba5565b60ff841115613431576134316131c8565b50506001821b611ba5565b5060208310610133831016604e8410600b841016171561345f575081810a611ba5565b6134698383613383565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561349b5761349b6131c8565b029392505050565b6000612cc283836133e4565b600060ff821660ff8416808210156134c9576134c96131c8565b9003939250505056fea164736f6c634300080f000a0000000000000000000000002890ba17efe978480615e330ecb65333b880928e0000000000000000000000003d1d3e34f7fb6d26245e6640e1c50710efff15ba000000000000000000000000711965c7805635315201d0963148df4445505182000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23640000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be294000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23640000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101a35760003560e01c8063972c4928116100ee578063ca35893111610097578063e03595f511610071578063e03595f5146103fd578063e30c397814610410578063f2fde38b1461042e578063f953cec71461044157600080fd5b8063ca358931146103b7578063d76ff34e146103ca578063de9b771f146103dd57600080fd5b8063b665a5b2116100c8578063b665a5b21461035d578063c0857ba014610384578063c70aa727146103a457600080fd5b8063972c492814610303578063ab6dab0d14610323578063aea4e49e1461034a57600080fd5b80634434766911610150578063715018a61161012a578063715018a6146102d557806379ba5097146102dd5780638da5cb5b146102e557600080fd5b8063443476691461027c578063607f2d421461028f578063712f8e73146102c257600080fd5b8063226bed8411610181578063226bed841461024357806332f0476714610256578063393170cf1461026957600080fd5b80630e387de6146101a85780631ade5313146101e257806321fc4a9d146101f7575b600080fd5b6101cf7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b6040519081526020015b60405180910390f35b6101f56101f0366004612e61565b610454565b005b61021e7f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d236481565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d9565b6101f5610251366004612ea9565b6104c6565b6101f5610264366004612ea9565b6106c0565b6101f5610277366004612ee7565b6108c1565b6101f561028a366004612e61565b61099d565b6102b261029d366004612ee7565b60036020526000908152604090205460ff1681565b60405190151581526020016101d9565b6101f56102d0366004612e61565b610a26565b6101f5610aab565b6101f5610ae5565b60045473ffffffffffffffffffffffffffffffffffffffff1661021e565b60025461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b61021e7f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d236481565b6101f5610358366004612f00565b610b9f565b61021e7f000000000000000000000000711965c7805635315201d0963148df444550518281565b60015461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101f56103b2366004612ee7565b610c94565b6101f56103c5366004612e61565b610d4e565b6101f56103d8366004612e61565b610dd7565b60005461021e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101f561040b366004612e61565b610e50565b60055473ffffffffffffffffffffffffffffffffffffffff1661021e565b6101f561043c366004612f00565b610ec5565b6101f561044f366004612fa5565b610f75565b61045c610ffe565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff83169081179091556040519081527f6bef4f65b1092c540f74571b311af278a7bb6516268b41c947877d41a5490c47906020015b60405180910390a150565b6104ce610ffe565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152811515604482015260609060640160408051808303601f190181529181526020820180517fb242e534000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260065490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f0000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d73ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91610602917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23649186916801000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561061c57600080fd5b505af1158015610630573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff1661066a60045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167fbfcba8ae3206138777314b6c3f0d7d517ce8445a337df4eec8351111b968310c846040516106b3911515815260200190565b60405180910390a3505050565b6106c8610ffe565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152811515604482015260609060640160408051808303601f190181529181526020820180517fb242e534000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f0000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be29473ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91610810917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23649186917c010000000000000000000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561082a57600080fd5b505af115801561083e573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff1661087860045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f8cc01bd124a3295d8d6fd630daf4804b0a85e7adf11d6242431fcefda0abd49f846040516106b3911515815260200190565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000711965c7805635315201d0963148df44455051821614610930576040517feddebff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4261093b8282611081565b61094582826111f3565b61094f8282611283565b604080518381526fffffffffffffffffffffffffffffffff831660208201527fd4d83dbbd1b2b799521a08125aea58acd899c963b2e9b8ee0ca78b7e07c279a7910160405180910390a15050565b6109a5610ffe565b600580547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527fa6ad48bdee6467cd0e03ecc94ae21c2088f21ab2904bc9b218aa854c45d33445906020016104bb565b610a2e610ffe565b600580547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527f1f1bbd6eea04da4e228b4747a379a1acccfcf070d8ed9cf0e18afca54e7ce22d906020016104bb565b610ab3610ffe565b6040517f77aeb0ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554339073ffffffffffffffffffffffffffffffffffffffff168114610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610b9c816113a5565b50565b610ba7610ffe565b60025473ffffffffffffffffffffffffffffffffffffffff1615610c4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160448201527f4c52454144595f534554000000000000000000000000000000000000000000006064820152608401610b8a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000711965c7805635315201d0963148df44455051821614610d03576040517feddebff700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0c816113d6565b610d1581611538565b610d1e816115b0565b6040518181527f9036872f40830f3909d8006c77be543a639ad4ebb34aff720498fcd12656a292906020016104bb565b610d56610ffe565b600580547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff8416908102919091179091556040519081527fd6028463a2f56f40152fd9be7849e85ccea5ad358245727834ed73031ef9fea1906020016104bb565b610ddf610ffe565b600680547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff166801000000000000000063ffffffff8416908102919091179091556040519081527f284560d1ca7443d429f15e31f07cd827e372c4691b9751ee9e8528901c63f316906020016104bb565b610e58610ffe565b600680547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff1664010000000063ffffffff8416908102919091179091556040519081527fbc8b5074d5e8792b09de97f17fb3384a4c71d9c2fffedc6599c352ebdca50c19906020016104bb565b610ecd610ffe565b6005805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610f3060045473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610f80826116c8565b90505b5050565b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60045473ffffffffffffffffffffffffffffffffffffffff16331461107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b8a565b565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260009060640160408051808303601f190181529181526020820180517fb52a6a7e000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f0000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be29473ffffffffffffffffffffffffffffffffffffffff1691633dbb202b916111bc917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23649186917401000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b1580156111d657600080fd5b505af11580156111ea573d6000803e3d6000fd5b50505050505050565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260609060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb52a6a7e00000000000000000000000000000000000000000000000000000000179052905061127e81611a8c565b505050565b604051602481018390526fffffffffffffffffffffffffffffffff8216604482015260009060640160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb52a6a7e0000000000000000000000000000000000000000000000000000000017905260065490517f3dbb202b00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d1691633dbb202b916111bc917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d236491869163ffffffff90911690600401613081565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610b9c81610f87565b6060816040516024016113eb91815260200190565b60408051808303601f190181529181526020820180517fc70aa727000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260055490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f0000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be29473ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91611502917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d2364918691780100000000000000000000000000000000000000000000000090910463ffffffff1690600401613081565b600060405180830381600087803b15801561151c57600080fd5b505af1158015611530573d6000803e3d6000fd5b505050505050565b60608160405160240161154d91815260200190565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc70aa727000000000000000000000000000000000000000000000000000000001790529050610f8381611a8c565b6060816040516024016115c591815260200190565b60408051808303601f190181529181526020820180517fc70aa727000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617905260065490517f3dbb202b0000000000000000000000000000000000000000000000000000000081529192507f0000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d73ffffffffffffffffffffffffffffffffffffffff1691633dbb202b91611502917f000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d236491869164010000000090910463ffffffff1690600401613081565b606060006116d583611b1d565b905060006116e282611b7c565b905060006116ef83611bab565b90506000816116fd84611bd4565b61170686611dc2565b604051602001611718939291906130c6565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff16156117cf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560448201527f53534544000000000000000000000000000000000000000000000000000000006064820152608401610b8a565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561180f85611dde565b9050600061181c82611f28565b905061182781611fb8565b60025473ffffffffffffffffffffffffffffffffffffffff9081169116146118d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460448201527f554e4e454c0000000000000000000000000000000000000000000000000000006064820152608401610b8a565b60006118dc87611fe1565b90506118fc6118ec846020015190565b876118f68a611ffd565b84612019565b611988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260448201527f4f4f4600000000000000000000000000000000000000000000000000000000006064820152608401610b8a565b6119b685611995896122cc565b61199e8a6122e8565b846119a88c612304565b6119b18d612320565b61233c565b5060006119c2836124a2565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0366119f86119f38360006124de565b612516565b14611a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e4154555245006044820152606401610b8a565b6000611a6a84612591565b806020019051810190611a7d91906130f3565b9b9a5050505050505050505050565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b472047792611ae892911690859060040161316a565b600060405180830381600087803b158015611b0257600080fd5b505af1158015611b16573d6000803e3d6000fd5b5050505050565b6040805160208101909152606081526000611b67611b628460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b6125ad565b60408051602081019091529081529392505050565b6060611ba58260000151600881518110611b9857611b98613199565b60200260200101516126c3565b92915050565b6000611ba58260000151600281518110611bc757611bc7613199565b6020026020010151612516565b60408051602081019091526000815281516060919015611ba557600080611bfc600086612760565b60f81c90506001811480611c1357508060ff166003145b15611cd357600185516002611c2891906131f7565b611c329190613234565b67ffffffffffffffff811115611c4a57611c4a612f1d565b6040519080825280601f01601f191660200182016040528015611c74576020820181803683370190505b5092506000611c84600187612760565b90508084600081518110611c9a57611c9a613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001925050611d37565b600285516002611ce391906131f7565b611ced9190613234565b67ffffffffffffffff811115611d0557611d05612f1d565b6040519080825280601f01601f191660200182016040528015611d2f576020820181803683370190505b509250600091505b60ff82165b8351811015611db957611d66611d5560ff851683613234565b611d6090600261324b565b87612760565b848281518110611d7857611d78613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080611db181613263565b915050611d3c565b50505092915050565b6000611ba58260000151600981518110611bc757611bc7613199565b611e0260405180606001604052806060815260200160608152602001600081525090565b611e1c8260000151600681518110611b9857611b98613199565b602082810182905260408051808201825260008082529083015280518082019091528251815291810190820152611e52816127e1565b15611e6757611e60816125ad565b8252611f14565b60208201518051600090611e7d90600190613234565b67ffffffffffffffff811115611e9557611e95612f1d565b6040519080825280601f01601f191660200182016040528015611ebf576020820181803683370190505b509050600080836021019150826020019050611edd8282855161281c565b604080518082018252600080825260209182015281518083019092528451825280850190820152611f0d906125ad565b8652505050505b611f1d83611dc2565b604083015250919050565b604080516080810182526000918101828152606080830193909352815260208101919091526000611f768360000151600381518110611f6957611f69613199565b60200260200101516125ad565b836040015181518110611f8b57611f8b613199565b602002602001015190506040518060400160405280828152602001611faf836125ad565b90529392505050565b6000611ba58260200151600081518110611fd457611fd4613199565b60200260200101516128a7565b6000611ba58260000151600581518110611bc757611bc7613199565b6060611ba58260000151600781518110611b9857611b98613199565b60008061204d8460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b9050600061205a826125ad565b90506060808560008061206c8b611bd4565b905080516000036120875760009750505050505050506122c4565b60005b86518110156122bb5781518311156120ad576000985050505050505050506122c4565b6120cf8782815181106120c2576120c2613199565b60200260200101516128c1565b9550858051906020012084146120f0576000985050505050505050506122c4565b612105878281518110611f6957611f69613199565b945084516011036121d75781518303612164578c8051906020012061213686601081518110611b9857611b98613199565b8051906020012003612153576001985050505050505050506122c4565b6000985050505050505050506122c4565b600082848151811061217857612178613199565b016020015160f81c9050601081111561219d57600099505050505050505050506122c4565b6121c2868260ff16815181106121b5576121b5613199565b6020026020010151612940565b94506121cf60018561324b565b9350506122a9565b84516002036121535760006122026121fb87600081518110611b9857611b98613199565b848661296e565b8351909150612211828661324b565b03612264578d8051906020012061223487600181518110611b9857611b98613199565b805190602001200361225257600199505050505050505050506122c4565b600099505050505050505050506122c4565b8060000361227e57600099505050505050505050506122c4565b612288818561324b565b93506122a0866001815181106121b5576121b5613199565b94506122a99050565b806122b381613263565b91505061208a565b50505050505050505b949350505050565b6000611ba58260000151600381518110611bc757611bc7613199565b6000611ba58260000151600481518110611bc757611bc7613199565b6000611ba58260000151600081518110611bc757611bc7613199565b6060611ba58260000151600181518110611b9857611b98613199565b6001546040517f41539d4a0000000000000000000000000000000000000000000000000000000081526004810184905260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a9060240160a060405180830381865afa1580156123b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d8919061329b565b509350509250925061242f828b6123ef9190613234565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a09092019092528051910120908588612aa6565b612495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4678526f6f7454756e6e656c3a20494e56414c49445f484541444552000000006044820152606401610b8a565b9998505050505050505050565b60408051602081019091526060815260405180602001604052806124d68460200151600181518110611f6957611f69613199565b905292915050565b6040805180820190915260008082526020820152825180518390811061250657612506613199565b6020026020010151905092915050565b80516000901580159061252b57508151602110155b61253457600080fd5b60006125438360200151612c53565b905060008184600001516125579190613234565b905060008083866020015161256c919061324b565b905080519150602083101561258857826020036101000a820491505b50949350505050565b6060611ba58260200151600281518110611b9857611b98613199565b60606125b8826127e1565b6125c157600080fd5b60006125cc83612cd5565b905060008167ffffffffffffffff8111156125e9576125e9612f1d565b60405190808252806020026020018201604052801561262e57816020015b60408051808201909152600080825260208201528152602001906001900390816126075790505b50905060006126408560200151612c53565b856020015161264f919061324b565b90506000805b848110156126b85761266683612d5a565b915060405180604001604052808381526020018481525084828151811061268f5761268f613199565b60209081029190910101526126a4828461324b565b9250806126b081613263565b915050612655565b509195945050505050565b80516060906126d157600080fd5b60006126e08360200151612c53565b905060008184600001516126f49190613234565b905060008167ffffffffffffffff81111561271157612711612f1d565b6040519080825280601f01601f19166020018201604052801561273b576020820181803683370190505b5090506000816020019050612588848760200151612759919061324b565b8285612e1c565b600061276d600284613317565b156127a75760108261278060028661332b565b8151811061279057612790613199565b01602001516127a2919060f81c61333f565b6127d7565b6010826127b560028661332b565b815181106127c5576127c5613199565b01602001516127d7919060f81c613361565b60f81b9392505050565b805160009081036127f457506000919050565b6020820151805160001a9060c0821015612812575060009392505050565b5060019392505050565b8060000361282957505050565b60208110612861578251825261284060208461324b565b925061284d60208361324b565b915061285a602082613234565b9050612829565b8060000361286e57505050565b6000600161287d836020613234565b612889906101006134a3565b6128939190613234565b935183518516941916939093179091525050565b80516000906015146128b857600080fd5b611ba582612516565b60606000826000015167ffffffffffffffff8111156128e2576128e2612f1d565b6040519080825280601f01601f19166020018201604052801561290c576020820181803683370190505b509050805160000361291e5792915050565b60008160200190506129398460200151828660000151612e1c565b5092915050565b805160009060211461295157600080fd5b60008083602001516001612965919061324b565b51949350505050565b6000808061297b86611bd4565b90506000815167ffffffffffffffff81111561299957612999612f1d565b6040519080825280601f01601f1916602001820160405280156129c3576020820181803683370190505b509050845b82516129d4908761324b565b811015612a775760008782815181106129ef576129ef613199565b01602001517fff000000000000000000000000000000000000000000000000000000000000001690508083612a248985613234565b81518110612a3457612a34613199565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080612a6f90613263565b9150506129c8565b508080519060200120828051906020012003612a965781519250612a9b565b600092505b509095945050505050565b600060208251612ab69190613317565b15612b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c69642070726f6f66206c656e6774680000000000000000000000006044820152606401610b8a565b600060208351612b2d919061332b565b9050612b3a8160026134a3565b8510612ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4c65616620696e64657820697320746f6f2062696700000000000000000000006044820152606401610b8a565b60008660205b85518111612c4557858101519250612bc1600289613317565b600003612bf9576040805160208101849052908101849052606001604051602081830303815290604052805190602001209150612c26565b60408051602081018590529081018390526060016040516020818303038152906040528051906020012091505b612c3160028961332b565b9750612c3e60208261324b565b9050612ba8565b509094149695505050505050565b8051600090811a6080811015612c6c5750600092915050565b60b8811080612c87575060c08110801590612c87575060f881105b15612c955750600192915050565b60c0811015612cc957612caa600160b86134af565b612cb79060ff1682613234565b612cc290600161324b565b9392505050565b612caa600160f86134af565b80516000908103612ce857506000919050565b600080612cf88460200151612c53565b8460200151612d07919061324b565b9050600084600001518560200151612d1f919061324b565b90505b80821015612d5157612d3382612d5a565b612d3d908361324b565b915082612d4981613263565b935050612d22565b50909392505050565b80516000908190811a6080811015612d755760019150612939565b60b8811015612d9b57612d89608082613234565b612d9490600161324b565b9150612939565b60c0811015612dc85760b78103600185019450806020036101000a85510460018201810193505050612939565b60f8811015612ddc57612d8960c082613234565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b80600003612e2957505050565b602081106128615782518252612e4060208461324b565b9250612e4d60208361324b565b9150612e5a602082613234565b9050612e29565b600060208284031215612e7357600080fd5b813563ffffffff81168114612cc257600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610b9c57600080fd5b60008060408385031215612ebc57600080fd5b8235612ec781612e87565b915060208301358015158114612edc57600080fd5b809150509250929050565b600060208284031215612ef957600080fd5b5035919050565b600060208284031215612f1257600080fd5b8135612cc281612e87565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f7557612f75612f1d565b604052919050565b600067ffffffffffffffff821115612f9757612f97612f1d565b50601f01601f191660200190565b600060208284031215612fb757600080fd5b813567ffffffffffffffff811115612fce57600080fd5b8201601f81018413612fdf57600080fd5b8035612ff2612fed82612f7d565b612f4c565b81815285602083850101111561300757600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b83811015613040578181015183820152602001613028565b8381111561304f576000848401525b50505050565b6000815180845261306d816020860160208601613025565b601f01601f19169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006130b06060830185613055565b905063ffffffff83166040830152949350505050565b838152600083516130de816020850160208801613025565b60209201918201929092526040019392505050565b60006020828403121561310557600080fd5b815167ffffffffffffffff81111561311c57600080fd5b8201601f8101841361312d57600080fd5b805161313b612fed82612f7d565b81815285602083850101111561315057600080fd5b613161826020830160208601613025565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006122c46040830184613055565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561322f5761322f6131c8565b500290565b600082821015613246576132466131c8565b500390565b6000821982111561325e5761325e6131c8565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613294576132946131c8565b5060010190565b600080600080600060a086880312156132b357600080fd5b8551945060208601519350604086015192506060860151915060808601516132da81612e87565b809150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613326576133266132e8565b500690565b60008261333a5761333a6132e8565b500490565b600060ff831680613352576133526132e8565b8060ff84160691505092915050565b600060ff831680613374576133746132e8565b8060ff84160491505092915050565b600181815b808511156133dc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156133c2576133c26131c8565b808516156133cf57918102915b93841c9390800290613388565b509250929050565b6000826133f357506001611ba5565b8161340057506000611ba5565b816001811461341657600281146134205761343c565b6001915050611ba5565b60ff841115613431576134316131c8565b50506001821b611ba5565b5060208310610133831016604e8410600b841016171561345f575081810a611ba5565b6134698383613383565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561349b5761349b6131c8565b029392505050565b6000612cc283836133e4565b600060ff821660ff8416808210156134c9576134c96131c8565b9003939250505056fea164736f6c634300080f000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002890ba17efe978480615e330ecb65333b880928e0000000000000000000000003d1d3e34f7fb6d26245e6640e1c50710efff15ba000000000000000000000000711965c7805635315201d0963148df4445505182000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23640000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be294000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d23640000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d
-----Decoded View---------------
Arg [0] : _checkpointManager (address): 0x2890bA17EfE978480615e330ecB65333b880928e
Arg [1] : _fxRoot (address): 0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA
Arg [2] : _worldIDIdentityManager (address): 0x711965c7805635315201d0963148DF4445505182
Arg [3] : _opWorldIDAddress (address): 0x047eE5313F98E26Cc8177fA38877cB36292D2364
Arg [4] : _opCrossDomainMessenger (address): 0x5086d1eEF304eb5284A0f6720f79403b4e9bE294
Arg [5] : _baseWorldIDAddress (address): 0x047eE5313F98E26Cc8177fA38877cB36292D2364
Arg [6] : _baseCrossDomainMessenger (address): 0x8e5693140eA606bcEB98761d9beB1BC87383706D
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000002890ba17efe978480615e330ecb65333b880928e
Arg [1] : 0000000000000000000000003d1d3e34f7fb6d26245e6640e1c50710efff15ba
Arg [2] : 000000000000000000000000711965c7805635315201d0963148df4445505182
Arg [3] : 000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d2364
Arg [4] : 0000000000000000000000005086d1eef304eb5284a0f6720f79403b4e9be294
Arg [5] : 000000000000000000000000047ee5313f98e26cc8177fa38877cb36292d2364
Arg [6] : 0000000000000000000000008e5693140ea606bceb98761d9beb1bc87383706d
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.