ETH Price: $2,633.75 (-1.10%)

Contract

0x110fd9a44a056cb418D07F7d9957D0303F0020e4
 

Overview

ETH Balance

4.167900000000000474 ETH

Eth Value

$10,977.21 (@ $2,633.75/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Receive Message218143422025-02-10 6:31:111 hrs ago1739169071IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000488421.27516479
Receive Message218134662025-02-10 3:35:113 hrs ago1739158511IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000715182.03647388
Receive Message218120852025-02-09 22:57:238 hrs ago1739141843IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000785312.1555084
Receive Message218118092025-02-09 22:01:479 hrs ago1739138507IN
0x110fd9a4...03F0020e4
0 ETH0.00210774.77950937
Receive Message218114922025-02-09 20:58:1110 hrs ago1739134691IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000535561.46756871
Receive Message218100522025-02-09 16:07:4715 hrs ago1739117267IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000483081.37946817
Receive Message218063452025-02-09 3:42:4727 hrs ago1739072567IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000459561.26164173
Receive Message218061852025-02-09 3:10:4728 hrs ago1739070647IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000509981.39347327
Receive Message218046442025-02-08 22:01:4733 hrs ago1739052107IN
0x110fd9a4...03F0020e4
0 ETH0.001056972.3967416
Receive Message218014042025-02-08 11:09:3544 hrs ago1739012975IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000575241.54627577
Receive Message218013932025-02-08 11:07:2344 hrs ago1739012843IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000602921.55338864
Receive Message217974652025-02-07 21:57:592 days ago1738965479IN
0x110fd9a4...03F0020e4
0 ETH0.000299412.5339041
Receive Message217957652025-02-07 16:16:112 days ago1738944971IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000835492.38636615
Receive Message217954972025-02-07 15:22:232 days ago1738941743IN
0x110fd9a4...03F0020e4
0.0004 ETH0.001563313.986167
Receive Message217953282025-02-07 14:48:232 days ago1738939703IN
0x110fd9a4...03F0020e4
0.0004 ETH0.001176963.09778311
Receive Message217913672025-02-07 1:32:233 days ago1738891943IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000537541.44342624
Receive Message217903002025-02-06 21:58:113 days ago1738879091IN
0x110fd9a4...03F0020e4
0 ETH0.000318132.69177297
Receive Message217898072025-02-06 20:18:593 days ago1738873139IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000639371.75773825
Receive Message217857622025-02-06 6:47:114 days ago1738824431IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000558621.54964296
Receive Message217832832025-02-05 22:28:234 days ago1738794503IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000613681.61757827
Receive Message217831472025-02-05 22:01:114 days ago1738792871IN
0x110fd9a4...03F0020e4
0 ETH0.000341882.89125821
Receive Message217793452025-02-05 9:17:354 days ago1738747055IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000722841.93416999
Receive Message217777822025-02-05 4:02:595 days ago1738728179IN
0x110fd9a4...03F0020e4
0.0004 ETH0.000649321.84406622
Receive Message217775382025-02-05 3:13:355 days ago1738725215IN
0x110fd9a4...03F0020e4
0.0004 ETH0.001380213.7948097
Receive Message217773112025-02-05 2:27:595 days ago1738722479IN
0x110fd9a4...03F0020e4
0.0004 ETH0.001538664.03984658
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
218146202025-02-10 7:27:113 mins ago1739172431
0x110fd9a4...03F0020e4
0.0003 ETH
218133432025-02-10 3:10:354 hrs ago1739157035
0x110fd9a4...03F0020e4
0.0003 ETH
218118092025-02-09 22:01:479 hrs ago1739138507
0x110fd9a4...03F0020e4
0.0016 ETH
218106172025-02-09 18:02:1113 hrs ago1739124131
0x110fd9a4...03F0020e4
0.0003 ETH
218092932025-02-09 13:35:4717 hrs ago1739108147
0x110fd9a4...03F0020e4
0.0003 ETH
218067692025-02-09 5:07:5926 hrs ago1739077679
0x110fd9a4...03F0020e4
0.0003 ETH
218046442025-02-08 22:01:4733 hrs ago1739052107
0x110fd9a4...03F0020e4
0.0008 ETH
218024852025-02-08 14:46:4740 hrs ago1739026007
0x110fd9a4...03F0020e4
0.0003 ETH
218012572025-02-08 10:40:1144 hrs ago1739011211
0x110fd9a4...03F0020e4
0.0003 ETH
217985422025-02-08 1:33:352 days ago1738978415
0x110fd9a4...03F0020e4
0.0003 ETH
217981242025-02-08 0:09:592 days ago1738973399
0x110fd9a4...03F0020e4
0.0003 ETH
217974652025-02-07 21:57:592 days ago1738965479
0x110fd9a4...03F0020e4
0.0016 ETH
217943452025-02-07 11:31:232 days ago1738927883
0x110fd9a4...03F0020e4
0.0003 ETH
217903002025-02-06 21:58:113 days ago1738879091
0x110fd9a4...03F0020e4
0.0012 ETH
217896942025-02-06 19:56:233 days ago1738871783
0x110fd9a4...03F0020e4
0.0003 ETH
217884722025-02-06 15:50:593 days ago1738857059
0x110fd9a4...03F0020e4
0.0003 ETH
217884722025-02-06 15:50:593 days ago1738857059
0x110fd9a4...03F0020e4
0.0003 ETH
217884622025-02-06 15:48:593 days ago1738856939
0x110fd9a4...03F0020e4
0.0003 ETH
217884592025-02-06 15:48:233 days ago1738856903
0x110fd9a4...03F0020e4
0.0003 ETH
217884422025-02-06 15:44:593 days ago1738856699
0x110fd9a4...03F0020e4
0.0003 ETH
217878112025-02-06 13:38:353 days ago1738849115
0x110fd9a4...03F0020e4
0.0003 ETH
217847712025-02-06 3:27:234 days ago1738812443
0x110fd9a4...03F0020e4
0.0003 ETH
217831472025-02-05 22:01:114 days ago1738792871
0x110fd9a4...03F0020e4
0.002 ETH
217830532025-02-05 21:42:234 days ago1738791743
0x110fd9a4...03F0020e4
0.0003 ETH
217795102025-02-05 9:50:354 days ago1738749035
0x110fd9a4...03F0020e4
0.0003 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Bridge

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 10 : Bridge.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./IBridge.sol";

/// @title Root network bridge contract on ethereum
/// @author Root Network
/// @notice Provides methods for verifying messages from the validator set
contract Bridge is IBridge, IBridgeReceiver, Ownable, ReentrancyGuard, ERC165 {
    using ECDSA for bytes32;

    // map from validator set nonce to keccak256 digest of validator ECDSA addresses (i.e bridge session keys)
    // these should be encoded in sorted order matching `pallet_session::Module<T>::validators()` to create the digest
    // signatures from a threshold of these addresses are considered approved by the protocol
    mapping(uint => bytes32) public validatorSetDigests;
    // Nonce for validator set changes
    uint32 public activeValidatorSetId;
    // Nonce of the next outgoing event
    uint public sentEventId;
    // Map of verified incoming event nonces
    // will only validate one event per nonce.
    // Verification/submission out of order is ok.
    mapping(uint => bool) public verifiedEventIds;
    // Fee for message verification
    // Offsets bridge upkeep costs i.e updating the validator set
    uint public bridgeFee = 4e15; // 0.004 ether
    // Acceptance threshold in %
    uint public thresholdPercent = 60;
    // Number of staking eras before a bridge message will be considered expired
    uint public proofTTL = 7;
    // Whether the bridge is active or not
    bool public active = false;
    // Max reward paid out to successful caller of `setValidator`
    uint public maxRewardPayout = 1 ether;
    // The bridge pallet (pseudo) address this contract is paired with
    address public palletAddress =
        address(0x6D6f646C65746879627264670000000000000000);
    // Max message length allowed
    uint public maxMessageLength = 1024; // 1kb
    // Fee required to be paid for SendMessage calls
    uint256 internal _sendMessageFee = 3e14; // 0.0003 ether
    // Message fees accumulated by the bridge
    uint public accumulatedMessageFees;

    event MessageReceived(
        uint indexed eventId,
        address indexed source,
        address indexed destinate,
        bytes message
    );
    event SetValidators(
        bytes32 indexed validatorSetDigest,
        uint256 indexed reward,
        uint32 indexed validatorSetId
    );
    event ForceSetActiveValidators(
        bytes32 indexed validatorSetDigest,
        uint32 indexed validatorSetId
    );
    event ForceSetHistoricValidators(
        bytes32 indexed validatorSetDigest,
        uint32 indexed validatorSetId
    );
    event BridgeFeeUpdated(uint indexed bridgeFee);
    event ThresholdUpdated(uint indexed thresholdPercent);
    event ProofTTLUpdated(uint indexed proofTTL);
    event BridgeActiveUpdated(bool indexed active);
    event MaxRewardPayoutUpdated(uint indexed maxRewardPayout);
    event PalletAddressUpdated(address indexed palletAddress);
    event MaxMessageLengthUpdated(uint indexed maxMessageLength);
    event SentEventIdUpdated(uint indexed _newId);
    event Endowed(uint256 indexed amount);
    event EtherWithdrawn(address _to, uint256 _amount);
    event WithdrawnMessageFees(address indexed recipient, uint indexed amount);
    event SendMessageFeeUpdated(uint256 indexed sendMessageFee);

    /// @notice Emit an event for the remote chain
    function sendMessage(address destination, bytes calldata message)
        external
        payable
        override
    {
        require(active, "Bridge: bridge inactive");
        require(message.length <= maxMessageLength, "Bridge: msg exceeds max length");
        require(msg.value >= _sendMessageFee, "Bridge: insufficient message fee");
        accumulatedMessageFees += msg.value;
        emit SendMessage(sentEventId++, msg.sender, destination, message, msg.value);
    }

    function sendMessageFee() external override view returns (uint256) {
        return _sendMessageFee;
    }

    /// @notice Receive a message from the remote chain
    /// @param proof contains a list of validator signature data and respective addresses - retrieved via RPC call from the remote chain
    function receiveMessage(
        address source,
        address destination,
        bytes calldata appMessage,
        EventProof calldata proof
    ) external payable override {
        require(
            msg.value >= bridgeFee || destination == address(this),
            "Bridge: must supply bridge fee"
        );
        require(appMessage.length > 0, "Bridge: empty message");

        bytes memory preimage = abi.encode(
            source,
            destination,
            appMessage,
            proof.validatorSetId,
            proof.eventId
        );
        _verifyMessage(preimage, proof);

        emit MessageReceived(proof.eventId, source, destination, appMessage);

        // call bridge receiver
        IBridgeReceiver(destination).onMessageReceived(source, appMessage);
    }

    /// @notice Verify a message was authorised by validators.
    /// - Callable by anyone.
    /// - Caller must provide `bridgeFee`.
    /// - Requires signatures from a threshold validators at proof.validatorSetId.
    /// - Requires proof is not older than `proofTTL` eras
    /// - Halts on failure
    ///
    /// @dev Parameters:
    /// - preimage: the unhashed message data packed wide w source, dest, validatorSetId & eventId e.g. `abi.encode(source, dest, message, validatorSetId, eventId);`
    /// - proof: Signed witness material generated by proving 'message'
    ///     - v,r,s are sparse arrays expected to align w public key in 'validators'
    ///     - i.e. v[i], r[i], s[i] matches the i-th validator[i]
    function _verifyMessage(bytes memory preimage, EventProof calldata proof)
        internal
    {
        // gas savings
        uint256 _eventId = proof.eventId;
        uint32 _validatorSetId = proof.validatorSetId;
        address[] memory _validators = proof.validators;

        require(active, "Bridge: bridge inactive");
        require(!verifiedEventIds[_eventId], "Bridge: eventId replayed");
        require(
            _validatorSetId <= activeValidatorSetId,
            "Bridge: future validator set"
        );
        require(
            activeValidatorSetId - _validatorSetId <= proofTTL,
            "Bridge: expired proof"
        );
        // audit item #1
        require(_validators.length > 0, "Bridge: invalid validator set");
        require(
            keccak256(abi.encode(_validators)) ==
                validatorSetDigests[_validatorSetId],
            "Bridge: unexpected validator digest"
        );

        bytes32 digest = keccak256(preimage);
        uint acceptanceTreshold = ((_validators.length * thresholdPercent) /
            100);
        uint witnessCount; // uint256(0)
        bytes32 ommited; // bytes32(0)

        for (uint i; i < _validators.length; ++i) {
            if (proof.r[i] != ommited) { // check signature omitted == bytes32(0)
                // check signature
                require(
                    _validators[i] == digest.recover(proof.v[i], proof.r[i], proof.s[i]),
                    "Bridge: signature invalid"
                );
                witnessCount += 1;
                // have we got proven consensus?
                if (witnessCount >= acceptanceTreshold) {
                    break;
                }
            }
        }

        require(witnessCount >= acceptanceTreshold, "Bridge: not enough signatures");
        verifiedEventIds[_eventId] = true;
    }

    /// @notice Handle a verified message provided by 'receiveMessage` to update the next validator set
    /// i.e. The bridge contract is itself a bridge app contract
    function onMessageReceived(address source, bytes calldata message)
        external
        override
    {
        require(msg.sender == address(this), "Bridge: only bridge can call");
        require(source == palletAddress, "Bridge: source must be pallet");
        (address[] memory newValidators, uint32 newValidatorSetId) = abi.decode(
            message,
            (address[], uint32)
        );
        _setValidators(newValidators, newValidatorSetId);
    }

    /// @dev Update the known validator set (must be called via 'relayMessage' with a valid proof of new validator set)
    function _setValidators(
        address[] memory newValidators,
        uint32 newValidatorSetId
    ) internal nonReentrant {
        require(newValidators.length > 0, "Bridge: empty validator set"); // also checked in _verifyMessage
        require(
            newValidatorSetId > activeValidatorSetId,
            "Bridge: validator set id replayed"
        );

        // update set digest and active id
        bytes32 validatorSetDigest = keccak256(abi.encode(newValidators));
        validatorSetDigests[newValidatorSetId] = validatorSetDigest;
        activeValidatorSetId = newValidatorSetId;

        // return accumulated fees to the sender as a reward, capped at `maxRewardPayout`
        uint reward = Math.min(address(this).balance - accumulatedMessageFees, maxRewardPayout);
        (bool sent, ) = tx.origin.call{value: reward}("");
        require(sent, "Bridge: Failed to send reward");

        emit SetValidators(validatorSetDigest, reward, newValidatorSetId);
    }

    /// @dev See {IERC165-supportsInterface}. Docs: https://docs.openzeppelin.com/contracts/4.x/api/utils#IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IBridge).interfaceId ||
            interfaceId == type(IBridgeReceiver).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    // ============================================================================================================= //
    // ============================================== Admin functions ============================================== //
    // ============================================================================================================= //

    /// @notice force set the active validator set
    /// @dev newValidatorSetId can be equal to current activeValidatorSetId - to override current validators
    function forceActiveValidatorSet(
        address[] calldata newValidators,
        uint32 newValidatorSetId
    ) external onlyOwner {
        require(newValidators.length > 0, "Bridge: empty validator set");
        require(newValidatorSetId >= activeValidatorSetId, "Bridge: set is historic");
        bytes32 validatorSetDigest = keccak256(abi.encode(newValidators));
        validatorSetDigests[newValidatorSetId] = validatorSetDigest;
        activeValidatorSetId = newValidatorSetId;
        emit ForceSetActiveValidators(validatorSetDigest, newValidatorSetId);
    }

    /// @notice Force set a historic validator set
    /// @dev Sets older than proofTTL are not modifiable (since they cannot produce valid proofs any longer)
    function forceHistoricValidatorSet(
        address[] calldata _validators,
        uint32 validatorSetId
    ) external onlyOwner {
        require(_validators.length > 0, "Bridge: empty validator set");
        require(
            validatorSetId + proofTTL > activeValidatorSetId,
            "Bridge: set is inactive"
        );
        bytes32 validatorSetDigest = keccak256(abi.encode(_validators));
        validatorSetDigests[validatorSetId] = validatorSetDigest;
        emit ForceSetHistoricValidators(validatorSetDigest, validatorSetId);
    }

    /// @notice Set the TTL for historic validator set proofs
    function setProofTTL(uint256 _proofTTL) external onlyOwner {
        proofTTL = _proofTTL;
        emit ProofTTLUpdated(_proofTTL);
    }

    /// @notice Set the max reward payout for `setValidator` incentive
    function setMaxRewardPayout(uint256 _maxRewardPayout) external onlyOwner {
        maxRewardPayout = _maxRewardPayout;
        emit MaxRewardPayoutUpdated(_maxRewardPayout);
    }

    /// @notice Set the sentEventId for the contract to start with
    function setSentEventId(uint _newId) external onlyOwner {
        sentEventId = _newId;
        emit SentEventIdUpdated(_newId);
    }

    /// @notice Set the fee for verify messages
    function setBridgeFee(uint256 _bridgeFee) external onlyOwner {
        bridgeFee = _bridgeFee;
        emit BridgeFeeUpdated(_bridgeFee);
    }

    /// @notice Set the threshold % required for proof verification
    function setThreshold(uint256 _thresholdPercent) external onlyOwner {
        require(_thresholdPercent <= 100, "Bridge: percent must be <= 100");
        thresholdPercent = _thresholdPercent;
        emit ThresholdUpdated(_thresholdPercent);
    }

    /// @notice Set the pallet address
    function setPalletAddress(address _palletAddress) external onlyOwner {
        palletAddress = _palletAddress;
        emit PalletAddressUpdated(_palletAddress);
    }

    /// @notice Activate/deactivate the bridge
    function setActive(bool _active) external onlyOwner {
        active = _active;
        emit BridgeActiveUpdated(_active);
    }

    /// @dev Reset max message length
    function setMaxMessageLength(uint256 _maxMessageLength) external onlyOwner {
        maxMessageLength = _maxMessageLength;
        emit MaxMessageLengthUpdated(_maxMessageLength);
    }

    /// @dev Endow the contract with ether
    function endow() external payable {
        require(msg.value > 0, "Bridge: must endow nonzero");
        emit Endowed(msg.value);
    }

    /// @dev Owner can withdraw ether from the contract (primarily to support contract upgradability)
    function withdrawAll(address payable _to) public onlyOwner {
        uint256 balance = address(this).balance;
        (bool sent,) = _to.call{value: balance}("");
        require(sent, "Bridge: failed to send Ether");
        emit EtherWithdrawn(_to, balance);
    }

    /// @dev Set _sendMessageFee
    function setSendMessageFee(uint256 _fee) external onlyOwner {
        _sendMessageFee = _fee;
        emit SendMessageFeeUpdated(_fee);
    }

    /// @dev Owner can withdraw accumulates msg fees from the contract
    function withdrawMsgFees(address payable _to, uint256 _amount) public onlyOwner {
        accumulatedMessageFees -= _amount; // prevent re-entrancy protection
        (bool sent, ) = _to.call{value: _amount}("");
        require(sent, "Bridge: Failed to send msg fees");
        emit WithdrawnMessageFees(_to, _amount);
    }
}

File 2 of 10 : IBridge.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.17;

// Proof of a witnessed event by validators
struct EventProof {
    // The Id (nonce) of the event
    uint256 eventId;
    // The validator set Id which witnessed the event
    uint32 validatorSetId;
    // v,r,s are sparse arrays expected to align w public key in 'validators'
    // i.e. v[i], r[i], s[i] matches the i-th validator[i]
    // v part of validator signatures
    uint8[] v;
    // r part of validator signatures
    bytes32[] r;
    // s part of validator signatures
    bytes32[] s;
    // The validator addresses
    address[] validators;
}

interface IBridge {
    // A sent message event
    event SendMessage(uint messageId, address source, address destination, bytes message, uint256 fee);
    // Receive a bridge message from the remote chain
    function receiveMessage(address source, address destination, bytes calldata message, EventProof calldata proof) external payable;
    // Send a bridge message to the remote chain
    function sendMessage(address destination, bytes calldata message) external payable;
    // Send message fee - used by sendMessage caller to obtain required fee for sendMessage
    function sendMessageFee() external view returns (uint256);
}

interface IBridgeReceiver {
    // Handle a bridge message received from the remote chain
    // It is guaranteed to be valid
    function onMessageReceived(address source, bytes calldata message) external;
}

File 3 of 10 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 4 of 10 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 5 of 10 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 6 of 10 : Ownable.sol
// 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);
    }
}

