Contract 0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d 1

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x3ca19a2ee7cdac9e1995b1c1cd1216901f5e5a5e7a575e965dbacdc8d0559dc5Submit256830612023-02-01 6:46:3727 secs ago0x281754ab58391a478b7aa4e7f39991cfb41118c4 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.005297175 25
0x76a08ba05429bf8dae35aa48a0df5d62ff4555e5d229e1164b12741c3e2a9885Submit256830332023-02-01 6:45:411 min ago0x501731c6a69803a53ec6c3e12f293c247ce1092b IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004676825 25
0x17ac5c6405e8232b63db180192001dc54e23e089ae92f77d1930dd328f868dfcSubmit256830312023-02-01 6:45:371 min ago0x8bf9661f1b247522c75dd0fe84355ad2eff27144 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.005297175 25
0xfe53301eabe2db12b60a4dd96004941122d04dd2ee5a62f331d45a475a1a8a1dSubmit256828922023-02-01 6:40:496 mins ago0x42e210b110c6aa49cdfa7cef1444aa4719653111 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.0043683 25
0x3c3f9f6d11337f9490464a547067f422954bcbd91f5731477d5998cd5a3228e7Submit256828412023-02-01 6:39:048 mins ago0x220230eda8f50067dd9e4729345dabcce0c61542 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.005297175 25
0x18a54ec400990931871c969058c5ebb872919524afab6d41f43cb38729ff455cSubmit256827442023-02-01 6:35:4911 mins ago0xcd733e06b06083d52fc5867e8e3432aa5c103a38 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004058875 25
0x58b62e4aaf500aa1a89541b8c1e9861b09d3928c8827bebd712e5be5768a42c9Submit256826882023-02-01 6:33:5713 mins ago0x93fdcab283b0bcac48157590af482e1cfd6af6ac IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.0043683 25
0x8b396dcaaf28be0940f7287f906b08fc9b401aa105d3ef43998b913481879761Submit256826452023-02-01 6:32:3014 mins ago0xd56c6a4f64e0bd70260472d1db6cf5825858cb0d IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.001100475 25
0x25775012cfaad08c7a05fb2e3474bb34b4fbf521e4c0500bd67b3a5d2d9d1a47Submit256826452023-02-01 6:32:3014 mins ago0xb9c63a350a04d8bd245d18928a26ee036352ddd8 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.00653495 25
0x759eddff7fcb2067df61f3c191b10ac63042ba90d52ad16d0a31bedd616dc7a0Submit256825892023-02-01 6:30:3816 mins ago0x2f85824b2b38f179e451988670935d315b5b9692 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004058575 25
0x80129dc2e3a60e333658b8251d03645696032319448ffad228e64e8d3e677b1dSubmit256825292023-02-01 6:28:3818 mins ago0x281754ab58391a478b7aa4e7f39991cfb41118c4 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.005297775 25
0x7b47c1c3b4247501aa2193e4bc78fe490bec1f6b3d5f75a37546246021cd6562Submit256825082023-02-01 6:27:5619 mins ago0x501731c6a69803a53ec6c3e12f293c247ce1092b IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004677425 25
0x079b9c92d4c1f1f4d9707290512b57053e9cc92299c12901bc93f8bf9e9198b5Submit256823852023-02-01 6:23:5023 mins ago0x42e210b110c6aa49cdfa7cef1444aa4719653111 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004678025 25
0x1421e5a33c424c79a93f3c8dba1cab4d49bb56688f73bc351e4090b72eb45471Submit256823312023-02-01 6:22:0225 mins ago0xe868be65c50b61e81a3fc5cb5a7916090b05eb2a IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004677125 25
0x929cf8454cf9b67ea1ecc52da4e054df5f1986320d141676f413356eeb73fd67Submit256822922023-02-01 6:20:4426 mins ago0x220230eda8f50067dd9e4729345dabcce0c61542 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.00498805 25
0xf62489995ad3ffcff7479cbe8b998e79263c8ec905ded3e7086500f77aeb6986Submit256822012023-02-01 6:17:4429 mins ago0x57f404ad75e371c1a539589c1efca12e0c6980ad IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.005296875 25
0x18e1a2fbd88f2475e28a5e92b772c725902a21d594b9ee8d97924ce2055c6cc3Submit256821652023-02-01 6:16:3230 mins ago0x93fdcab283b0bcac48157590af482e1cfd6af6ac IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.0043683 25
0x9f1d9022497487fce6f6ca291a1290fd67b7f5528d7e3dd36f4982af9eedbd4eSubmit256821002023-02-01 6:14:1932 mins ago0xb9c63a350a04d8bd245d18928a26ee036352ddd8 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.00746645 25
0x6e6112edcb8c3ee5331faf4cdb9f171c541c1f18ca9fd8fc6985a333be7dbbd7Submit256820652023-02-01 6:13:0933 mins ago0xd56c6a4f64e0bd70260472d1db6cf5825858cb0d IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004058875 25
0x44d92d113a3b35a4606cd262a958115db1ed7af1d9ebf580467e4504b0f15b92Submit256820352023-02-01 6:12:0934 mins ago0x2f85824b2b38f179e451988670935d315b5b9692 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004058575 25
0xf82095b682e27eb74128fedb3d74b27092418708f09df11e50b7ff052960c556Submit256819962023-02-01 6:10:5136 mins ago0x281754ab58391a478b7aa4e7f39991cfb41118c4 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.00746495 25
0x4e4ead5cf4d980139e609e0589594f0dc4d1a744724993f434971206267e4954Submit256819612023-02-01 6:09:4137 mins ago0x501731c6a69803a53ec6c3e12f293c247ce1092b IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004058275 25
0x134b20fc38c4cf71f231009dae9242399121340fa38a91a1d62ce8a5338e548bSubmit256818462023-02-01 6:05:4941 mins ago0x42e210b110c6aa49cdfa7cef1444aa4719653111 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004676825 25
0xe8268d3e6672f23bf42473843f17d3415fb28213c6e86dc39b1de8cf4243411bSubmit256818132023-02-01 6:04:4342 mins ago0xe868be65c50b61e81a3fc5cb5a7916090b05eb2a IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004676525 25
0xa81f125928507dd9484a88db7955cd9cf4ab3d23ee7a04d32f526c68142e735eSubmit256817532023-02-01 6:02:4344 mins ago0x220230eda8f50067dd9e4729345dabcce0c61542 IN  0x8d8675c9292bf61fa45f1ff3cb4b041f7487651d0 AVAX0.004675625 25
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ForeignChain

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 15 : ForeignChain.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "./Chain.sol";

/// @dev contract for foreign chains
contract ForeignChain is Chain {
    error NotSupported();

    /// @param _contractRegistry Registry address
    /// @param _padding required "space" between blocks in seconds
    /// @param _requiredSignatures number of required signatures for accepting consensus submission
    constructor(
        IRegistry _contractRegistry,
        uint32 _padding,
        uint16 _requiredSignatures,
        bool _allowForMixedType
    ) Chain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {
        // no additional configuration needed
    }

    /// @inheritdoc BaseChain
    function isForeign() external pure override returns (bool) {
        return true;
    }

    /// @inheritdoc Chain
    /// @notice this method is made to be compatible with MasterChain, but it does not return full data eg validators
    /// data will be missing.
    /// @return blockNumber `block.number`
    /// @return timePadding `this.padding`
    /// @return lastDataTimestamp timestamp for last submitted consensus
    /// @return lastId ID of last submitted consensus
    /// @return nextLeader will be always address(0)
    /// @return nextBlockId block ID for `block.timestamp + padding`
    /// @return validators array will be always empty
    /// @return powers array will be always empty
    /// @return locations array will be always empty
    /// @return staked total UMB staked by validators
    /// @return minSignatures `this.requiredSignatures`
    function getStatus() external view override returns(
        uint256 blockNumber,
        uint32 timePadding,
        uint32 lastDataTimestamp,
        uint32 lastId,
        address nextLeader,
        uint32 nextBlockId,
        address[] memory validators,
        uint256[] memory powers,
        string[] memory locations,
        uint256 staked,
        uint16 minSignatures
    ) {
        ConsensusData memory data = _consensusData;

        blockNumber = block.number;
        timePadding = data.padding;
        lastId = data.lastTimestamp;
        lastDataTimestamp = lastId;
        minSignatures = _REQUIRED_SIGNATURES;

        staked = stakingBank.totalSupply();
        uint256 numberOfValidators = 0;
        powers = new uint256[](numberOfValidators);
        validators = new address[](numberOfValidators);
        locations = new string[](numberOfValidators);
        nextLeader = address(0);

        unchecked {
            // we will not overflow with timestamp in a lifetime
            nextBlockId = lastId + data.padding + 1;
        }
    }

    function getLeaderIndex(uint256, uint256) public pure override returns (uint256) {
        revert NotSupported();
    }

    function getLeaderAddressAtTime(uint256) public pure override returns (address) {
        revert NotSupported();
    }
}

File 2 of 15 : Chain.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "./BaseChain.sol";

contract Chain is BaseChain {
    IStakingBank public immutable stakingBank;

    event LogMint(address indexed minter, uint256 blockId, uint256 staked, uint256 power);
    event LogVoter(uint256 indexed blockId, address indexed voter, uint256 vote);

    error NotEnoughSignatures();
    error SignaturesOutOfOrder();

    /// @param _contractRegistry Registry address
    /// @param _padding required "space" between blocks in seconds
    /// @param _requiredSignatures number of required signatures for accepting consensus submission
    /// @param _allowForMixedType we have two "types" of Chain: HomeChain and ForeignChain, when we redeploying
    /// we don't want to mix up them, so we checking, if new Chain has the same type as current one.
    /// However, when we will be switching from one homechain to another one, we have to allow for this mixing up.
    /// This flag will tell contract, if this is the case.
    constructor(
        IRegistry _contractRegistry,
        uint32 _padding,
        uint16 _requiredSignatures,
        bool _allowForMixedType
    ) BaseChain(_contractRegistry, _padding, _requiredSignatures, _allowForMixedType) {
        stakingBank = IStakingBank(_contractRegistry.requireAndGetAddress("StakingBank"));
    }

    /// @dev method for submitting consensus data
    /// @param _dataTimestamp consensus timestamp, this is time for all data in merkle tree including FCDs
    /// @param _root merkle root
    /// @param _keys FCDs keys
    /// @param _values FCDs values
    /// @param _v array of `v` part of validators signatures
    /// @param _r array of `r` part of validators signatures
    /// @param _s array of `s` part of validators signatures
    // solhint-disable-next-line function-max-lines, code-complexity
    function submit(
        uint32 _dataTimestamp,
        bytes32 _root,
        bytes32[] memory _keys,
        uint256[] memory _values,
        uint8[] memory _v,
        bytes32[] memory _r,
        bytes32[] memory _s
    ) external {
        // below two checks are only for pretty errors, so we can safe gas and allow for raw revert
        // if (_keys.length != _values.length) revert ArraysDataDoNotMatch();
        // if (_v.length != _r.length || _r.length != _s.length) revert ArraysDataDoNotMatch();

        _verifySubmitTimestampAndIncSequence(_dataTimestamp);

        // we can't expect minter will have exactly the same timestamp
        // but for sure we can demand not to be off by a lot, that's why +3sec
        // temporary remove this condition, because recently on ropsten we see cases when minter/node
        // can be even 100sec behind
        // require(_dataTimestamp <= block.timestamp + 3,
        //   string(abi.encodePacked("oh, so you can predict the future:", _dataTimestamp - block.timestamp + 48)));

        bytes memory testimony = abi.encodePacked(_dataTimestamp, _root);

        for (uint256 i = 0; i < _keys.length;) {
            if (uint224(_values[i]) != _values[i]) revert FCDOverflow();

            fcds[_keys[i]] = FirstClassData(uint224(_values[i]), _dataTimestamp);
            testimony = abi.encodePacked(testimony, _keys[i], _values[i]);

            unchecked {
                // we can't pass enough data to overflow
                i++;
            }
        }

        uint256 signatures = 0;
        uint256 power = 0;
        //uint256 staked = stakingBank.totalSupply();
        bytes32 affidavit = keccak256(testimony);

        address prevSigner = address(0x0);

        for (uint256 i; i < _v.length;) {
            address signer = recoverSigner(affidavit, _v[i], _r[i], _s[i]);
            uint256 balance = stakingBank.balanceOf(signer);

            if (prevSigner >= signer) revert SignaturesOutOfOrder();

            prevSigner = signer;

            if (balance == 0) {
                unchecked { i++; }
                continue;
            }

            signatures++;
            emit LogVoter(uint256(_dataTimestamp), signer, balance);

            unchecked {
                // we can't overflow because that means token overflowed
                // and even if we do, we will get lower power
                power += balance;
                i++;
            }
        }

        if (signatures < _REQUIRED_SIGNATURES) revert NotEnoughSignatures();

        emit LogMint(msg.sender, _dataTimestamp, stakingBank.totalSupply(), power);

        // TODO remember to protect against flash loans when DPoS will be in place
        // we turn on power once we have DPoS in action, we have PoA now
        // require(power * 100 / staked >= 66, "not enough power was gathered");

        roots[_dataTimestamp] = _root;
        _consensusData.lastTimestamp = _dataTimestamp;
    }

    /// @inheritdoc BaseChain
    function isForeign() external pure virtual override returns (bool) {
        return false;
    }

    /// @dev helper method that returns all important data about current state of contract
    /// @return blockNumber `block.number`
    /// @return timePadding `this.padding`
    /// @return lastDataTimestamp timestamp for last submitted consensus
    /// @return lastId ID of last submitted consensus
    /// @return nextLeader leader for `block.timestamp + 1`
    /// @return nextBlockId block ID for `block.timestamp + padding`
    /// @return validators array of all validators addresses
    /// @return powers array of all validators powers
    /// @return locations array of all validators locations
    /// @return staked total UMB staked by validators
    /// @return minSignatures `this.requiredSignatures`
    function getStatus() external view virtual returns(
        uint256 blockNumber,
        uint32 timePadding,
        uint32 lastDataTimestamp,
        uint32 lastId,
        address nextLeader,
        uint32 nextBlockId,
        address[] memory validators,
        uint256[] memory powers,
        string[] memory locations,
        uint256 staked,
        uint16 minSignatures
    ) {
        ConsensusData memory data = _consensusData;

        blockNumber = block.number;
        timePadding = data.padding;
        lastId = data.lastTimestamp;
        lastDataTimestamp = lastId;
        minSignatures = _REQUIRED_SIGNATURES;

        staked = stakingBank.totalSupply();
        uint256 numberOfValidators = stakingBank.getNumberOfValidators();
        powers = new uint256[](numberOfValidators);
        validators = new address[](numberOfValidators);
        locations = new string[](numberOfValidators);

        for (uint256 i = 0; i < numberOfValidators;) {
            validators[i] = stakingBank.addresses(i);
            (, locations[i]) = stakingBank.validators(validators[i]);
            powers[i] = stakingBank.balanceOf(validators[i]);

            unchecked {
                // we will run out of gas before overflow happen
                i++;
            }
        }

        unchecked {
            // we will not overflow with timestamp in a lifetime
            nextBlockId = lastId + data.padding + 1;

            nextLeader = numberOfValidators > 0
                // we will not overflow with timestamp in a lifetime
                ? validators[getLeaderIndex(numberOfValidators, block.timestamp + 1)]
                : address(0);
        }
    }

    /// @return address of leader for next second
    function getNextLeaderAddress() external view returns (address) {
        return getLeaderAddressAtTime(block.timestamp + 1);
    }

    /// @return address of current leader
    function getLeaderAddress() external view returns (address) {
        return getLeaderAddressAtTime(block.timestamp);
    }

    /// @param _numberOfValidators total number of validators
    /// @param _timestamp timestamp for which you want to calculate index
    /// @return leader index, use it for StakingBank.addresses[index] to fetch leader address
    function getLeaderIndex(uint256 _numberOfValidators, uint256 _timestamp) public view virtual returns (uint256) {
        ConsensusData memory data = _consensusData;

        unchecked {
            // we will not overflow on `timestamp` and `padding` in a life time
            // timePadding + 1 => because padding is a space between blocks,
            // so next round starts on first block after padding
            // TODO will it work for off-chain??
            uint256 validatorIndex = data.sequence + (_timestamp - data.lastTimestamp) / (data.padding + 1);

            return validatorIndex % _numberOfValidators;
        }
    }

    // @todo - properly handled non-enabled validators, newly added validators, and validators with low stake
    /// @param _timestamp timestamp for which you want to calculate leader address
    /// @return leader address for provider timestamp
    function getLeaderAddressAtTime(uint256 _timestamp) public view virtual returns (address) {
        uint256 numberOfValidators = stakingBank.getNumberOfValidators();

        if (numberOfValidators == 0) {
            return address(0x0);
        }

        uint256 validatorIndex = getLeaderIndex(numberOfValidators, _timestamp);

        return stakingBank.addresses(validatorIndex);
    }

    /// @dev we had stack too deep in `submit` so this method was created as a solution
    // we increasing `_consensusData.sequence` here so we don't have to read sequence again in other place
    function _verifySubmitTimestampAndIncSequence(uint256 _dataTimestamp) internal {
        ConsensusData memory data = _consensusData;

        // `data.lastTimestamp` must be setup either on deployment
        // or via cloning from previous contract
        if (data.lastTimestamp == 0) revert ContractNotReady();

        unchecked {
            // we will not overflow with timestamp and padding in a life time
            if (data.lastTimestamp + data.padding >= _dataTimestamp) revert BlockSubmittedToFastOrDataToOld();
        }

        unchecked {
            // we will not overflow in a life time
            _consensusData.sequence = uint32(data.sequence + 1);
        }
    }
}

File 3 of 15 : BaseChain.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@umb-network/toolbox/dist/contracts/lib/ValueDecoder.sol";

import "./interfaces/IBaseChainV1.sol";
import "./interfaces/IStakingBank.sol";
import "./extensions/Registrable.sol";
import "./Registry.sol";