File 7 of 10 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`.
        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
        // good first aproximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1;
        uint256 x = a;
        if (x >> 128 > 0) {
            x >>= 128;
            result <<= 64;
        }
        if (x >> 64 > 0) {
            x >>= 64;
            result <<= 32;
        }
        if (x >> 32 > 0) {
            x >>= 32;
            result <<= 16;
        }
        if (x >> 16 > 0) {
            x >>= 16;
            result <<= 8;
        }
        if (x >> 8 > 0) {
            x >>= 8;
            result <<= 4;
        }
        if (x >> 4 > 0) {
            x >>= 4;
            result <<= 2;
        }
        if (x >> 2 > 0) {
            result <<= 1;
        }

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        uint256 result = sqrt(a);
        if (rounding == Rounding.Up && result * result < a) {
            result += 1;
        }
        return result;
    }
}

File 8 of 10 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 9 of 10 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 10 of 10 : Context.sol
// 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;
    }
}

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"active","type":"bool"}],"name":"BridgeActiveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"bridgeFee","type":"uint256"}],"name":"BridgeFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Endowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"EtherWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"validatorSetDigest","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"validatorSetId","type":"uint32"}],"name":"ForceSetActiveValidators","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"validatorSetDigest","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"validatorSetId","type":"uint32"}],"name":"ForceSetHistoricValidators","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"maxMessageLength","type":"uint256"}],"name":"MaxMessageLengthUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"maxRewardPayout","type":"uint256"}],"name":"MaxRewardPayoutUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eventId","type":"uint256"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":true,"internalType":"address","name":"destinate","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"MessageReceived","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":"palletAddress","type":"address"}],"name":"PalletAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proofTTL","type":"uint256"}],"name":"ProofTTLUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"messageId","type":"uint256"},{"indexed":false,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SendMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sendMessageFee","type":"uint256"}],"name":"SendMessageFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_newId","type":"uint256"}],"name":"SentEventIdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"validatorSetDigest","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":true,"internalType":"uint32","name":"validatorSetId","type":"uint32"}],"name":"SetValidators","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"thresholdPercent","type":"uint256"}],"name":"ThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawnMessageFees","type":"event"},{"inputs":[],"name":"accumulatedMessageFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeValidatorSetId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"newValidators","type":"address[]"},{"internalType":"uint32","name":"newValidatorSetId","type":"uint32"}],"name":"forceActiveValidatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_validators","type":"address[]"},{"internalType":"uint32","name":"validatorSetId","type":"uint32"}],"name":"forceHistoricValidatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxMessageLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRewardPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"source","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"onMessageReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"palletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofTTL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"source","type":"address"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes","name":"appMessage","type":"bytes"},{"components":[{"internalType":"uint256","name":"eventId","type":"uint256"},{"internalType":"uint32","name":"validatorSetId","type":"uint32"},{"internalType":"uint8[]","name":"v","type":"uint8[]"},{"internalType":"bytes32[]","name":"r","type":"bytes32[]"},{"internalType":"bytes32[]","name":"s","type":"bytes32[]"},{"internalType":"address[]","name":"validators","type":"address[]"}],"internalType":"struct EventProof","name":"proof","type":"tuple"}],"name":"receiveMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"sendMessageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sentEventId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_active","type":"bool"}],"name":"setActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bridgeFee","type":"uint256"}],"name":"setBridgeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMessageLength","type":"uint256"}],"name":"setMaxMessageLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxRewardPayout","type":"uint256"}],"name":"setMaxRewardPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_palletAddress","type":"address"}],"name":"setPalletAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_proofTTL","type":"uint256"}],"name":"setProofTTL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setSendMessageFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newId","type":"uint256"}],"name":"setSentEventId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_thresholdPercent","type":"uint256"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"thresholdPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"validatorSetDigests","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"verifiedEventIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawMsgFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052660e35fa931a0000600655603c60075560076008556000600960006101000a81548160ff021916908315150217905550670de0b6b3a7640000600a55736d6f646c65746879627264670000000000000000600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610400600c55660110d9316ec000600d55348015620000b357600080fd5b50620000d4620000c8620000e160201b60201c565b620000e960201b60201c565b60018081905550620001ad565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b613f8080620001bd6000396000f3fe6080604052600436106101f95760003560e01c80637755618b1161010d5780639c11bc30116100a0578063cfc16cea1161006f578063cfc16cea14610696578063d87500db146106c1578063f0bdb2d1146106fe578063f2fde38b14610727578063fa09e63014610750576101f9565b80639c11bc30146105fd578063acec338a14610626578063bb5ddb0f1461064f578063c6c0f59e1461066b576101f9565b80638da5cb5b116100dc5780638da5cb5b14610543578063960bfe041461056e578063996b2f9414610597578063998cdf83146105d4576101f9565b80637755618b146104a8578063823d2fc8146104d157806382b12dd7146104ed57806387b50acb14610518576101f9565b80634008b03f1161019057806361ab5a781161015f57806361ab5a78146103eb578063650bd364146104145780636a70fef21461043d578063715018a614610468578063728952f81461047f576101f9565b80634008b03f146103435780634acf77211461036c57806350dcb027146103955780635f7e9399146103c0576101f9565b80632c05f9a2116101cc5780632c05f9a21461029b5780632ee111ed146102c65780633301a464146102ef5780633ab578aa14610318576101f9565b806301ffc9a7146101fe57806302fb0c5e1461023b57806306e30dfc146102665780631d1d4e2914610270575b600080fd5b34801561020a57600080fd5b50610225600480360381019061022091906122b4565b610779565b60405161023291906122fc565b60405180910390f35b34801561024757600080fd5b5061025061085b565b60405161025d91906122fc565b60405180910390f35b61026e61086e565b005b34801561027c57600080fd5b506102856108e0565b6040516102929190612330565b60405180910390f35b3480156102a757600080fd5b506102b06108e6565b6040516102bd9190612330565b60405180910390f35b3480156102d257600080fd5b506102ed60048036038101906102e891906123a9565b6108ec565b005b3480156102fb57600080fd5b5061031660048036038101906103119190612402565b61097b565b005b34801561032457600080fd5b5061032d6109ba565b60405161033a9190612330565b60405180910390f35b34801561034f57600080fd5b5061036a600480360381019061036591906124d0565b6109c0565b005b34801561037857600080fd5b50610393600480360381019061038e91906124d0565b610b00565b005b3480156103a157600080fd5b506103aa610c55565b6040516103b79190612330565b60405180910390f35b3480156103cc57600080fd5b506103d5610c5f565b6040516103e2919061253f565b60405180910390f35b3480156103f757600080fd5b50610412600480360381019061040d9190612402565b610c75565b005b34801561042057600080fd5b5061043b600480360381019061043691906125b0565b610cb4565b005b34801561044957600080fd5b50610452610dd9565b60405161045f9190612330565b60405180910390f35b34801561047457600080fd5b5061047d610ddf565b005b34801561048b57600080fd5b506104a660048036038101906104a19190612402565b610df3565b005b3480156104b457600080fd5b506104cf60048036038101906104ca9190612402565b610e32565b005b6104eb60048036038101906104e69190612634565b610e71565b005b3480156104f957600080fd5b50610502611063565b60405161050f9190612330565b60405180910390f35b34801561052457600080fd5b5061052d611069565b60405161053a9190612330565b60405180910390f35b34801561054f57600080fd5b5061055861106f565b60405161056591906126e7565b60405180910390f35b34801561057a57600080fd5b5061059560048036038101906105909190612402565b611098565b005b3480156105a357600080fd5b506105be60048036038101906105b99190612402565b61111b565b6040516105cb919061271b565b60405180910390f35b3480156105e057600080fd5b506105fb60048036038101906105f69190612402565b611133565b005b34801561060957600080fd5b50610624600480360381019061061f9190612402565b611172565b005b34801561063257600080fd5b5061064d60048036038101906106489190612762565b6111b1565b005b610669600480360381019061066491906125b0565b611205565b005b34801561067757600080fd5b50610680611356565b60405161068d91906126e7565b60405180910390f35b3480156106a257600080fd5b506106ab61137c565b6040516106b89190612330565b60405180910390f35b3480156106cd57600080fd5b506106e860048036038101906106e39190612402565b611382565b6040516106f591906122fc565b60405180910390f35b34801561070a57600080fd5b50610725600480360381019061072091906127cd565b6113a2565b005b34801561073357600080fd5b5061074e600480360381019061074991906123a9565b6114b8565b005b34801561075c57600080fd5b506107776004803603810190610772919061280d565b61153b565b005b60007f69bc44e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061084457507f650bd364000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610854575061085382611632565b5b9050919050565b600960009054906101000a900460ff1681565b600034116108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a890612897565b60405180910390fd5b347f840be946bba3df0d184eb7e6cd7c9e57bb380cf6078516c7441db5709d58509860405160405180910390a2565b600c5481565b600a5481565b6108f461169c565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f679cb5acfebd038830b61daadd5f2f74e2114862b1c289a5d2db82bc6eda32a660405160405180910390a250565b61098361169c565b80600a81905550807f11cff79cc5c082b5f775ae922a2a6dc80e9f79b9207767278bdf7391db5467f760405160405180910390a250565b60085481565b6109c861169c565b60008383905011610a0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0590612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff166008548263ffffffff16610a3b9190612952565b11610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a72906129d2565b60405180910390fd5b60008383604051602001610a90929190612ab5565b60405160208183030381529060405280519060200120905080600260008463ffffffff168152602001908152602001600020819055508163ffffffff16817ff541dede932a20dba17286430555d7aa784b74222f2a34f107d40822f41992e360405160405180910390a350505050565b610b0861169c565b60008383905011610b4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4590612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168163ffffffff161015610baf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba690612b25565b60405180910390fd5b60008383604051602001610bc4929190612ab5565b60405160208183030381529060405280519060200120905080600260008463ffffffff1681526020019081526020016000208190555081600360006101000a81548163ffffffff021916908363ffffffff1602179055508163ffffffff16817f36885d9a49d239da5379a6f8f9bb89273332a7e312cb5b8a2d3b0f567e8209f460405160405180910390a350505050565b6000600d54905090565b600360009054906101000a900463ffffffff1681565b610c7d61169c565b80600481905550807f06055c66c43187163b022b7d954ff32b4ba5265e175458d1b134cfe8ab72f41260405160405180910390a250565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d1990612b91565b60405180910390fd5b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610db2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da990612bfd565b60405180910390fd5b6000808383810190610dc49190612d6c565b91509150610dd2828261171a565b5050505050565b600e5481565b610de761169c565b610df16000611981565b565b610dfb61169c565b80600d81905550807fabd57ef278738881488128581f298faa35ba1bae2bbec9fb6e370ff60d531e4b60405160405180910390a250565b610e3a61169c565b80600881905550807f01116a77fa86522c55d40463f1b48825870a5d04ea15ca52a166d8ace7f355ff60405160405180910390a250565b60065434101580610ead57503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b610eec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee390612e14565b60405180910390fd5b60008383905011610f32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2990612e80565b60405180910390fd5b600085858585856020016020810190610f4b9190612ea0565b8660000135604051602001610f6596959493929190612f1a565b6040516020818303038152906040529050610f808183611a45565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1683600001357f3591658888eebc109961f7116a3e6aafbbeb08b55e727cf69c44d466a77a90d18787604051610fe4929190612f76565b60405180910390a48473ffffffffffffffffffffffffffffffffffffffff1663650bd3648786866040518463ffffffff1660e01b815260040161102993929190612f9a565b600060405180830381600087803b15801561104357600080fd5b505af1158015611057573d6000803e3d6000fd5b50505050505050505050565b60065481565b60045481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6110a061169c565b60648111156110e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110db90613018565b60405180910390fd5b80600781905550807fadfa8ecb21b6962ebcd0adbd9ab985b7b4c5b5eb3b0dead683171565c7bfe17160405160405180910390a250565b60026020528060005260406000206000915090505481565b61113b61169c565b80600681905550807f42dfb00d085d601e55327921154ae76c1b24270b026c5a0c51caee18eb4c401f60405160405180910390a250565b61117a61169c565b80600c81905550807f80e9dc023eeed9cbe4e886f225681c4fa94a046011c6269619c21befd6c4518160405160405180910390a250565b6111b961169c565b80600960006101000a81548160ff0219169083151502179055508015157fd06b0db8a7172c6c142c15cd90b6efb883b600b978dfca380621aa4c9f6d881560405160405180910390a250565b600960009054906101000a900460ff16611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90613084565b60405180910390fd5b600c5482829050111561129c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611293906130f0565b60405180910390fd5b600d543410156112e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d89061315c565b60405180910390fd5b34600e60008282546112f39190612952565b925050819055507ff2a50cd57a795ad452a0b8586bcd3fe8e3ee00054c01c4712655d7753539dd356004600081548092919061132e9061317c565b919050553385858534604051611349969594939291906131c4565b60405180910390a1505050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075481565b60056020528060005260406000206000915054906101000a900460ff1681565b6113aa61169c565b80600e60008282546113bc9190613220565b9250508190555060008273ffffffffffffffffffffffffffffffffffffffff16826040516113e990613285565b60006040518083038185875af1925050503d8060008114611426576040519150601f19603f3d011682016040523d82523d6000602084013e61142b565b606091505b505090508061146f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611466906132e6565b60405180910390fd5b818373ffffffffffffffffffffffffffffffffffffffff167fcc89aff20f6022ea39ee28e42ebe0013f5e8a32d9388b49d2f6fe08563a54cdf60405160405180910390a3505050565b6114c061169c565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361152f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152690613378565b60405180910390fd5b61153881611981565b50565b61154361169c565b600047905060008273ffffffffffffffffffffffffffffffffffffffff168260405161156e90613285565b60006040518083038185875af1925050503d80600081146115ab576040519150601f19603f3d011682016040523d82523d6000602084013e6115b0565b606091505b50509050806115f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115eb906133e4565b60405180910390fd5b7f06097061aeda806b5e9cb4133d9899f332ff0913956567fc0f7ea15e3d19947c8383604051611625929190613463565b60405180910390a1505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6116a4611f24565b73ffffffffffffffffffffffffffffffffffffffff166116c261106f565b73ffffffffffffffffffffffffffffffffffffffff1614611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f906134d8565b60405180910390fd5b565b60026001540361175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690613544565b60405180910390fd5b600260018190555060008251116117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168163ffffffff161161180b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611802906135d6565b60405180910390fd5b60008260405160200161181e919061367c565b60405160208183030381529060405280519060200120905080600260008463ffffffff1681526020019081526020016000208190555081600360006101000a81548163ffffffff021916908363ffffffff1602179055506000611890600e54476118889190613220565b600a54611f2c565b905060003273ffffffffffffffffffffffffffffffffffffffff16826040516118b890613285565b60006040518083038185875af1925050503d80600081146118f5576040519150601f19603f3d011682016040523d82523d6000602084013e6118fa565b606091505b505090508061193e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611935906136ea565b60405180910390fd5b8363ffffffff1682847f3dab4e75c61b76a4152c289f3c93392ddab6386b2423ffab2cee4da9fbb05c7160405160405180910390a4505050600180819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000816000013590506000826020016020810190611a639190612ea0565b90506000838060a00190611a779190613719565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509050600960009054906101000a900460ff16611b08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611aff90613084565b60405180910390fd5b6005600084815260200190815260200160002060009054906101000a900460ff1615611b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b60906137c8565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168263ffffffff161115611bca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc190613834565b60405180910390fd5b60085482600360009054906101000a900463ffffffff16611beb9190613854565b63ffffffff161115611c32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c29906138d8565b60405180910390fd5b6000815111611c76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6d90613944565b60405180910390fd5b600260008363ffffffff1681526020019081526020016000205481604051602001611ca1919061367c565b6040516020818303038152906040528051906020012014611cf7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cee906139d6565b60405180910390fd5b600085805190602001209050600060646007548451611d1691906139f6565b611d209190613a67565b905060008060005b8551811015611ea95781898060600190611d429190613a98565b83818110611d5357611d52613afb565b5b9050602002013514611e9857611df9898060400190611d729190613b2a565b83818110611d8357611d82613afb565b5b9050602002016020810190611d989190613bc6565b8a8060600190611da89190613a98565b84818110611db957611db8613afb565b5b905060200201358b8060800190611dd09190613a98565b85818110611de157611de0613afb565b5b9050602002013588611f45909392919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16868281518110611e2257611e21613afb565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614611e80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7790613c3f565b60405180910390fd5b600183611e8d9190612952565b925083831015611ea9575b80611ea29061317c565b9050611d28565b5082821015611eed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee490613cab565b60405180910390fd5b60016005600089815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050505050565b600033905090565b6000818310611f3b5781611f3d565b825b905092915050565b6000806000611f5687878787611f70565b91509150611f638161207c565b8192505050949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c1115611fab576000600391509150612073565b601b8560ff1614158015611fc35750601c8560ff1614155b15611fd5576000600491509150612073565b600060018787878760405160008152602001604052604051611ffa9493929190613cda565b6020604051602081039080840390855afa15801561201c573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361206a57600060019250925050612073565b80600092509250505b94509492505050565b600060048111156120905761208f613d1f565b5b8160048111156120a3576120a2613d1f565b5b031561224557600160048111156120bd576120bc613d1f565b5b8160048111156120d0576120cf613d1f565b5b03612110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210790613d9a565b60405180910390fd5b6002600481111561212457612123613d1f565b5b81600481111561213757612136613d1f565b5b03612177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161216e90613e06565b60405180910390fd5b6003600481111561218b5761218a613d1f565b5b81600481111561219e5761219d613d1f565b5b036121de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d590613e98565b60405180910390fd5b6004808111156121f1576121f0613d1f565b5b81600481111561220457612203613d1f565b5b03612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223b90613f2a565b60405180910390fd5b5b50565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6122918161225c565b811461229c57600080fd5b50565b6000813590506122ae81612288565b92915050565b6000602082840312156122ca576122c9612252565b5b60006122d88482850161229f565b91505092915050565b60008115159050919050565b6122f6816122e1565b82525050565b600060208201905061231160008301846122ed565b92915050565b6000819050919050565b61232a81612317565b82525050565b60006020820190506123456000830184612321565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123768261234b565b9050919050565b6123868161236b565b811461239157600080fd5b50565b6000813590506123a38161237d565b92915050565b6000602082840312156123bf576123be612252565b5b60006123cd84828501612394565b91505092915050565b6123df81612317565b81146123ea57600080fd5b50565b6000813590506123fc816123d6565b92915050565b60006020828403121561241857612417612252565b5b6000612426848285016123ed565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126124545761245361242f565b5b8235905067ffffffffffffffff81111561247157612470612434565b5b60208301915083602082028301111561248d5761248c612439565b5b9250929050565b600063ffffffff82169050919050565b6124ad81612494565b81146124b857600080fd5b50565b6000813590506124ca816124a4565b92915050565b6000806000604084860312156124e9576124e8612252565b5b600084013567ffffffffffffffff81111561250757612506612257565b5b6125138682870161243e565b93509350506020612526868287016124bb565b9150509250925092565b61253981612494565b82525050565b60006020820190506125546000830184612530565b92915050565b60008083601f8401126125705761256f61242f565b5b8235905067ffffffffffffffff81111561258d5761258c612434565b5b6020830191508360018202830111156125a9576125a8612439565b5b9250929050565b6000806000604084860312156125c9576125c8612252565b5b60006125d786828701612394565b935050602084013567ffffffffffffffff8111156125f8576125f7612257565b5b6126048682870161255a565b92509250509250925092565b600080fd5b600060c0828403121561262b5761262a612610565b5b81905092915050565b6000806000806000608086880312156126505761264f612252565b5b600061265e88828901612394565b955050602061266f88828901612394565b945050604086013567ffffffffffffffff8111156126905761268f612257565b5b61269c8882890161255a565b9350935050606086013567ffffffffffffffff8111156126bf576126be612257565b5b6126cb88828901612615565b9150509295509295909350565b6126e18161236b565b82525050565b60006020820190506126fc60008301846126d8565b92915050565b6000819050919050565b61271581612702565b82525050565b6000602082019050612730600083018461270c565b92915050565b61273f816122e1565b811461274a57600080fd5b50565b60008135905061275c81612736565b92915050565b60006020828403121561277857612777612252565b5b60006127868482850161274d565b91505092915050565b600061279a8261234b565b9050919050565b6127aa8161278f565b81146127b557600080fd5b50565b6000813590506127c7816127a1565b92915050565b600080604083850312156127e4576127e3612252565b5b60006127f2858286016127b8565b9250506020612803858286016123ed565b9150509250929050565b60006020828403121561282357612822612252565b5b6000612831848285016127b8565b91505092915050565b600082825260208201905092915050565b7f4272696467653a206d75737420656e646f77206e6f6e7a65726f000000000000600082015250565b6000612881601a8361283a565b915061288c8261284b565b602082019050919050565b600060208201905081810360008301526128b081612874565b9050919050565b7f4272696467653a20656d7074792076616c696461746f72207365740000000000600082015250565b60006128ed601b8361283a565b91506128f8826128b7565b602082019050919050565b6000602082019050818103600083015261291c816128e0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061295d82612317565b915061296883612317565b92508282019050808211156129805761297f612923565b5b92915050565b7f4272696467653a2073657420697320696e616374697665000000000000000000600082015250565b60006129bc60178361283a565b91506129c782612986565b602082019050919050565b600060208201905081810360008301526129eb816129af565b9050919050565b600082825260208201905092915050565b6000819050919050565b612a168161236b565b82525050565b6000612a288383612a0d565b60208301905092915050565b6000612a436020840184612394565b905092915050565b6000602082019050919050565b6000612a6483856129f2565b9350612a6f82612a03565b8060005b85811015612aa857612a858284612a34565b612a8f8882612a1c565b9750612a9a83612a4b565b925050600181019050612a73565b5085925050509392505050565b60006020820190508181036000830152612ad0818486612a58565b90509392505050565b7f4272696467653a2073657420697320686973746f726963000000000000000000600082015250565b6000612b0f60178361283a565b9150612b1a82612ad9565b602082019050919050565b60006020820190508181036000830152612b3e81612b02565b9050919050565b7f4272696467653a206f6e6c79206272696467652063616e2063616c6c00000000600082015250565b6000612b7b601c8361283a565b9150612b8682612b45565b602082019050919050565b60006020820190508181036000830152612baa81612b6e565b9050919050565b7f4272696467653a20736f75726365206d7573742062652070616c6c6574000000600082015250565b6000612be7601d8361283a565b9150612bf282612bb1565b602082019050919050565b60006020820190508181036000830152612c1681612bda565b9050919050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c6682612c1d565b810181811067ffffffffffffffff82111715612c8557612c84612c2e565b5b80604052505050565b6000612c98612248565b9050612ca48282612c5d565b919050565b600067ffffffffffffffff821115612cc457612cc3612c2e565b5b602082029050602081019050919050565b6000612ce8612ce384612ca9565b612c8e565b90508083825260208201905060208402830185811115612d0b57612d0a612439565b5b835b81811015612d345780612d208882612394565b845260208401935050602081019050612d0d565b5050509392505050565b600082601f830112612d5357612d5261242f565b5b8135612d63848260208601612cd5565b91505092915050565b60008060408385031215612d8357612d82612252565b5b600083013567ffffffffffffffff811115612da157612da0612257565b5b612dad85828601612d3e565b9250506020612dbe858286016124bb565b9150509250929050565b7f4272696467653a206d75737420737570706c7920627269646765206665650000600082015250565b6000612dfe601e8361283a565b9150612e0982612dc8565b602082019050919050565b60006020820190508181036000830152612e2d81612df1565b9050919050565b7f4272696467653a20656d707479206d6573736167650000000000000000000000600082015250565b6000612e6a60158361283a565b9150612e7582612e34565b602082019050919050565b60006020820190508181036000830152612e9981612e5d565b9050919050565b600060208284031215612eb657612eb5612252565b5b6000612ec4848285016124bb565b91505092915050565b600082825260208201905092915050565b82818337600083830152505050565b6000612ef98385612ecd565b9350612f06838584612ede565b612f0f83612c1d565b840190509392505050565b600060a082019050612f2f60008301896126d8565b612f3c60208301886126d8565b8181036040830152612f4f818688612eed565b9050612f5e6060830185612530565b612f6b6080830184612321565b979650505050505050565b60006020820190508181036000830152612f91818486612eed565b90509392505050565b6000604082019050612faf60008301866126d8565b8181036020830152612fc2818486612eed565b9050949350505050565b7f4272696467653a2070657263656e74206d757374206265203c3d203130300000600082015250565b6000613002601e8361283a565b915061300d82612fcc565b602082019050919050565b6000602082019050818103600083015261303181612ff5565b9050919050565b7f4272696467653a2062726964676520696e616374697665000000000000000000600082015250565b600061306e60178361283a565b915061307982613038565b602082019050919050565b6000602082019050818103600083015261309d81613061565b9050919050565b7f4272696467653a206d73672065786365656473206d6178206c656e6774680000600082015250565b60006130da601e8361283a565b91506130e5826130a4565b602082019050919050565b60006020820190508181036000830152613109816130cd565b9050919050565b7f4272696467653a20696e73756666696369656e74206d65737361676520666565600082015250565b600061314660208361283a565b915061315182613110565b602082019050919050565b6000602082019050818103600083015261317581613139565b9050919050565b600061318782612317565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036131b9576131b8612923565b5b600182019050919050565b600060a0820190506131d96000830189612321565b6131e660208301886126d8565b6131f360408301876126d8565b8181036060830152613206818587612eed565b90506132156080830184612321565b979650505050505050565b600061322b82612317565b915061323683612317565b925082820390508181111561324e5761324d612923565b5b92915050565b600081905092915050565b50565b600061326f600083613254565b915061327a8261325f565b600082019050919050565b600061329082613262565b9150819050919050565b7f4272696467653a204661696c656420746f2073656e64206d7367206665657300600082015250565b60006132d0601f8361283a565b91506132db8261329a565b602082019050919050565b600060208201905081810360008301526132ff816132c3565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061336260268361283a565b915061336d82613306565b604082019050919050565b6000602082019050818103600083015261339181613355565b9050919050565b7f4272696467653a206661696c656420746f2073656e6420457468657200000000600082015250565b60006133ce601c8361283a565b91506133d982613398565b602082019050919050565b600060208201905081810360008301526133fd816133c1565b9050919050565b6000819050919050565b600061342961342461341f8461234b565b613404565b61234b565b9050919050565b600061343b8261340e565b9050919050565b600061344d82613430565b9050919050565b61345d81613442565b82525050565b60006040820190506134786000830185613454565b6134856020830184612321565b9392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006134c260208361283a565b91506134cd8261348c565b602082019050919050565b600060208201905081810360008301526134f1816134b5565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061352e601f8361283a565b9150613539826134f8565b602082019050919050565b6000602082019050818103600083015261355d81613521565b9050919050565b7f4272696467653a2076616c696461746f7220736574206964207265706c61796560008201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b60006135c060218361283a565b91506135cb82613564565b604082019050919050565b600060208201905081810360008301526135ef816135b3565b9050919050565b600081519050919050565b6000819050602082019050919050565b6000602082019050919050565b6000613629826135f6565b61363381856129f2565b935061363e83613601565b8060005b8381101561366f5781516136568882612a1c565b975061366183613611565b925050600181019050613642565b5085935050505092915050565b60006020820190508181036000830152613696818461361e565b905092915050565b7f4272696467653a204661696c656420746f2073656e6420726577617264000000600082015250565b60006136d4601d8361283a565b91506136df8261369e565b602082019050919050565b60006020820190508181036000830152613703816136c7565b9050919050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126137365761373561370a565b5b80840192508235915067ffffffffffffffff8211156137585761375761370f565b5b60208301925060208202360383131561377457613773613714565b5b509250929050565b7f4272696467653a206576656e744964207265706c617965640000000000000000600082015250565b60006137b260188361283a565b91506137bd8261377c565b602082019050919050565b600060208201905081810360008301526137e1816137a5565b9050919050565b7f4272696467653a206675747572652076616c696461746f722073657400000000600082015250565b600061381e601c8361283a565b9150613829826137e8565b602082019050919050565b6000602082019050818103600083015261384d81613811565b9050919050565b600061385f82612494565b915061386a83612494565b9250828203905063ffffffff81111561388657613885612923565b5b92915050565b7f4272696467653a20657870697265642070726f6f660000000000000000000000600082015250565b60006138c260158361283a565b91506138cd8261388c565b602082019050919050565b600060208201905081810360008301526138f1816138b5565b9050919050565b7f4272696467653a20696e76616c69642076616c696461746f7220736574000000600082015250565b600061392e601d8361283a565b9150613939826138f8565b602082019050919050565b6000602082019050818103600083015261395d81613921565b9050919050565b7f4272696467653a20756e65787065637465642076616c696461746f722064696760008201527f6573740000000000000000000000000000000000000000000000000000000000602082015250565b60006139c060238361283a565b91506139cb82613964565b604082019050919050565b600060208201905081810360008301526139ef816139b3565b9050919050565b6000613a0182612317565b9150613a0c83612317565b9250828202613a1a81612317565b91508282048414831517613a3157613a30612923565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613a7282612317565b9150613a7d83612317565b925082613a8d57613a8c613a38565b5b828204905092915050565b60008083356001602003843603038112613ab557613ab461370a565b5b80840192508235915067ffffffffffffffff821115613ad757613ad661370f565b5b602083019250602082023603831315613af357613af2613714565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083356001602003843603038112613b4757613b4661370a565b5b80840192508235915067ffffffffffffffff821115613b6957613b6861370f565b5b602083019250602082023603831315613b8557613b84613714565b5b509250929050565b600060ff82169050919050565b613ba381613b8d565b8114613bae57600080fd5b50565b600081359050613bc081613b9a565b92915050565b600060208284031215613bdc57613bdb612252565b5b6000613bea84828501613bb1565b91505092915050565b7f4272696467653a207369676e617475726520696e76616c696400000000000000600082015250565b6000613c2960198361283a565b9150613c3482613bf3565b602082019050919050565b60006020820190508181036000830152613c5881613c1c565b9050919050565b7f4272696467653a206e6f7420656e6f756768207369676e617475726573000000600082015250565b6000613c95601d8361283a565b9150613ca082613c5f565b602082019050919050565b60006020820190508181036000830152613cc481613c88565b9050919050565b613cd481613b8d565b82525050565b6000608082019050613cef600083018761270c565b613cfc6020830186613ccb565b613d09604083018561270c565b613d16606083018461270c565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000613d8460188361283a565b9150613d8f82613d4e565b602082019050919050565b60006020820190508181036000830152613db381613d77565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000613df0601f8361283a565b9150613dfb82613dba565b602082019050919050565b60006020820190508181036000830152613e1f81613de3565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000613e8260228361283a565b9150613e8d82613e26565b604082019050919050565b60006020820190508181036000830152613eb181613e75565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000613f1460228361283a565b9150613f1f82613eb8565b604082019050919050565b60006020820190508181036000830152613f4381613f07565b905091905056fea2646970667358221220f9a8d1b86a248b8c1da50bc478fabe85896722e6801967a7060316a27baa54eb64736f6c63430008110033

Deployed Bytecode

0x6080604052600436106101f95760003560e01c80637755618b1161010d5780639c11bc30116100a0578063cfc16cea1161006f578063cfc16cea14610696578063d87500db146106c1578063f0bdb2d1146106fe578063f2fde38b14610727578063fa09e63014610750576101f9565b80639c11bc30146105fd578063acec338a14610626578063bb5ddb0f1461064f578063c6c0f59e1461066b576101f9565b80638da5cb5b116100dc5780638da5cb5b14610543578063960bfe041461056e578063996b2f9414610597578063998cdf83146105d4576101f9565b80637755618b146104a8578063823d2fc8146104d157806382b12dd7146104ed57806387b50acb14610518576101f9565b80634008b03f1161019057806361ab5a781161015f57806361ab5a78146103eb578063650bd364146104145780636a70fef21461043d578063715018a614610468578063728952f81461047f576101f9565b80634008b03f146103435780634acf77211461036c57806350dcb027146103955780635f7e9399146103c0576101f9565b80632c05f9a2116101cc5780632c05f9a21461029b5780632ee111ed146102c65780633301a464146102ef5780633ab578aa14610318576101f9565b806301ffc9a7146101fe57806302fb0c5e1461023b57806306e30dfc146102665780631d1d4e2914610270575b600080fd5b34801561020a57600080fd5b50610225600480360381019061022091906122b4565b610779565b60405161023291906122fc565b60405180910390f35b34801561024757600080fd5b5061025061085b565b60405161025d91906122fc565b60405180910390f35b61026e61086e565b005b34801561027c57600080fd5b506102856108e0565b6040516102929190612330565b60405180910390f35b3480156102a757600080fd5b506102b06108e6565b6040516102bd9190612330565b60405180910390f35b3480156102d257600080fd5b506102ed60048036038101906102e891906123a9565b6108ec565b005b3480156102fb57600080fd5b5061031660048036038101906103119190612402565b61097b565b005b34801561032457600080fd5b5061032d6109ba565b60405161033a9190612330565b60405180910390f35b34801561034f57600080fd5b5061036a600480360381019061036591906124d0565b6109c0565b005b34801561037857600080fd5b50610393600480360381019061038e91906124d0565b610b00565b005b3480156103a157600080fd5b506103aa610c55565b6040516103b79190612330565b60405180910390f35b3480156103cc57600080fd5b506103d5610c5f565b6040516103e2919061253f565b60405180910390f35b3480156103f757600080fd5b50610412600480360381019061040d9190612402565b610c75565b005b34801561042057600080fd5b5061043b600480360381019061043691906125b0565b610cb4565b005b34801561044957600080fd5b50610452610dd9565b60405161045f9190612330565b60405180910390f35b34801561047457600080fd5b5061047d610ddf565b005b34801561048b57600080fd5b506104a660048036038101906104a19190612402565b610df3565b005b3480156104b457600080fd5b506104cf60048036038101906104ca9190612402565b610e32565b005b6104eb60048036038101906104e69190612634565b610e71565b005b3480156104f957600080fd5b50610502611063565b60405161050f9190612330565b60405180910390f35b34801561052457600080fd5b5061052d611069565b60405161053a9190612330565b60405180910390f35b34801561054f57600080fd5b5061055861106f565b60405161056591906126e7565b60405180910390f35b34801561057a57600080fd5b5061059560048036038101906105909190612402565b611098565b005b3480156105a357600080fd5b506105be60048036038101906105b99190612402565b61111b565b6040516105cb919061271b565b60405180910390f35b3480156105e057600080fd5b506105fb60048036038101906105f69190612402565b611133565b005b34801561060957600080fd5b50610624600480360381019061061f9190612402565b611172565b005b34801561063257600080fd5b5061064d60048036038101906106489190612762565b6111b1565b005b610669600480360381019061066491906125b0565b611205565b005b34801561067757600080fd5b50610680611356565b60405161068d91906126e7565b60405180910390f35b3480156106a257600080fd5b506106ab61137c565b6040516106b89190612330565b60405180910390f35b3480156106cd57600080fd5b506106e860048036038101906106e39190612402565b611382565b6040516106f591906122fc565b60405180910390f35b34801561070a57600080fd5b50610725600480360381019061072091906127cd565b6113a2565b005b34801561073357600080fd5b5061074e600480360381019061074991906123a9565b6114b8565b005b34801561075c57600080fd5b506107776004803603810190610772919061280d565b61153b565b005b60007f69bc44e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061084457507f650bd364000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610854575061085382611632565b5b9050919050565b600960009054906101000a900460ff1681565b600034116108b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a890612897565b60405180910390fd5b347f840be946bba3df0d184eb7e6cd7c9e57bb380cf6078516c7441db5709d58509860405160405180910390a2565b600c5481565b600a5481565b6108f461169c565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f679cb5acfebd038830b61daadd5f2f74e2114862b1c289a5d2db82bc6eda32a660405160405180910390a250565b61098361169c565b80600a81905550807f11cff79cc5c082b5f775ae922a2a6dc80e9f79b9207767278bdf7391db5467f760405160405180910390a250565b60085481565b6109c861169c565b60008383905011610a0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0590612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff166008548263ffffffff16610a3b9190612952565b11610a7b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a72906129d2565b60405180910390fd5b60008383604051602001610a90929190612ab5565b60405160208183030381529060405280519060200120905080600260008463ffffffff168152602001908152602001600020819055508163ffffffff16817ff541dede932a20dba17286430555d7aa784b74222f2a34f107d40822f41992e360405160405180910390a350505050565b610b0861169c565b60008383905011610b4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4590612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168163ffffffff161015610baf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ba690612b25565b60405180910390fd5b60008383604051602001610bc4929190612ab5565b60405160208183030381529060405280519060200120905080600260008463ffffffff1681526020019081526020016000208190555081600360006101000a81548163ffffffff021916908363ffffffff1602179055508163ffffffff16817f36885d9a49d239da5379a6f8f9bb89273332a7e312cb5b8a2d3b0f567e8209f460405160405180910390a350505050565b6000600d54905090565b600360009054906101000a900463ffffffff1681565b610c7d61169c565b80600481905550807f06055c66c43187163b022b7d954ff32b4ba5265e175458d1b134cfe8ab72f41260405160405180910390a250565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d1990612b91565b60405180910390fd5b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610db2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da990612bfd565b60405180910390fd5b6000808383810190610dc49190612d6c565b91509150610dd2828261171a565b5050505050565b600e5481565b610de761169c565b610df16000611981565b565b610dfb61169c565b80600d81905550807fabd57ef278738881488128581f298faa35ba1bae2bbec9fb6e370ff60d531e4b60405160405180910390a250565b610e3a61169c565b80600881905550807f01116a77fa86522c55d40463f1b48825870a5d04ea15ca52a166d8ace7f355ff60405160405180910390a250565b60065434101580610ead57503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b610eec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ee390612e14565b60405180910390fd5b60008383905011610f32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f2990612e80565b60405180910390fd5b600085858585856020016020810190610f4b9190612ea0565b8660000135604051602001610f6596959493929190612f1a565b6040516020818303038152906040529050610f808183611a45565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1683600001357f3591658888eebc109961f7116a3e6aafbbeb08b55e727cf69c44d466a77a90d18787604051610fe4929190612f76565b60405180910390a48473ffffffffffffffffffffffffffffffffffffffff1663650bd3648786866040518463ffffffff1660e01b815260040161102993929190612f9a565b600060405180830381600087803b15801561104357600080fd5b505af1158015611057573d6000803e3d6000fd5b50505050505050505050565b60065481565b60045481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6110a061169c565b60648111156110e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110db90613018565b60405180910390fd5b80600781905550807fadfa8ecb21b6962ebcd0adbd9ab985b7b4c5b5eb3b0dead683171565c7bfe17160405160405180910390a250565b60026020528060005260406000206000915090505481565b61113b61169c565b80600681905550807f42dfb00d085d601e55327921154ae76c1b24270b026c5a0c51caee18eb4c401f60405160405180910390a250565b61117a61169c565b80600c81905550807f80e9dc023eeed9cbe4e886f225681c4fa94a046011c6269619c21befd6c4518160405160405180910390a250565b6111b961169c565b80600960006101000a81548160ff0219169083151502179055508015157fd06b0db8a7172c6c142c15cd90b6efb883b600b978dfca380621aa4c9f6d881560405160405180910390a250565b600960009054906101000a900460ff16611254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124b90613084565b60405180910390fd5b600c5482829050111561129c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611293906130f0565b60405180910390fd5b600d543410156112e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d89061315c565b60405180910390fd5b34600e60008282546112f39190612952565b925050819055507ff2a50cd57a795ad452a0b8586bcd3fe8e3ee00054c01c4712655d7753539dd356004600081548092919061132e9061317c565b919050553385858534604051611349969594939291906131c4565b60405180910390a1505050565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60075481565b60056020528060005260406000206000915054906101000a900460ff1681565b6113aa61169c565b80600e60008282546113bc9190613220565b9250508190555060008273ffffffffffffffffffffffffffffffffffffffff16826040516113e990613285565b60006040518083038185875af1925050503d8060008114611426576040519150601f19603f3d011682016040523d82523d6000602084013e61142b565b606091505b505090508061146f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611466906132e6565b60405180910390fd5b818373ffffffffffffffffffffffffffffffffffffffff167fcc89aff20f6022ea39ee28e42ebe0013f5e8a32d9388b49d2f6fe08563a54cdf60405160405180910390a3505050565b6114c061169c565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361152f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161152690613378565b60405180910390fd5b61153881611981565b50565b61154361169c565b600047905060008273ffffffffffffffffffffffffffffffffffffffff168260405161156e90613285565b60006040518083038185875af1925050503d80600081146115ab576040519150601f19603f3d011682016040523d82523d6000602084013e6115b0565b606091505b50509050806115f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115eb906133e4565b60405180910390fd5b7f06097061aeda806b5e9cb4133d9899f332ff0913956567fc0f7ea15e3d19947c8383604051611625929190613463565b60405180910390a1505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6116a4611f24565b73ffffffffffffffffffffffffffffffffffffffff166116c261106f565b73ffffffffffffffffffffffffffffffffffffffff1614611718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170f906134d8565b60405180910390fd5b565b60026001540361175f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175690613544565b60405180910390fd5b600260018190555060008251116117ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a290612903565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168163ffffffff161161180b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611802906135d6565b60405180910390fd5b60008260405160200161181e919061367c565b60405160208183030381529060405280519060200120905080600260008463ffffffff1681526020019081526020016000208190555081600360006101000a81548163ffffffff021916908363ffffffff1602179055506000611890600e54476118889190613220565b600a54611f2c565b905060003273ffffffffffffffffffffffffffffffffffffffff16826040516118b890613285565b60006040518083038185875af1925050503d80600081146118f5576040519150601f19603f3d011682016040523d82523d6000602084013e6118fa565b606091505b505090508061193e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611935906136ea565b60405180910390fd5b8363ffffffff1682847f3dab4e75c61b76a4152c289f3c93392ddab6386b2423ffab2cee4da9fbb05c7160405160405180910390a4505050600180819055505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000816000013590506000826020016020810190611a639190612ea0565b90506000838060a00190611a779190613719565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509050600960009054906101000a900460ff16611b08576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611aff90613084565b60405180910390fd5b6005600084815260200190815260200160002060009054906101000a900460ff1615611b69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b60906137c8565b60405180910390fd5b600360009054906101000a900463ffffffff1663ffffffff168263ffffffff161115611bca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc190613834565b60405180910390fd5b60085482600360009054906101000a900463ffffffff16611beb9190613854565b63ffffffff161115611c32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c29906138d8565b60405180910390fd5b6000815111611c76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c6d90613944565b60405180910390fd5b600260008363ffffffff1681526020019081526020016000205481604051602001611ca1919061367c565b6040516020818303038152906040528051906020012014611cf7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cee906139d6565b60405180910390fd5b600085805190602001209050600060646007548451611d1691906139f6565b611d209190613a67565b905060008060005b8551811015611ea95781898060600190611d429190613a98565b83818110611d5357611d52613afb565b5b9050602002013514611e9857611df9898060400190611d729190613b2a565b83818110611d8357611d82613afb565b5b9050602002016020810190611d989190613bc6565b8a8060600190611da89190613a98565b84818110611db957611db8613afb565b5b905060200201358b8060800190611dd09190613a98565b85818110611de157611de0613afb565b5b9050602002013588611f45909392919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff16868281518110611e2257611e21613afb565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1614611e80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7790613c3f565b60405180910390fd5b600183611e8d9190612952565b925083831015611ea9575b80611ea29061317c565b9050611d28565b5082821015611eed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ee490613cab565b60405180910390fd5b60016005600089815260200190815260200160002060006101000a81548160ff021916908315150217905550505050505050505050565b600033905090565b6000818310611f3b5781611f3d565b825b905092915050565b6000806000611f5687878787611f70565b91509150611f638161207c565b8192505050949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c1115611fab576000600391509150612073565b601b8560ff1614158015611fc35750601c8560ff1614155b15611fd5576000600491509150612073565b600060018787878760405160008152602001604052604051611ffa9493929190613cda565b6020604051602081039080840390855afa15801561201c573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361206a57600060019250925050612073565b80600092509250505b94509492505050565b600060048111156120905761208f613d1f565b5b8160048111156120a3576120a2613d1f565b5b031561224557600160048111156120bd576120bc613d1f565b5b8160048111156120d0576120cf613d1f565b5b03612110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210790613d9a565b60405180910390fd5b6002600481111561212457612123613d1f565b5b81600481111561213757612136613d1f565b5b03612177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161216e90613e06565b60405180910390fd5b6003600481111561218b5761218a613d1f565b5b81600481111561219e5761219d613d1f565b5b036121de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d590613e98565b60405180910390fd5b6004808111156121f1576121f0613d1f565b5b81600481111561220457612203613d1f565b5b03612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161223b90613f2a565b60405180910390fd5b5b50565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6122918161225c565b811461229c57600080fd5b50565b6000813590506122ae81612288565b92915050565b6000602082840312156122ca576122c9612252565b5b60006122d88482850161229f565b91505092915050565b60008115159050919050565b6122f6816122e1565b82525050565b600060208201905061231160008301846122ed565b92915050565b6000819050919050565b61232a81612317565b82525050565b60006020820190506123456000830184612321565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123768261234b565b9050919050565b6123868161236b565b811461239157600080fd5b50565b6000813590506123a38161237d565b92915050565b6000602082840312156123bf576123be612252565b5b60006123cd84828501612394565b91505092915050565b6123df81612317565b81146123ea57600080fd5b50565b6000813590506123fc816123d6565b92915050565b60006020828403121561241857612417612252565b5b6000612426848285016123ed565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126124545761245361242f565b5b8235905067ffffffffffffffff81111561247157612470612434565b5b60208301915083602082028301111561248d5761248c612439565b5b9250929050565b600063ffffffff82169050919050565b6124ad81612494565b81146124b857600080fd5b50565b6000813590506124ca816124a4565b92915050565b6000806000604084860312156124e9576124e8612252565b5b600084013567ffffffffffffffff81111561250757612506612257565b5b6125138682870161243e565b93509350506020612526868287016124bb565b9150509250925092565b61253981612494565b82525050565b60006020820190506125546000830184612530565b92915050565b60008083601f8401126125705761256f61242f565b5b8235905067ffffffffffffffff81111561258d5761258c612434565b5b6020830191508360018202830111156125a9576125a8612439565b5b9250929050565b6000806000604084860312156125c9576125c8612252565b5b60006125d786828701612394565b935050602084013567ffffffffffffffff8111156125f8576125f7612257565b5b6126048682870161255a565b92509250509250925092565b600080fd5b600060c0828403121561262b5761262a612610565b5b81905092915050565b6000806000806000608086880312156126505761264f612252565b5b600061265e88828901612394565b955050602061266f88828901612394565b945050604086013567ffffffffffffffff8111156126905761268f612257565b5b61269c8882890161255a565b9350935050606086013567ffffffffffffffff8111156126bf576126be612257565b5b6126cb88828901612615565b9150509295509295909350565b6126e18161236b565b82525050565b60006020820190506126fc60008301846126d8565b92915050565b6000819050919050565b61271581612702565b82525050565b6000602082019050612730600083018461270c565b92915050565b61273f816122e1565b811461274a57600080fd5b50565b60008135905061275c81612736565b92915050565b60006020828403121561277857612777612252565b5b60006127868482850161274d565b91505092915050565b600061279a8261234b565b9050919050565b6127aa8161278f565b81146127b557600080fd5b50565b6000813590506127c7816127a1565b92915050565b600080604083850312156127e4576127e3612252565b5b60006127f2858286016127b8565b9250506020612803858286016123ed565b9150509250929050565b60006020828403121561282357612822612252565b5b6000612831848285016127b8565b91505092915050565b600082825260208201905092915050565b7f4272696467653a206d75737420656e646f77206e6f6e7a65726f000000000000600082015250565b6000612881601a8361283a565b915061288c8261284b565b602082019050919050565b600060208201905081810360008301526128b081612874565b9050919050565b7f4272696467653a20656d7074792076616c696461746f72207365740000000000600082015250565b60006128ed601b8361283a565b91506128f8826128b7565b602082019050919050565b6000602082019050818103600083015261291c816128e0565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061295d82612317565b915061296883612317565b92508282019050808211156129805761297f612923565b5b92915050565b7f4272696467653a2073657420697320696e616374697665000000000000000000600082015250565b60006129bc60178361283a565b91506129c782612986565b602082019050919050565b600060208201905081810360008301526129eb816129af565b9050919050565b600082825260208201905092915050565b6000819050919050565b612a168161236b565b82525050565b6000612a288383612a0d565b60208301905092915050565b6000612a436020840184612394565b905092915050565b6000602082019050919050565b6000612a6483856129f2565b9350612a6f82612a03565b8060005b85811015612aa857612a858284612a34565b612a8f8882612a1c565b9750612a9a83612a4b565b925050600181019050612a73565b5085925050509392505050565b60006020820190508181036000830152612ad0818486612a58565b90509392505050565b7f4272696467653a2073657420697320686973746f726963000000000000000000600082015250565b6000612b0f60178361283a565b9150612b1a82612ad9565b602082019050919050565b60006020820190508181036000830152612b3e81612b02565b9050919050565b7f4272696467653a206f6e6c79206272696467652063616e2063616c6c00000000600082015250565b6000612b7b601c8361283a565b9150612b8682612b45565b602082019050919050565b60006020820190508181036000830152612baa81612b6e565b9050919050565b7f4272696467653a20736f75726365206d7573742062652070616c6c6574000000600082015250565b6000612be7601d8361283a565b9150612bf282612bb1565b602082019050919050565b60006020820190508181036000830152612c1681612bda565b9050919050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c6682612c1d565b810181811067ffffffffffffffff82111715612c8557612c84612c2e565b5b80604052505050565b6000612c98612248565b9050612ca48282612c5d565b919050565b600067ffffffffffffffff821115612cc457612cc3612c2e565b5b602082029050602081019050919050565b6000612ce8612ce384612ca9565b612c8e565b90508083825260208201905060208402830185811115612d0b57612d0a612439565b5b835b81811015612d345780612d208882612394565b845260208401935050602081019050612d0d565b5050509392505050565b600082601f830112612d5357612d5261242f565b5b8135612d63848260208601612cd5565b91505092915050565b60008060408385031215612d8357612d82612252565b5b600083013567ffffffffffffffff811115612da157612da0612257565b5b612dad85828601612d3e565b9250506020612dbe858286016124bb565b9150509250929050565b7f4272696467653a206d75737420737570706c7920627269646765206665650000600082015250565b6000612dfe601e8361283a565b9150612e0982612dc8565b602082019050919050565b60006020820190508181036000830152612e2d81612df1565b9050919050565b7f4272696467653a20656d707479206d6573736167650000000000000000000000600082015250565b6000612e6a60158361283a565b9150612e7582612e34565b602082019050919050565b60006020820190508181036000830152612e9981612e5d565b9050919050565b600060208284031215612eb657612eb5612252565b5b6000612ec4848285016124bb565b91505092915050565b600082825260208201905092915050565b82818337600083830152505050565b6000612ef98385612ecd565b9350612f06838584612ede565b612f0f83612c1d565b840190509392505050565b600060a082019050612f2f60008301896126d8565b612f3c60208301886126d8565b8181036040830152612f4f818688612eed565b9050612f5e6060830185612530565b612f6b6080830184612321565b979650505050505050565b60006020820190508181036000830152612f91818486612eed565b90509392505050565b6000604082019050612faf60008301866126d8565b8181036020830152612fc2818486612eed565b9050949350505050565b7f4272696467653a2070657263656e74206d757374206265203c3d203130300000600082015250565b6000613002601e8361283a565b915061300d82612fcc565b602082019050919050565b6000602082019050818103600083015261303181612ff5565b9050919050565b7f4272696467653a2062726964676520696e616374697665000000000000000000600082015250565b600061306e60178361283a565b915061307982613038565b602082019050919050565b6000602082019050818103600083015261309d81613061565b9050919050565b7f4272696467653a206d73672065786365656473206d6178206c656e6774680000600082015250565b60006130da601e8361283a565b91506130e5826130a4565b602082019050919050565b60006020820190508181036000830152613109816130cd565b9050919050565b7f4272696467653a20696e73756666696369656e74206d65737361676520666565600082015250565b600061314660208361283a565b915061315182613110565b602082019050919050565b6000602082019050818103600083015261317581613139565b9050919050565b600061318782612317565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036131b9576131b8612923565b5b600182019050919050565b600060a0820190506131d96000830189612321565b6131e660208301886126d8565b6131f360408301876126d8565b8181036060830152613206818587612eed565b90506132156080830184612321565b979650505050505050565b600061322b82612317565b915061323683612317565b925082820390508181111561324e5761324d612923565b5b92915050565b600081905092915050565b50565b600061326f600083613254565b915061327a8261325f565b600082019050919050565b600061329082613262565b9150819050919050565b7f4272696467653a204661696c656420746f2073656e64206d7367206665657300600082015250565b60006132d0601f8361283a565b91506132db8261329a565b602082019050919050565b600060208201905081810360008301526132ff816132c3565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061336260268361283a565b915061336d82613306565b604082019050919050565b6000602082019050818103600083015261339181613355565b9050919050565b7f4272696467653a206661696c656420746f2073656e6420457468657200000000600082015250565b60006133ce601c8361283a565b91506133d982613398565b602082019050919050565b600060208201905081810360008301526133fd816133c1565b9050919050565b6000819050919050565b600061342961342461341f8461234b565b613404565b61234b565b9050919050565b600061343b8261340e565b9050919050565b600061344d82613430565b9050919050565b61345d81613442565b82525050565b60006040820190506134786000830185613454565b6134856020830184612321565b9392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006134c260208361283a565b91506134cd8261348c565b602082019050919050565b600060208201905081810360008301526134f1816134b5565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b600061352e601f8361283a565b9150613539826134f8565b602082019050919050565b6000602082019050818103600083015261355d81613521565b9050919050565b7f4272696467653a2076616c696461746f7220736574206964207265706c61796560008201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b60006135c060218361283a565b91506135cb82613564565b604082019050919050565b600060208201905081810360008301526135ef816135b3565b9050919050565b600081519050919050565b6000819050602082019050919050565b6000602082019050919050565b6000613629826135f6565b61363381856129f2565b935061363e83613601565b8060005b8381101561366f5781516136568882612a1c565b975061366183613611565b925050600181019050613642565b5085935050505092915050565b60006020820190508181036000830152613696818461361e565b905092915050565b7f4272696467653a204661696c656420746f2073656e6420726577617264000000600082015250565b60006136d4601d8361283a565b91506136df8261369e565b602082019050919050565b60006020820190508181036000830152613703816136c7565b9050919050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126137365761373561370a565b5b80840192508235915067ffffffffffffffff8211156137585761375761370f565b5b60208301925060208202360383131561377457613773613714565b5b509250929050565b7f4272696467653a206576656e744964207265706c617965640000000000000000600082015250565b60006137b260188361283a565b91506137bd8261377c565b602082019050919050565b600060208201905081810360008301526137e1816137a5565b9050919050565b7f4272696467653a206675747572652076616c696461746f722073657400000000600082015250565b600061381e601c8361283a565b9150613829826137e8565b602082019050919050565b6000602082019050818103600083015261384d81613811565b9050919050565b600061385f82612494565b915061386a83612494565b9250828203905063ffffffff81111561388657613885612923565b5b92915050565b7f4272696467653a20657870697265642070726f6f660000000000000000000000600082015250565b60006138c260158361283a565b91506138cd8261388c565b602082019050919050565b600060208201905081810360008301526138f1816138b5565b9050919050565b7f4272696467653a20696e76616c69642076616c696461746f7220736574000000600082015250565b600061392e601d8361283a565b9150613939826138f8565b602082019050919050565b6000602082019050818103600083015261395d81613921565b9050919050565b7f4272696467653a20756e65787065637465642076616c696461746f722064696760008201527f6573740000000000000000000000000000000000000000000000000000000000602082015250565b60006139c060238361283a565b91506139cb82613964565b604082019050919050565b600060208201905081810360008301526139ef816139b3565b9050919050565b6000613a0182612317565b9150613a0c83612317565b9250828202613a1a81612317565b91508282048414831517613a3157613a30612923565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613a7282612317565b9150613a7d83612317565b925082613a8d57613a8c613a38565b5b828204905092915050565b60008083356001602003843603038112613ab557613ab461370a565b5b80840192508235915067ffffffffffffffff821115613ad757613ad661370f565b5b602083019250602082023603831315613af357613af2613714565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083356001602003843603038112613b4757613b4661370a565b5b80840192508235915067ffffffffffffffff821115613b6957613b6861370f565b5b602083019250602082023603831315613b8557613b84613714565b5b509250929050565b600060ff82169050919050565b613ba381613b8d565b8114613bae57600080fd5b50565b600081359050613bc081613b9a565b92915050565b600060208284031215613bdc57613bdb612252565b5b6000613bea84828501613bb1565b91505092915050565b7f4272696467653a207369676e617475726520696e76616c696400000000000000600082015250565b6000613c2960198361283a565b9150613c3482613bf3565b602082019050919050565b60006020820190508181036000830152613c5881613c1c565b9050919050565b7f4272696467653a206e6f7420656e6f756768207369676e617475726573000000600082015250565b6000613c95601d8361283a565b9150613ca082613c5f565b602082019050919050565b60006020820190508181036000830152613cc481613c88565b9050919050565b613cd481613b8d565b82525050565b6000608082019050613cef600083018761270c565b613cfc6020830186613ccb565b613d09604083018561270c565b613d16606083018461270c565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000613d8460188361283a565b9150613d8f82613d4e565b602082019050919050565b60006020820190508181036000830152613db381613d77565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000613df0601f8361283a565b9150613dfb82613dba565b602082019050919050565b60006020820190508181036000830152613e1f81613de3565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000613e8260228361283a565b9150613e8d82613e26565b604082019050919050565b60006020820190508181036000830152613eb181613e75565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000613f1460228361283a565b9150613f1f82613eb8565b604082019050919050565b60006020820190508181036000830152613f4381613f07565b905091905056fea2646970667358221220f9a8d1b86a248b8c1da50bc478fabe85896722e6801967a7060316a27baa54eb64736f6c63430008110033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.