abstract contract BaseChain is Registrable, Ownable {
    using ValueDecoder for bytes;
    using ValueDecoder for uint224;
    using MerkleProof for bytes32[];

    /// @param root merkle root for consensus
    /// @param dataTimestamp consensus timestamp
    struct Block {
        bytes32 root;
        uint32 dataTimestamp;
    }

    /// @param value FCD value
    /// @param dataTimestamp FCD timestamp
    struct FirstClassData {
        uint224 value;
        uint32 dataTimestamp;
    }

    /// @param blocksCountOffset number of all blocks that were generated before switching to this contract
    /// @param sequence is a total number of blocks (consensus rounds) including previous contracts
    /// @param lastTimestamp is a timestamp of last submitted block
    /// @param padding number of seconds that need to pass before new submit will be possible
    /// @param deprecated flag that changes to TRUE on `unregister`, when TRUE submissions are not longer available
    struct ConsensusData {
        uint32 blocksCountOffset;
        uint32 sequence;
        uint32 lastTimestamp;
        uint32 padding;
        bool deprecated;
    }

    uint256 constant public VERSION = 2;

    bool internal immutable _ALLOW_FOR_MIXED_TYPE; // solhint-disable-line var-name-mixedcase

    bytes4 constant private _VERSION_SELECTOR = bytes4(keccak256("VERSION()"));

    /// @dev minimal number of signatures required for accepting submission (PoA)
    uint16 internal immutable _REQUIRED_SIGNATURES; // solhint-disable-line var-name-mixedcase

    ConsensusData internal _consensusData;

    bytes constant public ETH_PREFIX = "\x19Ethereum Signed Message:\n32";

    /// @dev block id (consensus ID) => root
    /// consensus ID is at the same time consensus timestamp
    mapping(uint256 => bytes32) public roots;

    /// @dev FCD key => FCD data
    mapping(bytes32 => FirstClassData) public fcds;

    event LogDeprecation(address indexed deprecator);
    event LogPadding(address indexed executor, uint32 timePadding);

    error ArraysDataDoNotMatch();
    error AlreadyDeprecated();
    error AlreadyRegistered();
    error BlockSubmittedToFastOrDataToOld();
    error ContractNotReady();
    error FCDOverflow();
    error InvalidContractType();
    error NoChangeToState();
    error OnlyOwnerOrRegistry();
    error UnregisterFirst();

    modifier onlyOwnerOrRegistry () {
        if (msg.sender != address(contractRegistry) && msg.sender != owner()) revert OnlyOwnerOrRegistry();
        _;
    }

    /// @param _contractRegistry Registry address
    /// @param _padding required "space" between blocks in seconds
    /// @param _requiredSignatures number of required signatures for accepting consensus submission
    constructor(
        IRegistry _contractRegistry,
        uint32 _padding,
        uint16 _requiredSignatures,
        bool _allowForMixedType
    ) Registrable(_contractRegistry) {
        _ALLOW_FOR_MIXED_TYPE = _allowForMixedType;
        _REQUIRED_SIGNATURES = _requiredSignatures;

        _setPadding(_padding);

        BaseChain oldChain = BaseChain(_contractRegistry.getAddress("Chain"));

        if (address(oldChain) == address(0)) {
            // if this is first contract in sidechain, then we need to initialise lastTimestamp so submission
            // can be possible
            _consensusData.lastTimestamp = uint32(block.timestamp) - _padding - 1;
        }
    }

    /// @dev setter for `padding`
    function setPadding(uint16 _padding) external {
        _setPadding(_padding);
    }

    /// @notice if this method needs to be called manually (not from Registry)
    /// it is important to do it as part of tx batch
    /// eg using multisig, we should prepare set of transactions and confirm them all at once
    /// @inheritdoc Registrable
    function register() external override onlyOwnerOrRegistry {
        address oldChain = contractRegistry.getAddress("Chain");

        // registration must be done before address in registry is replaced
        if (oldChain == address(this)) revert AlreadyRegistered();

        if (oldChain == address(0x0)) {
            return;
        }

        _cloneLastDataFromPrevChain(oldChain);
    }

    /// @inheritdoc Registrable
    function unregister() external override onlyOwnerOrRegistry {
        // in case we deprecated contract manually, we simply return
        if (_consensusData.deprecated) return;

        address newChain = contractRegistry.getAddress("Chain");
        // unregistering must be done after address in registry is replaced
        if (newChain == address(this)) revert UnregisterFirst();

        // TODO:
        // I think we need to remove restriction for type (at least once)
        // when we will switch to multichain architecture

        if (!_ALLOW_FOR_MIXED_TYPE) {
            // can not be replaced with chain of different type
            if (BaseChain(newChain).isForeign() != this.isForeign()) revert InvalidContractType();
        }

        _consensusData.deprecated = true;
        emit LogDeprecation(msg.sender);
    }

    /// @notice it allows to deprecate contract manually
    /// Only new Registry calls `unregister()` where we set deprecated to true
    /// In old Registries we don't have this feature, so in order to safely redeploy new Chain
    /// we will have to first deprecate current contract manually, then register new contract
    function deprecate() external onlyOwnerOrRegistry {
        if (_consensusData.deprecated) revert AlreadyDeprecated();

        _consensusData.deprecated = true;
        emit LogDeprecation(msg.sender);
    }

    /// @dev getter for `_consensusData`
    function getConsensusData() external view returns (ConsensusData memory) {
        return _consensusData;
    }

    /// @dev number of blocks (consensus rounds) saved in this contract
    function blocksCount() external view returns (uint256) {
        return _consensusData.sequence - _consensusData.blocksCountOffset;
    }

    function blocksCountOffset() external view returns (uint32) {
        return _consensusData.blocksCountOffset;
    }

    function lastBlockId() external view returns (uint256) {
        return _consensusData.lastTimestamp;
    }

    /// @return TRUE if contract is ForeignChain, FALSE otherwise
    function isForeign() external pure virtual returns (bool);

    /// @inheritdoc Registrable
    function getName() external pure override returns (bytes32) {
        return "Chain";
    }

    /// @param _affidavit root and FCDs hashed together
    /// @param _v part of signature
    /// @param _r part of signature
    /// @param _s part of signature
    /// @return signer address
    function recoverSigner(bytes32 _affidavit, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {
        bytes32 hash = keccak256(abi.encodePacked(ETH_PREFIX, _affidavit));
        return ecrecover(hash, _v, _r, _s);
    }

    /// @param _blockId ID of submitted block
    /// @return block data (root + timestamp)
    function blocks(uint256 _blockId) external view returns (Block memory) {
        return Block(roots[_blockId], uint32(_blockId));
    }

    /// @return current block ID
    /// please note, that current ID is not the same as last ID, current means that once padding pass,
    /// ID will switch to next one and it will be pointing to empty submit until submit for that ID is done
    function getBlockId() external view returns (uint32) {
        if (_consensusData.lastTimestamp == 0) return 0;

        return getBlockIdAtTimestamp(block.timestamp);
    }

    function requiredSignatures() external view returns (uint16) {
        return _REQUIRED_SIGNATURES;
    }

    /// @dev calculates block ID for provided timestamp
    /// this function does not works for past timestamps
    /// @param _timestamp current or future timestamp
    /// @return block ID for provided timestamp
    function getBlockIdAtTimestamp(uint256 _timestamp) virtual public view returns (uint32) {
        ConsensusData memory data = _consensusData;

        unchecked {
            // we can't overflow because we adding two `uint32`
            if (data.lastTimestamp + data.padding < _timestamp) {
                return uint32(_timestamp);
            }
        }

        return data.lastTimestamp;
    }

    /// @return last submitted block ID, please note, that on deployment, when there is no submission for this contract
    /// block for last ID will be available in previous contract
    function getLatestBlockId() virtual public view returns (uint32) {
        return _consensusData.lastTimestamp;
    }

    /// @dev verifies if the leaf is valid leaf for merkle tree
    /// @param _proof merkle proof for merkle tree
    /// @param _root merkle root
    /// @param _leaf leaf hash
    /// @return TRUE if `_leaf` is valid, FALSE otherwise
    function verifyProof(bytes32[] memory _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
        if (_root == bytes32(0)) {
            return false;
        }

        return _proof.verify(_root, _leaf);
    }

    /// @dev creates leaf hash, that has is used in merkle tree
    /// @param _key key under which we store the value
    /// @param _value value itself as bytes
    /// @return leaf hash
    function hashLeaf(bytes memory _key, bytes memory _value) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(_key, _value));
    }

    /// @dev verifies, if provided key-value pair was part of consensus
    /// @param _blockId consensus ID for which we doing a check
    /// @param _proof merkle proof for pair
    /// @param _key pair key
    /// @param _value pair value
    /// @return TRUE if key-value par was part of consensus, FALSE otherwise
    function verifyProofForBlock(
        uint256 _blockId,
        bytes32[] memory _proof,
        bytes memory _key,
        bytes memory _value
    )
        public
        view
        returns (bool)
    {
        return _proof.verify(roots[_blockId], keccak256(abi.encodePacked(_key, _value)));
    }

    /// @dev this is helper method, that extracts one merkle proof from many hashed provided as bytes
    /// @param _data many hashes as bytes
    /// @param _offset this is starting point for extraction
    /// @param _items how many hashes to extract
    /// @return merkle proof (array of bytes32 hashes)
    function bytesToBytes32Array(
        bytes memory _data,
        uint256 _offset,
        uint256 _items
    )
        public
        pure
        returns (bytes32[] memory)
    {
        bytes32[] memory dataList = new bytes32[](_items);

        // we can unchecked because we working only with `i` and `_offset`
        // in case of wrong `_offset` it will throw
        unchecked {
            for (uint256 i = 0; i < _items; i++) {
                bytes32 temp;
                uint256 idx = (i + 1 + _offset) * 32;

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    temp := mload(add(_data, idx))
                }

                dataList[i] = temp;
            }
        }

        return (dataList);
    }

    /// @dev batch method for data verification
    /// @param _blockIds consensus IDs for which we doing a checks
    /// @param _proofs merkle proofs for all pair, sequence of hashes provided as bytes
    /// @param _proofItemsCounter array of counters, each counter tells how many hashes proof for each leaf has
    /// @param _leaves array of merkle leaves
    /// @return results array of verification results, TRUE if leaf is part of consensus, FALSE otherwise
    function verifyProofs(
        uint32[] memory _blockIds,
        bytes memory _proofs,
        uint256[] memory _proofItemsCounter,
        bytes32[] memory _leaves
    )
        public
        view
        returns (bool[] memory results)
    {
        results = new bool[](_leaves.length);
        uint256 offset = 0;

        for (uint256 i = 0; i < _leaves.length;) {
            results[i] = bytesToBytes32Array(_proofs, offset, _proofItemsCounter[i]).verify(
                roots[_blockIds[i]], _leaves[i]
            );

            unchecked {
                // we can uncheck because it will not overflow in a lifetime, and if someone provide invalid counter
                // we verification will not be valid (or we throw because of invalid memory access)
                offset += _proofItemsCounter[i];
                // we can uncheck because `i` will not overflow in a lifetime
                i++;
            }
        }
    }

    /// @param _blockId consensus ID
    /// @return root for provided consensus ID
    function getBlockRoot(uint32 _blockId) external view returns (bytes32) {
        return roots[_blockId];
    }

    /// @param _blockId consensus ID
    /// @return timestamp for provided consensus ID
    function getBlockTimestamp(uint32 _blockId) external view returns (uint32) {
        return roots[_blockId] == bytes32(0) ? 0 : _blockId;
    }

    /// @dev batch getter for FCDs
    /// @param _keys FCDs keys to fetch
    /// @return values array of FCDs values
    /// @return timestamps array of FCDs timestamps
    function getCurrentValues(bytes32[] calldata _keys)
        external
        view
        returns (uint256[] memory values, uint32[] memory timestamps)
    {
        timestamps = new uint32[](_keys.length);
        values = new uint256[](_keys.length);

        for (uint i=0; i<_keys.length;) {
            FirstClassData storage numericFCD = fcds[_keys[i]];
            values[i] = uint256(numericFCD.value);
            timestamps[i] = numericFCD.dataTimestamp;

            unchecked {
                // we can uncheck because `i` will not overflow in a lifetime
                i++;
            }
        }
    }

    /// @dev getter for single FCD value
    /// @param _key FCD key
    /// @return value FCD value
    /// @return timestamp FCD timestamp
    function getCurrentValue(bytes32 _key) external view returns (uint256 value, uint256 timestamp) {
        FirstClassData storage numericFCD = fcds[_key];
        return (uint256(numericFCD.value), numericFCD.dataTimestamp);
    }

    /// @dev getter for single FCD value in case its type is `int`
    /// @param _key FCD key
    /// @return value FCD value
    /// @return timestamp FCD timestamp
    function getCurrentIntValue(bytes32 _key) external view returns (int256 value, uint256 timestamp) {
        FirstClassData storage numericFCD = fcds[_key];
        return (numericFCD.value.toInt(), numericFCD.dataTimestamp);
    }

    function _setPadding(uint32 _padding) internal onlyOwner {
        if (_consensusData.padding == _padding) revert NoChangeToState();

        _consensusData.padding = _padding;
        emit LogPadding(msg.sender, _padding);
    }

    /// @dev we cloning last block time, because we will need reference point for next submissions
    function _cloneLastDataFromPrevChain(address _prevChain) internal {
        (bool success, bytes memory v) = _prevChain.staticcall(abi.encode(_VERSION_SELECTOR));
        uint256 prevVersion = success ? abi.decode(v, (uint256)) : 1;

        if (prevVersion == 1) {
            uint32 latestId = IBaseChainV1(address(_prevChain)).getLatestBlockId();
            _consensusData.lastTimestamp = IBaseChainV1(address(_prevChain)).getBlockTimestamp(latestId);

            // +1 because getLatestBlockId subtracts 1
            // +1 because it might be situation when tx is already in progress in old contract
            // and old contract do not have deprecated flag
            _consensusData.sequence = latestId + 2;
            _consensusData.blocksCountOffset = latestId + 2;
        } else { // VERSION 2
            // with new Registry, we have register/unregister methods
            // Chain will be deprecated, so there is no need to do "+1" as in old version
            // TODO what with current Registries??
            // we need a way to make it deprecated!
            ConsensusData memory data = BaseChain(_prevChain).getConsensusData();

            _consensusData.sequence = data.sequence;
            _consensusData.blocksCountOffset = data.sequence;
            _consensusData.lastTimestamp = data.lastTimestamp;
        }
    }
}

File 4 of 15 : Registry.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

// Inheritance
import "@openzeppelin/contracts/access/Ownable.sol";

import "./extensions/Registrable.sol";
import "./interfaces/IRegistry.sol";

/// @dev contracts registry
/// protocol uses this registry to fetch current contract addresses
contract Registry is IRegistry, Ownable {
    /// name => contract address
    mapping(bytes32 => address) public registry;


    error NameNotRegistered();
    error ArraysDataDoNotMatch();

    /// @inheritdoc IRegistry
    function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external onlyOwner {
        if (_names.length != _destinations.length) revert ArraysDataDoNotMatch();

        for (uint i = 0; i < _names.length;) {
            registry[_names[i]] = _destinations[i];
            emit LogRegistered(_destinations[i], _names[i]);

            unchecked {
                i++;
            }
        }
    }

    /// @inheritdoc IRegistry
    function importContracts(address[] calldata _destinations) external onlyOwner {
        for (uint i = 0; i < _destinations.length;) {
            bytes32 name = Registrable(_destinations[i]).getName();
            registry[name] = _destinations[i];
            emit LogRegistered(_destinations[i], name);

            unchecked {
                i++;
            }
        }
    }

    /// @inheritdoc IRegistry
    function atomicUpdate(address _newContract) external onlyOwner {
        Registrable(_newContract).register();

        bytes32 name = Registrable(_newContract).getName();
        address oldContract = registry[name];
        registry[name] = _newContract;

        Registrable(oldContract).unregister();

        emit LogRegistered(_newContract, name);
    }

    /// @inheritdoc IRegistry
    function requireAndGetAddress(bytes32 name) external view returns (address) {
        address _foundAddress = registry[name];
        if (_foundAddress == address(0)) revert NameNotRegistered();

        return _foundAddress;
    }

    /// @inheritdoc IRegistry
    function getAddress(bytes32 _bytes) external view returns (address) {
        return registry[_bytes];
    }

    /// @inheritdoc IRegistry
    function getAddressByString(string memory _name) public view returns (address) {
        return registry[stringToBytes32(_name)];
    }

    /// @inheritdoc IRegistry
    function stringToBytes32(string memory _string) public pure returns (bytes32 result) {
        bytes memory tempEmptyStringTest = bytes(_string);

        if (tempEmptyStringTest.length == 0) {
            return 0x0;
        }

        // solhint-disable-next-line no-inline-assembly
        assembly {
            result := mload(add(_string, 32))
        }
    }
}

File 5 of 15 : IBaseChainV1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IBaseChainV1 {
    /// @dev number of blocks (consensus rounds) saved in this contract
    function blocksCount() external returns (uint32);

    /// @dev number of all blocks that were generated before switching to this contract
    /// please note, that there might be a gap of one block when we switching from old to new contract
    /// see constructor for details
    function blocksCountOffset() external returns (uint32);

    function getLatestBlockId() external view returns (uint32);

    function getBlockTimestamp(uint32 _blockId) external view returns (uint32);

    function getStatus() external view returns (
        uint256 blockNumber,
        uint16 timePadding,
        uint32 lastDataTimestamp,
        uint32 lastId,
        uint32 nextBlockId
    );
}

File 6 of 15 : IStakingBank.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IStakingBank is IERC20 {
    /// @param id address of validator wallet
    /// @param location URL of the validator API
    struct Validator {
        address id;
        string location;
    }

    event LogValidatorRegistered(address indexed id);
    event LogValidatorUpdated(address indexed id);
    event LogValidatorRemoved(address indexed id);
    event LogMinAmountForStake(uint256 minAmountForStake);

    /// @dev setter for `minAmountForStake`
    function setMinAmountForStake(uint256 _minAmountForStake) external;

    /// @dev allows to stake `token` by validators
    /// Validator needs to approve StakingBank beforehand
    /// @param _value amount of tokens to stake
    function stake(uint256 _value) external;

    /// @dev notification about approval from `_from` address on UMB token
    /// Staking bank will stake max approved amount from `_from` address
    /// @param _from address which approved token spend for IStakingBank
    function receiveApproval(address _from) external returns (bool success);

    /// @dev withdraws stake tokens
    /// it throws, when balance will be less than required minimum for stake
    /// to withdraw all use `exit`
    function withdraw(uint256 _value) external returns (bool success);

    /// @dev unstake and withdraw all tokens
    function exit() external returns (bool success);

    /// @dev creates (register) new validator
    /// @param _id validator address
    /// @param _location location URL of the validator API
    function create(address _id, string calldata _location) external;

    /// @dev removes validator
    /// @param _id validator wallet
    function remove(address _id) external;

    /// @dev updates validator location
    /// @param _id validator wallet
    /// @param _location new validator URL
    function update(address _id, string calldata _location) external;

    /// @return total number of registered validators (with and without balance)
    function getNumberOfValidators() external view returns (uint256);

    /// @dev gets validator address for provided index
    /// @param _ix index in array of list of all validators wallets
    function addresses(uint256 _ix) external view returns (address);

    /// @param _id address of validator
    /// @return id address of validator
    /// @return location URL of validator
    function validators(address _id) external view returns (address id, string memory location);
}

File 7 of 15 : Registrable.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../interfaces/IRegistry.sol";
import "../interfaces/IStakingBank.sol";

/// @dev Any contract that we want to register in ContractRegistry, must inherit from Registrable
abstract contract Registrable {
    IRegistry public immutable contractRegistry;

    modifier onlyFromContract(address _msgSender, bytes32 _contractName) {
        require(
            contractRegistry.getAddress(_contractName) == _msgSender,
            string(abi.encodePacked("caller is not ", _contractName))
        );
        _;
    }

    modifier withRegistrySetUp() {
        require(address(contractRegistry) != address(0x0), "_registry is empty");
        _;
    }

    constructor(IRegistry _contractRegistry) {
        require(address(_contractRegistry) != address(0x0), "_registry is empty");
        contractRegistry = _contractRegistry;
    }

    /// @dev this method will be called as a first method in registration process when old contract will be replaced
    /// when called, old contract address is still in registry
    function register() virtual external;

    /// @dev this method will be called as a last method in registration process when old contract will be replaced
    /// when called, new contract address is already in registry
    function unregister() virtual external;

    /// @return contract name as bytes32
    function getName() virtual external pure returns (bytes32);

    /// @dev helper method for fetching StakingBank address
    function stakingBankContract() public view returns (IStakingBank) {
        return IStakingBank(contractRegistry.requireAndGetAddress("StakingBank"));
    }

    /// @dev helper method for fetching UMB address
    function tokenContract() public view withRegistrySetUp returns (ERC20) {
        return ERC20(contractRegistry.requireAndGetAddress("UMB"));
    }
}

File 8 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        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 9 of 15 : MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

File 10 of 15 : ValueDecoder.sol
//SPDX-License-Identifier: Unlicensed
pragma solidity >=0.6.8;

library ValueDecoder {
  function toUint(bytes memory _bytes) internal pure returns (uint256 value) {
    assembly {
      value := mload(add(_bytes, 32))
    }
  }

  function toUint(bytes32 _bytes) internal pure returns (uint256 value) {
    assembly {
      value := _bytes
    }
  }

  function toInt(uint224 u) internal pure returns (int256) {
    int224 i;
    uint224 max = type(uint224).max;

    if (u <= (max - 1) / 2) { // positive values
      assembly {
        i := add(u, 0)
      }

      return i;
    } else { // negative values
      assembly {
        i := sub(sub(u, max), 1)
      }
    }

    return i;
  }
}

File 11 of 15 : IRegistry.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.13;


interface IRegistry {
    event LogRegistered(address indexed destination, bytes32 name);

    /// @dev imports new contract addresses and override old addresses, if they exist under provided name
    /// This method can be used for contracts that for some reason do not have `getName` method
    /// @param  _names array of contract names that we want to register
    /// @param  _destinations array of contract addresses
    function importAddresses(bytes32[] calldata _names, address[] calldata _destinations) external;

    /// @dev imports new contracts and override old addresses, if they exist.
    /// Names of contracts are fetched directly from each contract by calling `getName`
    /// @param  _destinations array of contract addresses
    function importContracts(address[] calldata _destinations) external;

    /// @dev this method ensure, that old and new contract is aware of it state in registry
    /// Note: BSC registry does not have this method. This method was introduced in later stage.
    /// @param _newContract address of contract that will replace old one
    function atomicUpdate(address _newContract) external;

    /// @dev similar to `getAddress` but throws when contract name not exists
    /// @param name contract name
    /// @return contract address registered under provided name or throws, if does not exists
    function requireAndGetAddress(bytes32 name) external view returns (address);

    /// @param name contract name in a form of bytes32
    /// @return contract address registered under provided name
    function getAddress(bytes32 name) external view returns (address);

    /// @param _name contract name
    /// @return contract address assigned to the name or address(0) if not exists
    function getAddressByString(string memory _name) external view returns (address);

    /// @dev helper method that converts string to bytes32,
    /// you can use to to generate contract name
    function stringToBytes32(string memory _string) external pure returns (bytes32 result);
}

File 12 of 15 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 13 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 14 of 15 : 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;
    }
}

File 15 of 15 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

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

Contract ABI

[{"inputs":[{"internalType":"contract IRegistry","name":"_contractRegistry","type":"address"},{"internalType":"uint32","name":"_padding","type":"uint32"},{"internalType":"uint16","name":"_requiredSignatures","type":"uint16"},{"internalType":"bool","name":"_allowForMixedType","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyDeprecated","type":"error"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[],"name":"ArraysDataDoNotMatch","type":"error"},{"inputs":[],"name":"BlockSubmittedToFastOrDataToOld","type":"error"},{"inputs":[],"name":"ContractNotReady","type":"error"},{"inputs":[],"name":"FCDOverflow","type":"error"},{"inputs":[],"name":"InvalidContractType","type":"error"},{"inputs":[],"name":"NoChangeToState","type":"error"},{"inputs":[],"name":"NotEnoughSignatures","type":"error"},{"inputs":[],"name":"NotSupported","type":"error"},{"inputs":[],"name":"OnlyOwnerOrRegistry","type":"error"},{"inputs":[],"name":"SignaturesOutOfOrder","type":"error"},{"inputs":[],"name":"UnregisterFirst","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deprecator","type":"address"}],"name":"LogDeprecation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"staked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"power","type":"uint256"}],"name":"LogMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"uint32","name":"timePadding","type":"uint32"}],"name":"LogPadding","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":false,"internalType":"uint256","name":"vote","type":"uint256"}],"name":"LogVoter","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"},{"inputs":[],"name":"ETH_PREFIX","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockId","type":"uint256"}],"name":"blocks","outputs":[{"components":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint32","name":"dataTimestamp","type":"uint32"}],"internalType":"struct BaseChain.Block","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksCountOffset","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_items","type":"uint256"}],"name":"bytesToBytes32Array","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"contractRegistry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deprecate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"fcds","outputs":[{"internalType":"uint224","name":"value","type":"uint224"},{"internalType":"uint32","name":"dataTimestamp","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getBlockIdAtTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_blockId","type":"uint32"}],"name":"getBlockRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_blockId","type":"uint32"}],"name":"getBlockTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConsensusData","outputs":[{"components":[{"internalType":"uint32","name":"blocksCountOffset","type":"uint32"},{"internalType":"uint32","name":"sequence","type":"uint32"},{"internalType":"uint32","name":"lastTimestamp","type":"uint32"},{"internalType":"uint32","name":"padding","type":"uint32"},{"internalType":"bool","name":"deprecated","type":"bool"}],"internalType":"struct BaseChain.ConsensusData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"getCurrentIntValue","outputs":[{"internalType":"int256","name":"value","type":"int256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"getCurrentValue","outputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_keys","type":"bytes32[]"}],"name":"getCurrentValues","outputs":[{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"uint32[]","name":"timestamps","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestBlockId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLeaderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getLeaderAddressAtTime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getLeaderIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getName","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getNextLeaderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStatus","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint32","name":"timePadding","type":"uint32"},{"internalType":"uint32","name":"lastDataTimestamp","type":"uint32"},{"internalType":"uint32","name":"lastId","type":"uint32"},{"internalType":"address","name":"nextLeader","type":"address"},{"internalType":"uint32","name":"nextBlockId","type":"uint32"},{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"string[]","name":"locations","type":"string[]"},{"internalType":"uint256","name":"staked","type":"uint256"},{"internalType":"uint16","name":"minSignatures","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_key","type":"bytes"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"hashLeaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isForeign","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"lastBlockId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_affidavit","type":"bytes32"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"recoverSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requiredSignatures","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_padding","type":"uint16"}],"name":"setPadding","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingBank","outputs":[{"internalType":"contract IStakingBank","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingBankContract","outputs":[{"internalType":"contract IStakingBank","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dataTimestamp","type":"uint32"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"bytes32[]","name":"_keys","type":"bytes32[]"},{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"uint8[]","name":"_v","type":"uint8[]"},{"internalType":"bytes32[]","name":"_r","type":"bytes32[]"},{"internalType":"bytes32[]","name":"_s","type":"bytes32[]"}],"name":"submit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenContract","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unregister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"bytes32","name":"_leaf","type":"bytes32"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockId","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"bytes","name":"_key","type":"bytes"},{"internalType":"bytes","name":"_value","type":"bytes"}],"name":"verifyProofForBlock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_blockIds","type":"uint32[]"},{"internalType":"bytes","name":"_proofs","type":"bytes"},{"internalType":"uint256[]","name":"_proofItemsCounter","type":"uint256[]"},{"internalType":"bytes32[]","name":"_leaves","type":"bytes32[]"}],"name":"verifyProofs","outputs":[{"internalType":"bool[]","name":"results","type":"bool[]"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b506040516200586a3803806200586a83398181016040528101906200003891906200067f565b838383838383838383600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000b3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000aa9062000752565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505062000108620000fc620002ee60201b60201c565b620002f660201b60201c565b80151560a0811515815250508161ffff1660c08161ffff16815250506200013583620003ba60201b60201c565b60008473ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b815260040162000170906200079a565b602060405180830381865afa1580156200018e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b49190620007e6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200022b5760018442620001fb919062000847565b62000207919062000847565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055505b50505050508373ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016200026990620008a8565b602060405180830381865afa15801562000287573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ad9190620007e6565b73ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050505050505050505062000963565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003ca620002ee60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003f06200051b60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff161462000449576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004409062000913565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603620004a4576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec8260405162000510919062000946565b60405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005768262000549565b9050919050565b60006200058a8262000569565b9050919050565b6200059c816200057d565b8114620005a857600080fd5b50565b600081519050620005bc8162000591565b92915050565b600063ffffffff82169050919050565b620005dd81620005c2565b8114620005e957600080fd5b50565b600081519050620005fd81620005d2565b92915050565b600061ffff82169050919050565b6200061c8162000603565b81146200062857600080fd5b50565b6000815190506200063c8162000611565b92915050565b60008115159050919050565b620006598162000642565b81146200066557600080fd5b50565b60008151905062000679816200064e565b92915050565b600080600080608085870312156200069c576200069b62000544565b5b6000620006ac87828801620005ab565b9450506020620006bf87828801620005ec565b9350506040620006d2878288016200062b565b9250506060620006e58782880162000668565b91505092959194509250565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006200073a601283620006f1565b9150620007478262000702565b602082019050919050565b600060208201905081810360008301526200076d816200072b565b9050919050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050620007b06000830162000774565b919050565b620007c08162000569565b8114620007cc57600080fd5b50565b600081519050620007e081620007b5565b92915050565b600060208284031215620007ff57620007fe62000544565b5b60006200080f84828501620007cf565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006200085482620005c2565b91506200086183620005c2565b92508282101562000877576200087662000818565b5b828203905092915050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b6000602082019050620008be6000830162000882565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000620008fb602083620006f1565b91506200090882620008c3565b602082019050919050565b600060208201905081810360008301526200092e81620008ec565b9050919050565b6200094081620005c2565b82525050565b60006020820190506200095d600083018462000935565b92915050565b60805160a05160c05160e051614e72620009f860003960008181610f1c01528181611296015281816114c101526116f801526000818161142a015281816116d50152611c430152600061237f01526000818161089701528181610a8d01528181610b55015281816118a901528181611920015281816119bf01528181611d7b015281816121a101526122800152614e726000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c80638d06804311610151578063ca4d29d2116100c3578063e79a198f11610087578063e79a198f146107a0578063ed9975c3146107aa578063ef19f3e7146107c8578063f25b3f99146107f8578063f2fde38b14610828578063ffa1ad741461084457610269565b8063ca4d29d2146106d3578063cbb1b2c714610703578063d3d3ea0814610734578063d45167d014610752578063e76c0b571461078257610269565b8063adf1639d11610115578063adf1639d146105c4578063bef9f8a1146105f5578063bf66e3ba14610625578063c2a4250b14610655578063c2b40ae414610673578063c3369db8146106a357610269565b80638d0680431461052e5780638da5cb5b1461054c5780639f6119d71461056a578063a0bc937414610588578063abf410e5146105a657610269565b806340a9e5e3116101ea578063637180a8116101ae578063637180a81461047c5780636d046c3e1461049a578063715018a6146104b85780637353cbcb146104c257806377839fe6146104e0578063805d3432146104fe57610269565b806340a9e5e3146103ce578063485e055d146103ea5780634bc935d7146104065780634e69d5601461043657806355a373d61461045e57610269565b8063243b68f911610231578063243b68f91461030057806324c89a491461033057806326f3ab8b1461034e57806334ba34811461037f5780633bb8819d1461039d57610269565b80630f2acc3e1461026e5780630fcc0c281461029e57806317d7de7c146102a8578063199dadc5146102c65780631aa3a008146102f6575b600080fd5b61028860048036038101906102839190613087565b610862565b6040516102959190613118565b60405180910390f35b6102a6610895565b005b6102b0610a07565b6040516102bd9190613118565b60405180910390f35b6102e060048036038101906102db919061325d565b610a2f565b6040516102ed9190613333565b60405180910390f35b6102fe610a8b565b005b61031a6004803603810190610315919061334e565b610c99565b604051610327919061347b565b60405180910390f35b610338610d42565b6040516103459190613525565b60405180910390f35b610368600480360381019061036391906135a2565b610d7b565b60405161037692919061377b565b60405180910390f35b610387610f1a565b6040516103949190613831565b60405180910390f35b6103b760048036038101906103b2919061384c565b610f3e565b6040516103c59291906138a1565b60405180910390f35b6103e860048036038101906103e39190613904565b610fd3565b005b61040460048036038101906103ff9190613b1c565b610fe3565b005b610420600480360381019061041b9190613c4a565b6115b6565b60405161042d9190613333565b60405180910390f35b61043e6115ea565b6040516104559b9a99989796959493929190613ecd565b60405180910390f35b61046661188e565b6040516104739190613fae565b60405180910390f35b6104846119bb565b6040516104919190613831565b60405180910390f35b6104a2611a5a565b6040516104af9190613333565b60405180910390f35b6104c0611a63565b005b6104ca611aeb565b6040516104d79190613fc9565b60405180910390f35b6104e8611b2e565b6040516104f59190613fe4565b60405180910390f35b61051860048036038101906105139190613fff565b611b4b565b6040516105259190613fe4565b60405180910390f35b610536611c3f565b604051610543919061402c565b60405180910390f35b610554611c67565b6040516105619190614047565b60405180910390f35b610572611c90565b60405161057f9190614047565b60405180910390f35b610590611cac565b60405161059d91906140d9565b60405180910390f35b6105ae611d79565b6040516105bb9190614115565b60405180910390f35b6105de60048036038101906105d9919061384c565b611d9d565b6040516105ec929190614130565b60405180910390f35b61060f600480360381019061060a9190614159565b611e2a565b60405161061c9190613118565b60405180910390f35b61063f600480360381019061063a9190614249565b611e4d565b60405161064c91906143cf565b60405180910390f35b61065d611f89565b60405161066a9190613fc9565b60405180910390f35b61068d60048036038101906106889190613fff565b611fac565b60405161069a9190613118565b60405180910390f35b6106bd60048036038101906106b89190614159565b611fc4565b6040516106ca9190613fe4565b60405180910390f35b6106ed60048036038101906106e891906143f1565b611ff9565b6040516106fa9190613fc9565b60405180910390f35b61071d6004803603810190610718919061384c565b61202d565b60405161072b929190614468565b60405180910390f35b61073c612089565b6040516107499190613fe4565b60405180910390f35b61076c60048036038101906107679190614491565b6120a6565b6040516107799190614047565b60405180910390f35b61078a612163565b6040516107979190613fe4565b60405180910390f35b6107a861219f565b005b6107b2612520565b6040516107bf9190614047565b60405180910390f35b6107e260048036038101906107dd9190613fff565b612530565b6040516107ef9190614047565b60405180910390f35b610812600480360381019061080d9190613fff565b612564565b60405161081f9190614527565b60405180910390f35b610842600480360381019061083d919061456e565b6125a1565b005b61084c612698565b6040516108599190613fc9565b60405180910390f35b600082826040516020016108779291906145d7565b60405160208183030381529060405280519060200120905092915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561092457506108f4611c67565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561095b576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff16156109a5576040517f764c143b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2565b60007f436861696e000000000000000000000000000000000000000000000000000000905090565b6000610a8160026000878152602001908152602001600020548484604051602001610a5b9291906145d7565b604051602081830303815290604052805190602001208661269d9092919063ffffffff16565b9050949350505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610b1a5750610aea611c67565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610b51576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b8152600401610baa90614621565b602060405180830381865afa158015610bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610beb919061464f565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c52576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c8c5750610c97565b610c95816126b4565b505b565b606060008267ffffffffffffffff811115610cb757610cb6612f5c565b5b604051908082528060200260200182016040528015610ce55781602001602082028036833780820191505090505b50905060005b83811015610d3657600080602087600185010102905080880151915081848481518110610d1b57610d1a61467c565b5b60200260200101818152505050508080600101915050610ceb565b50809150509392505050565b6040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525081565b6060808383905067ffffffffffffffff811115610d9b57610d9a612f5c565b5b604051908082528060200260200182016040528015610dc95781602001602082028036833780820191505090505b5090508383905067ffffffffffffffff811115610de957610de8612f5c565b5b604051908082528060200260200182016040528015610e175781602001602082028036833780820191505090505b50915060005b84849050811015610f1257600060036000878785818110610e4157610e4061467c565b5b90506020020135815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16848381518110610eb657610eb561467c565b5b60200260200101818152505080600001601c9054906101000a900463ffffffff16838381518110610eea57610ee961467c565b5b602002602001019063ffffffff16908163ffffffff1681525050818060010192505050610e1d565b509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000600360008581526020019081526020016000209050610fab8160000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166129f6565b81600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b610fe08161ffff16612a9e565b50565b610ff28763ffffffff16612be9565b60008787604051602001611007929190614702565b604051602081830303815290604052905060005b8651811015611217578581815181106110375761103661467c565b5b60200260200101518682815181106110525761105161467c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16146110af576040517f6980091000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808783815181106110cd576110cc61467c565b5b60200260200101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018a63ffffffff16815250600360008984815181106111195761111861467c565b5b6020026020010151815260200190815260200160002060008201518160000160006101000a8154817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160217905550602082015181600001601c6101000a81548163ffffffff021916908363ffffffff160217905550905050818782815181106111c4576111c361467c565b5b60200260200101518783815181106111df576111de61467c565b5b60200260200101516040516020016111f99392919061474f565b6040516020818303038152906040529150808060010191505061101b565b506000806000838051906020012090506000805b8851811015611427576000611290848b848151811061124d5761124c61467c565b5b60200260200101518b85815181106112685761126761467c565b5b60200260200101518b86815181106112835761128261467c565b5b60200260200101516120a6565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b81526004016112ed9190614047565b602060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132e919061479d565b90508173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610611395576040517f9079f69b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b819350600081036113af5782806001019350505050611422565b86806113ba906147f9565b9750508173ffffffffffffffffffffffffffffffffffffffff168f63ffffffff167fbac7552ab5da8d0588709ddb75aceec28520646f54bca1cc5e6e104db61935ec8360405161140a9190613fc9565b60405180910390a38086019550828060010193505050505b61122b565b507f000000000000000000000000000000000000000000000000000000000000000061ffff16841015611486576040517fe246dc6300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f5f11830295067c4bcc7d02d4e3b048cd7427be50a3aeb6afc9d3d559ee64bcfa8d7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561152a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154e919061479d565b8660405161155e93929190614872565b60405180910390a28a600260008e63ffffffff168152602001908152602001600020819055508b600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505050505050505050505050565b60008060001b83036115cb57600090506115e3565b6115e083838661269d9092919063ffffffff16565b90505b9392505050565b6000806000806000806060806060600080600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff1615151515815250509050439b5080606001519a50806040015198508899507f000000000000000000000000000000000000000000000000000000000000000091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611761573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611785919061479d565b925060008067ffffffffffffffff8111156117a3576117a2612f5c565b5b6040519080825280602002602001820160405280156117d15781602001602082028036833780820191505090505b5095508067ffffffffffffffff8111156117ee576117ed612f5c565b5b60405190808252806020026020018201604052801561181c5781602001602082028036833780820191505090505b5096508067ffffffffffffffff81111561183957611838612f5c565b5b60405190808252806020026020018201604052801561186c57816020015b60608152602001906001900390816118575790505b50945060009850600182606001518b010197505050909192939495969798999a565b60008073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff160361191e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191590614906565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b81526004016119759061494c565b602060405180830381865afa158015611992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b6919061464f565b905090565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166346bcb49d6040518163ffffffff1660e01b8152600401611a149061498b565b602060405180830381865afa158015611a31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a55919061464f565b905090565b60006001905090565b611a6b612d69565b73ffffffffffffffffffffffffffffffffffffffff16611a89611c67565b73ffffffffffffffffffffffffffffffffffffffff1614611adf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ad6906149f0565b60405180910390fd5b611ae96000612d71565b565b6000600160000160009054906101000a900463ffffffff16600160000160049054906101000a900463ffffffff16611b239190614a10565b63ffffffff16905090565b6000600160000160009054906101000a900463ffffffff16905090565b60008060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905082816060015182604001510163ffffffff161015611c315782915050611c3a565b80604001519150505b919050565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000611ca7600142611ca29190614a44565b612530565b905090565b611cb4612ec1565b60016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff161515151581525050905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060006003600085815260200190815260200160002090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681600001601c9054906101000a900463ffffffff168063ffffffff1690509250925050915091565b6000600260008363ffffffff168152602001908152602001600020549050919050565b6060815167ffffffffffffffff811115611e6a57611e69612f5c565b5b604051908082528060200260200182016040528015611e985781602001602082028036833780820191505090505b5090506000805b8351811015611f7f57611f2e60026000898481518110611ec257611ec161467c565b5b602002602001015163ffffffff16815260200190815260200160002054858381518110611ef257611ef161467c565b5b6020026020010151611f1f89868a8781518110611f1257611f1161467c565b5b6020026020010151610c99565b61269d9092919063ffffffff16565b838281518110611f4157611f4061467c565b5b602002602001019015159081151581525050848181518110611f6657611f6561467c565b5b6020026020010151820191508080600101915050611e9f565b5050949350505050565b6000600160000160089054906101000a900463ffffffff1663ffffffff16905090565b60026020528060005260406000206000915090505481565b60008060001b600260008463ffffffff1681526020019081526020016000205414611fef5781611ff2565b60005b9050919050565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036020528060005260406000206000915090508060000160009054906101000a90047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169080600001601c9054906101000a900463ffffffff16905082565b6000600160000160089054906101000a900463ffffffff16905090565b6000806040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250866040516020016120f1929190614a9a565b6040516020818303038152906040528051906020012090506001818686866040516000815260200160405260405161212c9493929190614ad1565b6020604051602081039080840390855afa15801561214e573d6000803e3d6000fd5b50505060206040510351915050949350505050565b600080600160000160089054906101000a900463ffffffff1663ffffffff1603612190576000905061219c565b61219942611b4b565b90505b90565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561222e57506121fe611c67565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15612265576040517f0daa173600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160000160109054906101000a900460ff1661251e5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166321f8a7216040518163ffffffff1660e01b81526004016122d590614621565b602060405180830381865afa1580156122f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612316919061464f565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361237d576040517ff8e0084400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006124bc573073ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124119190614b42565b15158173ffffffffffffffffffffffffffffffffffffffff16636d046c3e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561245e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124829190614b42565b1515146124bb576040517f07b72f5e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b60018060000160106101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167fd4ae81319f0b4df100dcda9ce971671b97278c7a5ce6b37a8331a44700679fd460405160405180910390a2505b565b600061252b42612530565b905090565b60006040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61256c612f0a565b6040518060400160405280600260008581526020019081526020016000205481526020018363ffffffff168152509050919050565b6125a9612d69565b73ffffffffffffffffffffffffffffffffffffffff166125c7611c67565b73ffffffffffffffffffffffffffffffffffffffff161461261d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612614906149f0565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361268c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268390614be1565b60405180910390fd5b61269581612d71565b50565b600281565b6000826126aa8584612e35565b1490509392505050565b6000808273ffffffffffffffffffffffffffffffffffffffff167fffa1ad74ba96b4c159a84d090433911c3991c54f629eb60d0c84aed3be5f067c6040516020016126ff9190614c3c565b60405160208183030381529060405260405161271b9190614c57565b600060405180830381855afa9150503d8060008114612756576040519150601f19603f3d011682016040523d82523d6000602084013e61275b565b606091505b509150915060008261276e576001612783565b81806020019051810190612782919061479d565b5b9050600181036129035760008473ffffffffffffffffffffffffffffffffffffffff1663d3d3ea086040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fe9190614c83565b90508473ffffffffffffffffffffffffffffffffffffffff1663c3369db8826040518263ffffffff1660e01b81526004016128399190613fe4565b602060405180830381865afa158015612856573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287a9190614c83565b600160000160086101000a81548163ffffffff021916908363ffffffff1602179055506002816128aa9190614cb0565b600160000160046101000a81548163ffffffff021916908363ffffffff1602179055506002816128da9190614cb0565b600160000160006101000a81548163ffffffff021916908363ffffffff160217905550506129f0565b60008473ffffffffffffffffffffffffffffffffffffffff1663a0bc93746040518163ffffffff1660e01b815260040160a060405180830381865afa158015612950573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129749190614d7b565b90508060200151600160000160046101000a81548163ffffffff021916908363ffffffff1602179055508060200151600160000160006101000a81548163ffffffff021916908363ffffffff1602179055508060400151600160000160086101000a81548163ffffffff021916908363ffffffff160217905550505b50505050565b60008060007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506002600182612a299190614da8565b612a339190614e0b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1611612a885760008401915081601b0b92505050612a99565b600181850303915081601b0b925050505b919050565b612aa6612d69565b73ffffffffffffffffffffffffffffffffffffffff16612ac4611c67565b73ffffffffffffffffffffffffffffffffffffffff1614612b1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b11906149f0565b60405180910390fd5b8063ffffffff166001600001600c9054906101000a900463ffffffff1663ffffffff1603612b74576040517f96f56f6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600001600c6101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f02ff77a0f68d11f7efb906f331b2dda82916de8ba9c37dda2a95817936a530ec82604051612bde9190613fe4565b60405180910390a250565b600060016040518060a00160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900460ff16151515158152505090506000816040015163ffffffff1603612cf1576040517f96a96e1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81816060015182604001510163ffffffff1610612d3a576040517ff886149e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001816020015101600160000160046101000a81548163ffffffff021916908363ffffffff1602179055505050565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60008082905060005b8451811015612e9f576000858281518110612e5c57612e5b61467c565b5b60200260200101519050808311612e7e57612e778382612eaa565b9250612e8b565b612e888184612eaa565b92505b508080612e97906147f9565b915050612e3e565b508091505092915050565b600082600052816020526040600020905092915050565b6040518060a00160405280600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681526020016000151581525090565b604051806040016040528060008019168152602001600063ffffffff1681525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612f9482612f4b565b810181811067ffffffffffffffff82111715612fb357612fb2612f5c565b5b80604052505050565b6000612fc6612f2d565b9050612fd28282612f8b565b919050565b600067ffffffffffffffff821115612ff257612ff1612f5c565b5b612ffb82612f4b565b9050602081019050919050565b82818337600083830152505050565b600061302a61302584612fd7565b612fbc565b90508281526020810184848401111561304657613045612f46565b5b613051848285613008565b509392505050565b600082601f83011261306e5761306d612f41565b5b813561307e848260208601613017565b91505092915050565b6000806040838503121561309e5761309d612f37565b5b600083013567ffffffffffffffff8111156130bc576130bb612f3c565b5b6130c885828601613059565b925050602083013567ffffffffffffffff8111156130e9576130e8612f3c565b5b6130f585828601613059565b9150509250929050565b6000819050919050565b613112816130ff565b82525050565b600060208201905061312d6000830184613109565b92915050565b6000819050919050565b61314681613133565b811461315157600080fd5b50565b6000813590506131638161313d565b92915050565b600067ffffffffffffffff82111561318457613183612f5c565b5b602082029050602081019050919050565b600080fd5b6131a3816130ff565b81146131ae57600080fd5b50565b6000813590506131c08161319a565b92915050565b60006131d96131d484613169565b612fbc565b905080838252602082019050602084028301858111156131fc576131fb613195565b5b835b81811015613225578061321188826131b1565b8452602084019350506020810190506131fe565b5050509392505050565b600082601f83011261324457613243612f41565b5b81356132548482602086016131c6565b91505092915050565b6000806000806080858703121561327757613276612f37565b5b600061328587828801613154565b945050602085013567ffffffffffffffff8111156132a6576132a5612f3c565b5b6132b28782880161322f565b935050604085013567ffffffffffffffff8111156132d3576132d2612f3c565b5b6132df87828801613059565b925050606085013567ffffffffffffffff811115613300576132ff612f3c565b5b61330c87828801613059565b91505092959194509250565b60008115159050919050565b61332d81613318565b82525050565b60006020820190506133486000830184613324565b92915050565b60008060006060848603121561336757613366612f37565b5b600084013567ffffffffffffffff81111561338557613384612f3c565b5b61339186828701613059565b93505060206133a286828701613154565b92505060406133b386828701613154565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6133f2816130ff565b82525050565b600061340483836133e9565b60208301905092915050565b6000602082019050919050565b6000613428826133bd565b61343281856133c8565b935061343d836133d9565b8060005b8381101561346e57815161345588826133f8565b975061346083613410565b925050600181019050613441565b5085935050505092915050565b60006020820190508181036000830152613495818461341d565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156134d75780820151818401526020810190506134bc565b838111156134e6576000848401525b50505050565b60006134f78261349d565b61350181856134a8565b93506135118185602086016134b9565b61351a81612f4b565b840191505092915050565b6000602082019050818103600083015261353f81846134ec565b905092915050565b600080fd5b60008083601f84011261356257613561612f41565b5b8235905067ffffffffffffffff81111561357f5761357e613547565b5b60208301915083602082028301111561359b5761359a613195565b5b9250929050565b600080602083850312156135b9576135b8612f37565b5b600083013567ffffffffffffffff8111156135d7576135d6612f3c565b5b6135e38582860161354c565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61362481613133565b82525050565b6000613636838361361b565b60208301905092915050565b6000602082019050919050565b600061365a826135ef565b61366481856135fa565b935061366f8361360b565b8060005b838110156136a0578151613687888261362a565b975061369283613642565b925050600181019050613673565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600063ffffffff82169050919050565b6136f2816136d9565b82525050565b600061370483836136e9565b60208301905092915050565b6000602082019050919050565b6000613728826136ad565b61373281856136b8565b935061373d836136c9565b8060005b8381101561376e57815161375588826136f8565b975061376083613710565b925050600181019050613741565b5085935050505092915050565b60006040820190508181036000830152613795818561364f565b905081810360208301526137a9818461371d565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006137f76137f26137ed846137b2565b6137d2565b6137b2565b9050919050565b6000613809826137dc565b9050919050565b600061381b826137fe565b9050919050565b61382b81613810565b82525050565b60006020820190506138466000830184613822565b92915050565b60006020828403121561386257613861612f37565b5b6000613870848285016131b1565b91505092915050565b6000819050919050565b61388c81613879565b82525050565b61389b81613133565b82525050565b60006040820190506138b66000830185613883565b6138c36020830184613892565b9392505050565b600061ffff82169050919050565b6138e1816138ca565b81146138ec57600080fd5b50565b6000813590506138fe816138d8565b92915050565b60006020828403121561391a57613919612f37565b5b6000613928848285016138ef565b91505092915050565b61393a816136d9565b811461394557600080fd5b50565b60008135905061395781613931565b92915050565b600067ffffffffffffffff82111561397857613977612f5c565b5b602082029050602081019050919050565b600061399c6139978461395d565b612fbc565b905080838252602082019050602084028301858111156139bf576139be613195565b5b835b818110156139e857806139d48882613154565b8452602084019350506020810190506139c1565b5050509392505050565b600082601f830112613a0757613a06612f41565b5b8135613a17848260208601613989565b91505092915050565b600067ffffffffffffffff821115613a3b57613a3a612f5c565b5b602082029050602081019050919050565b600060ff82169050919050565b613a6281613a4c565b8114613a6d57600080fd5b50565b600081359050613a7f81613a59565b92915050565b6000613a98613a9384613a20565b612fbc565b90508083825260208201905060208402830185811115613abb57613aba613195565b5b835b81811015613ae45780613ad08882613a70565b845260208401935050602081019050613abd565b5050509392505050565b600082601f830112613b0357613b02612f41565b5b8135613b13848260208601613a85565b91505092915050565b600080600080600080600060e0888a031215613b3b57613b3a612f37565b5b6000613b498a828b01613948565b9750506020613b5a8a828b016131b1565b965050604088013567ffffffffffffffff811115613b7b57613b7a612f3c565b5b613b878a828b0161322f565b955050606088013567ffffffffffffffff811115613ba857613ba7612f3c565b5b613bb48a828b016139f2565b945050608088013567ffffffffffffffff811115613bd557613bd4612f3c565b5b613be18a828b01613aee565b93505060a088013567ffffffffffffffff811115613c0257613c01612f3c565b5b613c0e8a828b0161322f565b92505060c088013567ffffffffffffffff811115613c2f57613c2e612f3c565b5b613c3b8a828b0161322f565b91505092959891949750929550565b600080600060608486031215613c6357613c62612f37565b5b600084013567ffffffffffffffff811115613c8157613c80612f3c565b5b613c8d8682870161322f565b9350506020613c9e868287016131b1565b9250506040613caf868287016131b1565b9150509250925092565b613cc2816136d9565b82525050565b6000613cd3826137b2565b9050919050565b613ce381613cc8565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613d1e81613cc8565b82525050565b6000613d308383613d15565b60208301905092915050565b6000602082019050919050565b6000613d5482613ce9565b613d5e8185613cf4565b9350613d6983613d05565b8060005b83811015613d9a578151613d818882613d24565b9750613d8c83613d3c565b925050600181019050613d6d565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613dfa82613dd3565b613e048185613dde565b9350613e148185602086016134b9565b613e1d81612f4b565b840191505092915050565b6000613e348383613def565b905092915050565b6000602082019050919050565b6000613e5482613da7565b613e5e8185613db2565b935083602082028501613e7085613dc3565b8060005b85811015613eac5784840389528151613e8d8582613e28565b9450613e9883613e3c565b925060208a01995050600181019050613e74565b50829750879550505050505092915050565b613ec7816138ca565b82525050565b600061016082019050613ee3600083018e613892565b613ef0602083018d613cb9565b613efd604083018c613cb9565b613f0a606083018b613cb9565b613f17608083018a613cda565b613f2460a0830189613cb9565b81810360c0830152613f368188613d49565b905081810360e0830152613f4a818761364f565b9050818103610100830152613f5f8186613e49565b9050613f6f610120830185613892565b613f7d610140830184613ebe565b9c9b505050505050505050505050565b6000613f98826137fe565b9050919050565b613fa881613f8d565b82525050565b6000602082019050613fc36000830184613f9f565b92915050565b6000602082019050613fde6000830184613892565b92915050565b6000602082019050613ff96000830184613cb9565b92915050565b60006020828403121561401557614014612f37565b5b600061402384828501613154565b91505092915050565b60006020820190506140416000830184613ebe565b92915050565b600060208201905061405c6000830184613cda565b92915050565b61406b81613318565b82525050565b60a08201600082015161408760008501826136e9565b50602082015161409a60208501826136e9565b5060408201516140ad60408501826136e9565b5060608201516140c060608501826136e9565b5060808201516140d36080850182614062565b50505050565b600060a0820190506140ee6000830184614071565b92915050565b60006140ff826137fe565b9050919050565b61410f816140f4565b82525050565b600060208201905061412a6000830184614106565b92915050565b60006040820190506141456000830185613892565b6141526020830184613892565b9392505050565b60006020828403121561416f5761416e612f37565b5b600061417d84828501613948565b91505092915050565b600067ffffffffffffffff8211156141a1576141a0612f5c565b5b602082029050602081019050919050565b60006141c56141c084614186565b612fbc565b905080838252602082019050602084028301858111156141e8576141e7613195565b5b835b8181101561421157806141fd8882613948565b8452602084019350506020810190506141ea565b5050509392505050565b600082601f8301126142305761422f612f41565b5b81356142408482602086016141b2565b91505092915050565b6000806000806080858703121561426357614262612f37565b5b600085013567ffffffffffffffff81111561428157614280612f3c565b5b61428d8782880161421b565b945050602085013567ffffffffffffffff8111156142ae576142ad612f3c565b5b6142ba87828801613059565b935050604085013567ffffffffffffffff8111156142db576142da612f3c565b5b6142e7878288016139f2565b925050606085013567ffffffffffffffff81111561430857614307612f3c565b5b6143148782880161322f565b91505092959194509250565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006143588383614062565b60208301905092915050565b6000602082019050919050565b600061437c82614320565b614386818561432b565b93506143918361433c565b8060005b838110156143c25781516143a9888261434c565b97506143b483614364565b925050600181019050614395565b5085935050505092915050565b600060208201905081810360008301526143e98184614371565b905092915050565b6000806040838503121561440857614407612f37565b5b600061441685828601613154565b925050602061442785828601613154565b9150509250929050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff82169050919050565b61446281614431565b82525050565b600060408201905061447d6000830185614459565b61448a6020830184613cb9565b9392505050565b600080600080608085870312156144ab576144aa612f37565b5b60006144b9878288016131b1565b94505060206144ca87828801613a70565b93505060406144db878288016131b1565b92505060606144ec878288016131b1565b91505092959194509250565b60408201600082015161450e60008501826133e9565b50602082015161452160208501826136e9565b50505050565b600060408201905061453c60008301846144f8565b92915050565b61454b81613cc8565b811461455657600080fd5b50565b60008135905061456881614542565b92915050565b60006020828403121561458457614583612f37565b5b600061459284828501614559565b91505092915050565b600081905092915050565b60006145b18261349d565b6145bb818561459b565b93506145cb8185602086016134b9565b80840191505092915050565b60006145e382856145a6565b91506145ef82846145a6565b91508190509392505050565b7f436861696e000000000000000000000000000000000000000000000000000000815250565b6000602082019050614635600083016145fb565b919050565b60008151905061464981614542565b92915050565b60006020828403121561466557614664612f37565b5b60006146738482850161463a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008160e01b9050919050565b60006146c3826146ab565b9050919050565b6146db6146d6826136d9565b6146b8565b82525050565b6000819050919050565b6146fc6146f7826130ff565b6146e1565b82525050565b600061470e82856146ca565b60048201915061471e82846146eb565b6020820191508190509392505050565b6000819050919050565b61474961474482613133565b61472e565b82525050565b600061475b82866145a6565b915061476782856146eb565b6020820191506147778284614738565b602082019150819050949350505050565b6000815190506147978161313d565b92915050565b6000602082840312156147b3576147b2612f37565b5b60006147c184828501614788565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061480482613133565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614836576148356147ca565b5b600182019050919050565b600061485c614857614852846136d9565b6137d2565b613133565b9050919050565b61486c81614841565b82525050565b60006060820190506148876000830186614863565b6148946020830185613892565b6148a16040830184613892565b949350505050565b600082825260208201905092915050565b7f5f726567697374727920697320656d7074790000000000000000000000000000600082015250565b60006148f06012836148a9565b91506148fb826148ba565b602082019050919050565b6000602082019050818103600083015261491f816148e3565b9050919050565b7f554d420000000000000000000000000000000000000000000000000000000000815250565b600060208201905061496060008301614926565b919050565b7f5374616b696e6742616e6b000000000000000000000000000000000000000000815250565b600060208201905061499f60008301614965565b919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149da6020836148a9565b91506149e5826149a4565b602082019050919050565b60006020820190508181036000830152614a09816149cd565b9050919050565b6000614a1b826136d9565b9150614a26836136d9565b925082821015614a3957614a386147ca565b5b828203905092915050565b6000614a4f82613133565b9150614a5a83613133565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614a8f57614a8e6147ca565b5b828201905092915050565b6000614aa682856145a6565b9150614ab282846146eb565b6020820191508190509392505050565b614acb81613a4c565b82525050565b6000608082019050614ae66000830187613109565b614af36020830186614ac2565b614b006040830185613109565b614b0d6060830184613109565b95945050505050565b614b1f81613318565b8114614b2a57600080fd5b50565b600081519050614b3c81614b16565b92915050565b600060208284031215614b5857614b57612f37565b5b6000614b6684828501614b2d565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000614bcb6026836148a9565b9150614bd682614b6f565b604082019050919050565b60006020820190508181036000830152614bfa81614bbe565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614c3681614c01565b82525050565b6000602082019050614c516000830184614c2d565b92915050565b6000614c6382846145a6565b915081905092915050565b600081519050614c7d81613931565b92915050565b600060208284031215614c9957614c98612f37565b5b6000614ca784828501614c6e565b91505092915050565b6000614cbb826136d9565b9150614cc6836136d9565b92508263ffffffff03821115614cdf57614cde6147ca565b5b828201905092915050565b600080fd5b600060a08284031215614d0557614d04614cea565b5b614d0f60a0612fbc565b90506000614d1f84828501614c6e565b6000830152506020614d3384828501614c6e565b6020830152506040614d4784828501614c6e565b6040830152506060614d5b84828501614c6e565b6060830152506080614d6f84828501614b2d565b60808301525092915050565b600060a08284031215614d9157614d90612f37565b5b6000614d9f84828501614cef565b91505092915050565b6000614db382614431565b9150614dbe83614431565b925082821015614dd157614dd06147ca565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614e1682614431565b9150614e2183614431565b925082614e3157614e30614ddc565b5b82820490509291505056fea264697066735822122065b2747aa4bc97adbc2040a13531d80d4ff97afc9eb19e88b8e8d069bf467d9164736f6c634300080d0033000000000000000000000000da9a63d77406faa09d265413f4e128b54b5057e0000000000000000000000000000000000000000000000000000000000000070800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000da9a63d77406faa09d265413f4e128b54b5057e0000000000000000000000000000000000000000000000000000000000000070800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _contractRegistry (address): 0xda9a63d77406faa09d265413f4e128b54b5057e0
Arg [1] : _padding (uint32): 1800
Arg [2] : _requiredSignatures (uint16): 6
Arg [3] : _allowForMixedType (bool): False

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000da9a63d77406faa09d265413f4e128b54b5057e0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000708
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.