ETH Price: $3,450.01 (+0.84%)
Gas: 9 Gwei

Contract

0x3FBc7C6c2437dE24F91b2Ca61Fc7AD3D2D62F4c8
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
153652422022-08-18 13:22:25698 days ago1660828945  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Governance

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 9 : Governance.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



import "./Config.sol";
import "./Utils.sol";
import "./NFTFactory.sol";
import "./TokenGovernance.sol";

/// @title Governance Contract
/// @author Matter Labs
contract Governance is Config {
    /// @notice Token added to Franklin net
    event NewToken(address indexed token, uint16 indexed tokenId);

    /// @notice Default nft factory has set
    event SetDefaultNFTFactory(address indexed factory);

    /// @notice NFT factory registered new creator account
    event NFTFactoryRegisteredCreator(
        uint32 indexed creatorAccountId,
        address indexed creatorAddress,
        address factoryAddress
    );

    /// @notice Governor changed
    event NewGovernor(address newGovernor);

    /// @notice Token Governance changed
    event NewTokenGovernance(TokenGovernance newTokenGovernance);

    /// @notice Validator's status changed
    event ValidatorStatusUpdate(address indexed validatorAddress, bool isActive);

    event TokenPausedUpdate(address indexed token, bool paused);

    /// @notice Address which will exercise governance over the network i.e. add tokens, change validator set, conduct upgrades
    address public networkGovernor;

    /// @notice Total number of ERC20 tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0)
    uint16 public totalTokens;

    /// @notice List of registered tokens by tokenId
    mapping(uint16 => address) public tokenAddresses;

    /// @notice List of registered tokens by address
    mapping(address => uint16) public tokenIds;

    /// @notice List of permitted validators
    mapping(address => bool) public validators;

    /// @notice Paused tokens list, deposits are impossible to create for paused tokens
    mapping(uint16 => bool) public pausedTokens;

    /// @notice Address that is authorized to add tokens to the Governance.
    TokenGovernance public tokenGovernance;

    /// @notice NFT Creator address to factory address mapping
    mapping(uint32 => mapping(address => NFTFactory)) public nftFactories;

    /// @notice Address which will be used if NFT token has no factories
    NFTFactory public defaultFactory;

    /// @notice Governance contract initialization. Can be external because Proxy contract intercepts illegal calls of this function.
    /// @param initializationParameters Encoded representation of initialization parameters:
    ///     _networkGovernor The address of network governor
    function initialize(bytes calldata initializationParameters) external {
        address _networkGovernor = abi.decode(initializationParameters, (address));

        networkGovernor = _networkGovernor;
    }

    /// @notice Governance contract upgrade. Can be external because Proxy contract intercepts illegal calls of this function.
    /// @param upgradeParameters Encoded representation of upgrade parameters
    // solhint-disable-next-line no-empty-blocks
    function upgrade(bytes calldata upgradeParameters) external {}

    /// @notice Change current governor
    /// @param _newGovernor Address of the new governor
    function changeGovernor(address _newGovernor) external {
        require(_newGovernor != address(0), "1n");
        requireGovernor(msg.sender);
        if (networkGovernor != _newGovernor) {
            networkGovernor = _newGovernor;
            emit NewGovernor(_newGovernor);
        }
    }

    /// @notice Change current token governance
    /// @param _newTokenGovernance Address of the new token governor
    function changeTokenGovernance(TokenGovernance _newTokenGovernance) external {
        requireGovernor(msg.sender);
        if (tokenGovernance != _newTokenGovernance) {
            tokenGovernance = _newTokenGovernance;
            emit NewTokenGovernance(_newTokenGovernance);
        }
    }

    /// @notice Add token to the list of networks tokens
    /// @param _token Token address
    function addToken(address _token) external {
        require(msg.sender == address(tokenGovernance), "1E");
        require(tokenIds[_token] == 0, "1e"); // token exists
        require(totalTokens < MAX_AMOUNT_OF_REGISTERED_TOKENS, "1f"); // no free identifiers for tokens

        totalTokens++;
        uint16 newTokenId = totalTokens; // it is not `totalTokens - 1` because tokenId = 0 is reserved for eth

        tokenAddresses[newTokenId] = _token;
        tokenIds[_token] = newTokenId;
        emit NewToken(_token, newTokenId);
    }

    /// @notice Pause token deposits for the given token
    /// @param _tokenAddr Token address
    /// @param _tokenPaused Token paused status
    function setTokenPaused(address _tokenAddr, bool _tokenPaused) external {
        requireGovernor(msg.sender);

        uint16 tokenId = this.validateTokenAddress(_tokenAddr);
        if (pausedTokens[tokenId] != _tokenPaused) {
            pausedTokens[tokenId] = _tokenPaused;
            emit TokenPausedUpdate(_tokenAddr, _tokenPaused);
        }
    }

    /// @notice Change validator status (active or not active)
    /// @param _validator Validator address
    /// @param _active Active flag
    function setValidator(address _validator, bool _active) external {
        requireGovernor(msg.sender);
        if (validators[_validator] != _active) {
            validators[_validator] = _active;
            emit ValidatorStatusUpdate(_validator, _active);
        }
    }

    /// @notice Check if specified address is is governor
    /// @param _address Address to check
    function requireGovernor(address _address) public view {
        require(_address == networkGovernor, "1g"); // only by governor
    }

    /// @notice Checks if validator is active
    /// @param _address Validator address
    function requireActiveValidator(address _address) external view {
        require(validators[_address], "1h"); // validator is not active
    }

    /// @notice Validate token id (must be less than or equal to total tokens amount)
    /// @param _tokenId Token id
    /// @return bool flag that indicates if token id is less than or equal to total tokens amount
    function isValidTokenId(uint16 _tokenId) external view returns (bool) {
        return _tokenId <= totalTokens;
    }

    /// @notice Validate token address
    /// @param _tokenAddr Token address
    /// @return tokens id
    function validateTokenAddress(address _tokenAddr) external view returns (uint16) {
        uint16 tokenId = tokenIds[_tokenAddr];
        require(tokenId != 0, "1i"); // 0 is not a valid token
        return tokenId;
    }

    function packRegisterNFTFactoryMsg(
        uint32 _creatorAccountId,
        address _creatorAddress,
        address _factoryAddress
    ) internal pure returns (bytes memory) {
        return
            abi.encodePacked(
                "\x19Ethereum Signed Message:\n141",
                "\nCreator's account ID in zkSync: ",
                Bytes.bytesToHexASCIIBytes(abi.encodePacked((_creatorAccountId))),
                "\nCreator: ",
                Bytes.bytesToHexASCIIBytes(abi.encodePacked((_creatorAddress))),
                "\nFactory: ",
                Bytes.bytesToHexASCIIBytes(abi.encodePacked((_factoryAddress)))
            );
    }

    /// @notice Register creator corresponding to the factory
    /// @param _creatorAccountId Creator's zkSync account ID
    /// @param _creatorAddress NFT creator address
    /// @param _signature Creator's signature
    function registerNFTFactoryCreator(
        uint32 _creatorAccountId,
        address _creatorAddress,
        bytes memory _signature
    ) external {
        require(address(nftFactories[_creatorAccountId][_creatorAddress]) == address(0), "Q");
        bytes32 messageHash = keccak256(packRegisterNFTFactoryMsg(_creatorAccountId, _creatorAddress, msg.sender));

        address recoveredAddress = Utils.recoverAddressFromEthSignature(_signature, messageHash);
        require(recoveredAddress == _creatorAddress, "ws");
        nftFactories[_creatorAccountId][_creatorAddress] = NFTFactory(msg.sender);
        emit NFTFactoryRegisteredCreator(_creatorAccountId, _creatorAddress, msg.sender);
    }

    /// @notice Set default factory for our contract. This factory will be used to mint an NFT token that has no factory
    /// @param _factory Address of NFT factory
    function setDefaultNFTFactory(address _factory) external {
        requireGovernor(msg.sender);
        require(address(_factory) != address(0), "mb1"); // Factory should be non zero
        require(address(defaultFactory) == address(0), "mb2"); // NFTFactory is already set
        defaultFactory = NFTFactory(_factory);
        emit SetDefaultNFTFactory(_factory);
    }

    function getNFTFactory(uint32 _creatorAccountId, address _creatorAddress) external view returns (NFTFactory) {
        NFTFactory _factory = nftFactories[_creatorAccountId][_creatorAddress];
        // even if the factory is undefined or has been destroyed, the user can mint NFT
        if (address(_factory) == address(0) || !isContract(address(_factory))) {
            require(address(defaultFactory) != address(0), "fs"); // NFTFactory does not set
            return defaultFactory;
        } else {
            return _factory;
        }
    }

    /// @return whether the address is a contract or not
    /// NOTE: for smart contracts that called `selfdestruct` will return a negative result
    function isContract(address _address) internal view returns (bool) {
        uint256 contractSize;
        assembly {
            contractSize := extcodesize(_address)
        }

        return contractSize != 0;
    }
}

File 2 of 9 : Config.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



/// @title zkSync configuration constants
/// @author Matter Labs
contract Config {
    /// @dev ERC20 tokens and ETH withdrawals gas limit, used only for complete withdrawals
    uint256 internal constant WITHDRAWAL_GAS_LIMIT = 100000;

    /// @dev NFT withdrawals gas limit, used only for complete withdrawals
    uint256 internal constant WITHDRAWAL_NFT_GAS_LIMIT = 300000;

    /// @dev Bytes in one chunk
    uint8 internal constant CHUNK_BYTES = 10;

    /// @dev zkSync address length
    uint8 internal constant ADDRESS_BYTES = 20;

    uint8 internal constant PUBKEY_HASH_BYTES = 20;

    /// @dev Public key bytes length
    uint8 internal constant PUBKEY_BYTES = 32;

    /// @dev Ethereum signature r/s bytes length
    uint8 internal constant ETH_SIGN_RS_BYTES = 32;

    /// @dev Success flag bytes length
    uint8 internal constant SUCCESS_FLAG_BYTES = 1;

    /// @dev Max amount of tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0)
    uint32 internal constant MAX_AMOUNT_OF_REGISTERED_TOKENS = 1023;

    /// @dev Max account id that could be registered in the network
    uint32 internal constant MAX_ACCOUNT_ID = 16777215;

    /// @dev Expected average period of block creation
    uint256 internal constant BLOCK_PERIOD = 15 seconds;

    /// @dev ETH blocks verification expectation
    /// @dev Blocks can be reverted if they are not verified for at least EXPECT_VERIFICATION_IN.
    /// @dev If set to 0 validator can revert blocks at any time.
    uint256 internal constant EXPECT_VERIFICATION_IN = 0 hours / BLOCK_PERIOD;

    uint256 internal constant NOOP_BYTES = 1 * CHUNK_BYTES;
    uint256 internal constant DEPOSIT_BYTES = 6 * CHUNK_BYTES;
    uint256 internal constant MINT_NFT_BYTES = 5 * CHUNK_BYTES;
    uint256 internal constant TRANSFER_TO_NEW_BYTES = 6 * CHUNK_BYTES;
    uint256 internal constant PARTIAL_EXIT_BYTES = 6 * CHUNK_BYTES;
    uint256 internal constant TRANSFER_BYTES = 2 * CHUNK_BYTES;
    uint256 internal constant FORCED_EXIT_BYTES = 6 * CHUNK_BYTES;
    uint256 internal constant WITHDRAW_NFT_BYTES = 10 * CHUNK_BYTES;

    /// @dev Full exit operation length
    uint256 internal constant FULL_EXIT_BYTES = 11 * CHUNK_BYTES;

    /// @dev ChangePubKey operation length
    uint256 internal constant CHANGE_PUBKEY_BYTES = 6 * CHUNK_BYTES;

    /// @dev Expiration delta for priority request to be satisfied (in seconds)
    /// @dev NOTE: Priority expiration should be > (EXPECT_VERIFICATION_IN * BLOCK_PERIOD)
    /// @dev otherwise incorrect block with priority op could not be reverted.
    uint256 internal constant PRIORITY_EXPIRATION_PERIOD = 14 days;

    /// @dev Expiration delta for priority request to be satisfied (in ETH blocks)
    uint256 internal constant PRIORITY_EXPIRATION =
        PRIORITY_EXPIRATION_PERIOD/BLOCK_PERIOD;

    /// @dev Maximum number of priority request to clear during verifying the block
    /// @dev Cause deleting storage slots cost 5k gas per each slot it's unprofitable to clear too many slots
    /// @dev Value based on the assumption of ~750k gas cost of verifying and 5 used storage slots per PriorityOperation structure
    uint64 internal constant MAX_PRIORITY_REQUESTS_TO_DELETE_IN_VERIFY = 6;

    /// @dev Reserved time for users to send full exit priority operation in case of an upgrade (in seconds)
    uint256 internal constant MASS_FULL_EXIT_PERIOD = 5 days;

    /// @dev Reserved time for users to withdraw funds from full exit priority operation in case of an upgrade (in seconds)
    uint256 internal constant TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT = 2 days;

    /// @dev Notice period before activation preparation status of upgrade mode (in seconds)
    /// @dev NOTE: we must reserve for users enough time to send full exit operation, wait maximum time for processing this operation and withdraw funds from it.
    uint256 internal constant UPGRADE_NOTICE_PERIOD =
        MASS_FULL_EXIT_PERIOD+PRIORITY_EXPIRATION_PERIOD+TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT;

    /// @dev Timestamp - seconds since unix epoch
    uint256 internal constant COMMIT_TIMESTAMP_NOT_OLDER = 24 hours;

    /// @dev Maximum available error between real commit block timestamp and analog used in the verifier (in seconds)
    /// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 15 seconds)
    uint256 internal constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 15 minutes;

    /// @dev Bit mask to apply for verifier public input before verifying.
    uint256 internal constant INPUT_MASK = 14474011154664524427946373126085988481658748083205070504932198000989141204991;

    /// @dev Auth fact reset timelock.
    uint256 internal constant AUTH_FACT_RESET_TIMELOCK = 1 days;

    /// @dev Max deposit of ERC20 token that is possible to deposit
    uint128 internal constant MAX_DEPOSIT_AMOUNT = 20282409603651670423947251286015;

    uint32 internal constant SPECIAL_ACCOUNT_ID = 16777215;
    address internal constant SPECIAL_ACCOUNT_ADDRESS = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF);
    uint32 internal constant SPECIAL_NFT_TOKEN_ID = 2147483646;

    uint32 internal constant MAX_FUNGIBLE_TOKEN_ID = 65535;

    uint256 internal constant SECURITY_COUNCIL_MEMBERS_NUMBER = 15;

    string internal constant name = "ZkSync";

    string internal constant version = "1.0";

    bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId)");

    bytes32 internal constant EIP712_CHANGEPUBKEY_TYPEHASH =
        keccak256("ChangePubKey(bytes20 pubKeyHash,uint32 nonce,uint32 accountId)");
}

File 3 of 9 : Utils.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



import "./IERC20.sol";
import "./Bytes.sol";

library Utils {
    /// @notice Returns lesser of two values
    function minU32(uint32 a, uint32 b) internal pure returns (uint32) {
        return a < b ? a : b;
    }

    /// @notice Returns lesser of two values
    function minU64(uint64 a, uint64 b) internal pure returns (uint64) {
        return a < b ? a : b;
    }

    /// @notice Returns lesser of two values
    function minU128(uint128 a, uint128 b) internal pure returns (uint128) {
        return a < b ? a : b;
    }

    /// @notice Recovers signer's address from ethereum signature for given message
    /// @param _signature 65 bytes concatenated. R (32) + S (32) + V (1)
    /// @param _messageHash signed message hash.
    /// @return address of the signer
    /// NOTE: will revert if signature is invalid
    function recoverAddressFromEthSignature(bytes memory _signature, bytes32 _messageHash)
        internal
        pure
        returns (address)
    {
        require(_signature.length == 65, "P"); // incorrect signature length

        bytes32 signR;
        bytes32 signS;
        uint8 signV;
        assembly {
            signR := mload(add(_signature, 32))
            signS := mload(add(_signature, 64))
            signV := byte(0, mload(add(_signature, 96)))
        }

        address recoveredAddress = ecrecover(_messageHash, signV, signR, signS);
        require(recoveredAddress != address(0), "p4"); // invalid signature

        return recoveredAddress;
    }

    /// @notice Returns new_hash = hash(old_hash + bytes)
    function concatHash(bytes32 _hash, bytes memory _bytes) internal pure returns (bytes32) {
        bytes32 result;
        assembly {
            let bytesLen := add(mload(_bytes), 32)
            mstore(_bytes, _hash)
            result := keccak256(_bytes, bytesLen)
        }
        return result;
    }

    function hashBytesToBytes20(bytes memory _bytes) internal pure returns (bytes20) {
        return bytes20(uint160(uint256(keccak256(_bytes))));
    }

    function getChainId() internal pure returns (uint256) {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        return chainId;
    }
}

File 4 of 9 : NFTFactory.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: UNLICENSED


interface NFTFactory {
    function mintNFTFromZkSync(
        address creator,
        address recipient,
        uint32 creatorAccountId,
        uint32 serialId,
        bytes32 contentHash,
        // Even though the token id can fit into the uint32, we still use
        // the uint256 to preserve consistency with the ERC721 parent contract
        uint256 tokenId
    ) external;

    event MintNFTFromZkSync(
        address indexed creator,
        address indexed recipient,
        uint32 creatorAccountId,
        uint32 serialId,
        bytes32 contentHash,
        uint256 tokenId
    );
}

File 5 of 9 : TokenGovernance.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



import "./ReentrancyGuard.sol";
import "./Governance.sol";
import "./ITrustedTransfarableERC20.sol";
import "./Utils.sol";

/// @title Token Governance Contract
/// @author Matter Labs
/// @notice Contract is used to allow anyone to add new ERC20 tokens to zkSync given sufficient payment
contract TokenGovernance is ReentrancyGuard {
    /// @notice Token lister added or removed (see `tokenLister`)
    event TokenListerUpdate(address indexed tokenLister, bool isActive);

    /// @notice Listing fee token set
    event ListingFeeTokenUpdate(ITrustedTransfarableERC20 indexed newListingFeeToken, uint256 newListingFee);

    /// @notice Listing fee set
    event ListingFeeUpdate(uint256 newListingFee);

    /// @notice Maximum number of listed tokens updated
    event ListingCapUpdate(uint16 newListingCap);

    /// @notice The treasury (the account which will receive the fee) was updated
    event TreasuryUpdate(address newTreasury);

    /// @notice zkSync governance contract
    Governance public governance;

    /// @notice Token used to collect listing fee for addition of new token to zkSync network
    ITrustedTransfarableERC20 public listingFeeToken;

    /// @notice Token listing fee
    uint256 public listingFee;

    /// @notice Max number of tokens that can be listed using this contract
    uint16 public listingCap;

    /// @notice Addresses that can list tokens without fee
    mapping(address => bool) public tokenLister;

    /// @notice Address that collects listing payments
    address public treasury;

    constructor(
        Governance _governance,
        ITrustedTransfarableERC20 _listingFeeToken,
        uint256 _listingFee,
        uint16 _listingCap,
        address _treasury
    ) {
        initializeReentrancyGuard();

        governance = _governance;
        listingFeeToken = _listingFeeToken;
        listingFee = _listingFee;
        listingCap = _listingCap;
        treasury = _treasury;

        address governor = governance.networkGovernor();
        // We add zkSync governor as a first token lister.
        tokenLister[governor] = true;
        emit TokenListerUpdate(governor, true);
    }

    /// @notice Adds new ERC20 token to zkSync network.
    /// @notice If caller is not present in the `tokenLister` map payment of `listingFee` in `listingFeeToken` should be made.
    /// @notice NOTE: before calling this function make sure to approve `listingFeeToken` transfer for this contract.
    function addToken(address _token) external nonReentrant {
        require(_token != address(0), "z1"); // Token should have a non-zero address
        require(_token != 0xaBEA9132b05A70803a4E85094fD0e1800777fBEF, "z2"); // Address of the token cannot be the same as the address of the main zksync contract
        require(governance.totalTokens() < listingCap, "can't add more tokens"); // Impossible to add more tokens using this contract
        if (!tokenLister[msg.sender] && listingFee > 0) {
            // Collect fees
            bool feeTransferOk = listingFeeToken.transferFrom(msg.sender, treasury, listingFee);
            require(feeTransferOk, "fee transfer failed"); // Failed to receive payment for token addition.
        }
        governance.addToken(_token);
    }

    /// Governance functions (this contract is governed by zkSync governor)

    /// @notice Set new listing token and fee
    /// @notice Can be called only by zkSync governor
    function setListingFeeToken(ITrustedTransfarableERC20 _newListingFeeToken, uint256 _newListingFee) external {
        governance.requireGovernor(msg.sender);
        listingFeeToken = _newListingFeeToken;
        listingFee = _newListingFee;

        emit ListingFeeTokenUpdate(_newListingFeeToken, _newListingFee);
    }

    /// @notice Set new listing fee
    /// @notice Can be called only by zkSync governor
    function setListingFee(uint256 _newListingFee) external {
        governance.requireGovernor(msg.sender);
        listingFee = _newListingFee;

        emit ListingFeeUpdate(_newListingFee);
    }

    /// @notice Enable or disable token lister. If enabled new tokens can be added by that address without payment
    /// @notice Can be called only by zkSync governor
    function setLister(address _listerAddress, bool _active) external {
        governance.requireGovernor(msg.sender);
        if (tokenLister[_listerAddress] != _active) {
            tokenLister[_listerAddress] = _active;
            emit TokenListerUpdate(_listerAddress, _active);
        }
    }

    /// @notice Change maximum amount of tokens that can be listed using this method
    /// @notice Can be called only by zkSync governor
    function setListingCap(uint16 _newListingCap) external {
        governance.requireGovernor(msg.sender);
        listingCap = _newListingCap;

        emit ListingCapUpdate(_newListingCap);
    }

    /// @notice Change address that collects payments for listing tokens.
    /// @notice Can be called only by zkSync governor
    function setTreasury(address _newTreasury) external {
        governance.requireGovernor(msg.sender);
        treasury = _newTreasury;

        emit TreasuryUpdate(_newTreasury);
    }
}

File 6 of 9 : IERC20.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: UNLICENSED


/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 `recipient`.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external;

    /**
     * @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 `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external;

    /**
     * @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);
}

File 7 of 9 : Bytes.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



// Functions named bytesToX, except bytesToBytes20, where X is some type of size N < 32 (size of one word)
// implements the following algorithm:
// f(bytes memory input, uint offset) -> X out
// where byte representation of out is N bytes from input at the given offset
// 1) We compute memory location of the word W such that last N bytes of W is input[offset..offset+N]
// W_address = input + 32 (skip stored length of bytes) + offset - (32 - N) == input + offset + N
// 2) We load W from memory into out, last N bytes of W are placed into out

library Bytes {
    function toBytesFromUInt16(uint16 self) internal pure returns (bytes memory _bts) {
        return toBytesFromUIntTruncated(uint256(self), 2);
    }

    function toBytesFromUInt24(uint24 self) internal pure returns (bytes memory _bts) {
        return toBytesFromUIntTruncated(uint256(self), 3);
    }

    function toBytesFromUInt32(uint32 self) internal pure returns (bytes memory _bts) {
        return toBytesFromUIntTruncated(uint256(self), 4);
    }

    function toBytesFromUInt128(uint128 self) internal pure returns (bytes memory _bts) {
        return toBytesFromUIntTruncated(uint256(self), 16);
    }

    // Copies 'len' lower bytes from 'self' into a new 'bytes memory'.
    // Returns the newly created 'bytes memory'. The returned bytes will be of length 'len'.
    function toBytesFromUIntTruncated(uint256 self, uint8 byteLength) private pure returns (bytes memory bts) {
        require(byteLength <= 32, "Q");
        bts = new bytes(byteLength);
        // Even though the bytes will allocate a full word, we don't want
        // any potential garbage bytes in there.
        uint256 data = self << ((32 - byteLength) * 8);
        assembly {
            mstore(
                add(bts, 32), // BYTES_HEADER_SIZE
                data
            )
        }
    }

    // Copies 'self' into a new 'bytes memory'.
    // Returns the newly created 'bytes memory'. The returned bytes will be of length '20'.
    function toBytesFromAddress(address self) internal pure returns (bytes memory bts) {
        bts = toBytesFromUIntTruncated(uint256(self), 20);
    }

    // See comment at the top of this file for explanation of how this function works.
    // NOTE: theoretically possible overflow of (_start + 20)
    function bytesToAddress(bytes memory self, uint256 _start) internal pure returns (address addr) {
        uint256 offset = _start + 20;
        require(self.length >= offset, "R");
        assembly {
            addr := mload(add(self, offset))
        }
    }

    // Reasoning about why this function works is similar to that of other similar functions, except NOTE below.
    // NOTE: that bytes1..32 is stored in the beginning of the word unlike other primitive types
    // NOTE: theoretically possible overflow of (_start + 20)
    function bytesToBytes20(bytes memory self, uint256 _start) internal pure returns (bytes20 r) {
        require(self.length >= (_start + 20), "S");
        assembly {
            r := mload(add(add(self, 0x20), _start))
        }
    }

    // See comment at the top of this file for explanation of how this function works.
    // NOTE: theoretically possible overflow of (_start + 0x2)
    function bytesToUInt16(bytes memory _bytes, uint256 _start) internal pure returns (uint16 r) {
        uint256 offset = _start + 0x2;
        require(_bytes.length >= offset, "T");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // See comment at the top of this file for explanation of how this function works.
    // NOTE: theoretically possible overflow of (_start + 0x3)
    function bytesToUInt24(bytes memory _bytes, uint256 _start) internal pure returns (uint24 r) {
        uint256 offset = _start + 0x3;
        require(_bytes.length >= offset, "U");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // NOTE: theoretically possible overflow of (_start + 0x4)
    function bytesToUInt32(bytes memory _bytes, uint256 _start) internal pure returns (uint32 r) {
        uint256 offset = _start + 0x4;
        require(_bytes.length >= offset, "V");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // NOTE: theoretically possible overflow of (_start + 0x10)
    function bytesToUInt128(bytes memory _bytes, uint256 _start) internal pure returns (uint128 r) {
        uint256 offset = _start + 0x10;
        require(_bytes.length >= offset, "W");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // See comment at the top of this file for explanation of how this function works.
    // NOTE: theoretically possible overflow of (_start + 0x14)
    function bytesToUInt160(bytes memory _bytes, uint256 _start) internal pure returns (uint160 r) {
        uint256 offset = _start + 0x14;
        require(_bytes.length >= offset, "X");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // NOTE: theoretically possible overflow of (_start + 0x20)
    function bytesToBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32 r) {
        uint256 offset = _start + 0x20;
        require(_bytes.length >= offset, "Y");
        assembly {
            r := mload(add(_bytes, offset))
        }
    }

    // Original source code: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol#L228
    // Get slice from bytes arrays
    // Returns the newly created 'bytes memory'
    // NOTE: theoretically possible overflow of (_start + _length)
    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    ) internal pure returns (bytes memory) {
        require(_bytes.length >= (_start + _length), "Z"); // bytes length is less then start byte + length bytes

        bytes memory tempBytes = new bytes(_length);

        if (_length != 0) {
            assembly {
                let slice_curr := add(tempBytes, 0x20)
                let slice_end := add(slice_curr, _length)

                for {
                    let array_current := add(_bytes, add(_start, 0x20))
                } lt(slice_curr, slice_end) {
                    slice_curr := add(slice_curr, 0x20)
                    array_current := add(array_current, 0x20)
                } {
                    mstore(slice_curr, mload(array_current))
                }
            }
        }

        return tempBytes;
    }

    /// Reads byte stream
    /// @return newOffset - offset + amount of bytes read
    /// @return data - actually read data
    // NOTE: theoretically possible overflow of (_offset + _length)
    function read(
        bytes memory _data,
        uint256 _offset,
        uint256 _length
    ) internal pure returns (uint256 newOffset, bytes memory data) {
        data = slice(_data, _offset, _length);
        newOffset = _offset + _length;
    }

    // NOTE: theoretically possible overflow of (_offset + 1)
    function readBool(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bool r) {
        newOffset = _offset + 1;
        r = uint8(_data[_offset]) != 0;
    }

    // NOTE: theoretically possible overflow of (_offset + 1)
    function readUint8(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint8 r) {
        newOffset = _offset + 1;
        r = uint8(_data[_offset]);
    }

    // NOTE: theoretically possible overflow of (_offset + 2)
    function readUInt16(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint16 r) {
        newOffset = _offset + 2;
        r = bytesToUInt16(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 3)
    function readUInt24(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint24 r) {
        newOffset = _offset + 3;
        r = bytesToUInt24(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 4)
    function readUInt32(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint32 r) {
        newOffset = _offset + 4;
        r = bytesToUInt32(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 16)
    function readUInt128(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint128 r) {
        newOffset = _offset + 16;
        r = bytesToUInt128(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 20)
    function readUInt160(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint160 r) {
        newOffset = _offset + 20;
        r = bytesToUInt160(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 20)
    function readAddress(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, address r) {
        newOffset = _offset + 20;
        r = bytesToAddress(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 20)
    function readBytes20(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bytes20 r) {
        newOffset = _offset + 20;
        r = bytesToBytes20(_data, _offset);
    }

    // NOTE: theoretically possible overflow of (_offset + 32)
    function readBytes32(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bytes32 r) {
        newOffset = _offset + 32;
        r = bytesToBytes32(_data, _offset);
    }

    /// Trim bytes into single word
    function trim(bytes memory _data, uint256 _newLength) internal pure returns (uint256 r) {
        require(_newLength <= 0x20, "10"); // new_length is longer than word
        require(_data.length >= _newLength, "11"); // data is to short

        uint256 a;
        assembly {
            a := mload(add(_data, 0x20)) // load bytes into uint256
        }

        return a >> ((0x20 - _newLength) * 8);
    }

    // Helper function for hex conversion.
    function halfByteToHex(bytes1 _byte) internal pure returns (bytes1 _hexByte) {
        require(uint8(_byte) < 0x10, "hbh11"); // half byte's value is out of 0..15 range.

        // "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated.
        return bytes1(uint8(0x66656463626139383736353433323130 >> (uint8(_byte) * 8)));
    }

    // Convert bytes to ASCII hex representation
    function bytesToHexASCIIBytes(bytes memory _input) internal pure returns (bytes memory _output) {
        bytes memory outStringBytes = new bytes(_input.length * 2);

        // code in `assembly` construction is equivalent of the next code:
        // for (uint i = 0; i < _input.length; ++i) {
        //     outStringBytes[i*2] = halfByteToHex(_input[i] >> 4);
        //     outStringBytes[i*2+1] = halfByteToHex(_input[i] & 0x0f);
        // }
        assembly {
            let input_curr := add(_input, 0x20)
            let input_end := add(input_curr, mload(_input))

            for {
                let out_curr := add(outStringBytes, 0x20)
            } lt(input_curr, input_end) {
                input_curr := add(input_curr, 0x01)
                out_curr := add(out_curr, 0x02)
            } {
                let curr_input_byte := shr(0xf8, mload(input_curr))
                // here outStringByte from each half of input byte calculates by the next:
                //
                // "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated.
                // outStringByte = byte (uint8 (0x66656463626139383736353433323130 >> (uint8 (_byteHalf) * 8)))
                mstore(
                    out_curr,
                    shl(0xf8, shr(mul(shr(0x04, curr_input_byte), 0x08), 0x66656463626139383736353433323130))
                )
                mstore(
                    add(out_curr, 0x01),
                    shl(0xf8, shr(mul(and(0x0f, curr_input_byte), 0x08), 0x66656463626139383736353433323130))
                )
            }
        }
        return outStringBytes;
    }
}

File 8 of 9 : ReentrancyGuard.sol
pragma solidity ^0.7.0;

// SPDX-License-Identifier: MIT OR Apache-2.0



/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 *
 * _Since v2.5.0:_ this module is now much more gas efficient, given net gas
 * metering changes introduced in the Istanbul hardfork.
 */
contract ReentrancyGuard {
    /// @dev Address of lock flag variable.
    /// @dev Flag is placed at random memory location to not interfere with Storage contract.
    uint256 private constant LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4; // keccak256("ReentrancyGuard") - 1;

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

    function initializeReentrancyGuard() internal {
        uint256 lockSlotOldValue;

        // Storing an initial non-zero value makes deployment a bit more
        // expensive, but in exchange every call to nonReentrant
        // will be cheaper.
        assembly {
            lockSlotOldValue := sload(LOCK_FLAG_ADDRESS)
            sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)
        }

        // Check that storage slot for reentrancy guard is empty to rule out possibility of double initialization
        require(lockSlotOldValue == 0, "1B");
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        uint256 _status;
        assembly {
            _status := sload(LOCK_FLAG_ADDRESS)
        }

        // On the first call to nonReentrant, _notEntered will be true
        require(_status == _NOT_ENTERED);

        // Any calls to nonReentrant after this point will fail
        assembly {
            sstore(LOCK_FLAG_ADDRESS, _ENTERED)
        }

        _;

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

File 9 of 9 : ITrustedTransfarableERC20.sol
/// @dev Interface of the ERC20 standard as defined in the EIP.
/// 1. Implements only `transfer` and `transferFrom` methods
/// 2. These methods return a boolean value in case of a non-revert call
/// NOTE: It is expected that if the function returns true, then the user's balance has
/// changed exactly by `amount` according to the ERC20 standard.
/// Note: Used to perform transfers for tokens that explicitly return a boolean value
/// (if the token returns any other data or does not return at all, then the function call will be reverted)
interface ITrustedTransfarableERC20 {
    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` 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 sender,
        address recipient,
        uint256 amount
    ) external returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"creatorAccountId","type":"uint32"},{"indexed":true,"internalType":"address","name":"creatorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"factoryAddress","type":"address"}],"name":"NFTFactoryRegisteredCreator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newGovernor","type":"address"}],"name":"NewGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"NewToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract TokenGovernance","name":"newTokenGovernance","type":"address"}],"name":"NewTokenGovernance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"}],"name":"SetDefaultNFTFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"TokenPausedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validatorAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"ValidatorStatusUpdate","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernor","type":"address"}],"name":"changeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract TokenGovernance","name":"_newTokenGovernance","type":"address"}],"name":"changeTokenGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultFactory","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_creatorAccountId","type":"uint32"},{"internalType":"address","name":"_creatorAddress","type":"address"}],"name":"getNFTFactory","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initializationParameters","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_tokenId","type":"uint16"}],"name":"isValidTokenId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"networkGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"nftFactories","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"pausedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_creatorAccountId","type":"uint32"},{"internalType":"address","name":"_creatorAddress","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"registerNFTFactoryCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"requireActiveValidator","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"requireGovernor","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setDefaultNFTFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"},{"internalType":"bool","name":"_tokenPaused","type":"bool"}],"name":"setTokenPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_validator","type":"address"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"tokenAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenGovernance","outputs":[{"internalType":"contract TokenGovernance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokens","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"upgradeParameters","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"}],"name":"validateTokenAddress","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50611302806100206000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063ce09e20d116100c3578063ead317621161007c578063ead3176214610514578063f39349ef1461053a578063f3a65bf914610542578063f5f84ed414610563578063fa52c7d814610589578063fc97a303146105af5761014d565b8063ce09e20d14610433578063d48bfca714610459578063d4b6846d1461047f578063e122b7d114610487578063e2c79268146104b9578063e4c0aaf4146104ee5761014d565b8063622574701161011557806362257470146102c557806378393d22146102f35780637e1c0c09146103195780638d1db94014610338578063b79eb8c714610340578063c4dcb92c146103725761014d565b806310603dad14610152578063253946451461018f578063439fab91146102015780634623c91d146102715780634b18bd0f1461029f575b600080fd5b6101736004803603602081101561016857600080fd5b503561ffff166105d5565b604080516001600160a01b039092168252519081900360200190f35b6101ff600480360360208110156101a557600080fd5b8101906020810181356401000000008111156101c057600080fd5b8201836020820111156101d257600080fd5b803590602001918460018302840111640100000000831117156101f457600080fd5b5090925090506105f0565b005b6101ff6004803603602081101561021757600080fd5b81019060208101813564010000000081111561023257600080fd5b82018360208201111561024457600080fd5b8035906020019184600183028401116401000000008311171561026657600080fd5b5090925090506105f4565b6101ff6004803603604081101561028757600080fd5b506001600160a01b038135169060200135151561062d565b6101ff600480360360208110156102b557600080fd5b50356001600160a01b03166106bc565b6101ff600480360360408110156102db57600080fd5b506001600160a01b0381351690602001351515610711565b6101ff6004803603602081101561030957600080fd5b50356001600160a01b0316610820565b610321610892565b6040805161ffff9092168252519081900360200190f35b6101736108a3565b6101736004803603604081101561035657600080fd5b50803563ffffffff1690602001356001600160a01b03166108b2565b6101ff6004803603606081101561038857600080fd5b63ffffffff823516916001600160a01b03602082013516918101906060810160408201356401000000008111156103be57600080fd5b8201836020820111156103d057600080fd5b803590602001918460018302840111640100000000831117156103f257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610953945050505050565b6101ff6004803603602081101561044957600080fd5b50356001600160a01b0316610a9f565b6101ff6004803603602081101561046f57600080fd5b50356001600160a01b0316610b77565b610173610cf7565b6101736004803603604081101561049d57600080fd5b50803563ffffffff1690602001356001600160a01b0316610d06565b6104da600480360360208110156104cf57600080fd5b503561ffff16610d2c565b604080519115158252519081900360200190f35b6101ff6004803603602081101561050457600080fd5b50356001600160a01b0316610d43565b6103216004803603602081101561052a57600080fd5b50356001600160a01b0316610df5565b610173610e49565b6104da6004803603602081101561055857600080fd5b503561ffff16610e58565b6101ff6004803603602081101561057957600080fd5b50356001600160a01b0316610e6d565b6104da6004803603602081101561059f57600080fd5b50356001600160a01b0316610eb4565b610321600480360360208110156105c557600080fd5b50356001600160a01b0316610ec9565b6001602052600090815260409020546001600160a01b031681565b5050565b60008282602081101561060657600080fd5b506000805491356001600160a01b03166001600160a01b0319909216919091179055505050565b61063633610e6d565b6001600160a01b03821660009081526003602052604090205460ff161515811515146105f0576001600160a01b038216600081815260036020908152604091829020805460ff1916851515908117909155825190815291517f065b77b53864e46fda3d8986acb51696223d6dde7ced42441eb150bae6d481369281900390910190a25050565b6001600160a01b03811660009081526003602052604090205460ff1661070e576040805162461bcd60e51b8152602060048201526002602482015261062d60f31b604482015290519081900360640190fd5b50565b61071a33610e6d565b6000306001600160a01b031663ead31762846040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561076957600080fd5b505afa15801561077d573d6000803e3d6000fd5b505050506040513d602081101561079357600080fd5b505161ffff811660009081526004602052604090205490915060ff1615158215151461081b5761ffff8116600090815260046020908152604091829020805460ff1916851515908117909155825190815291516001600160a01b038616927ff72cbadf0693609a042637541df35c63e7e074363dea6efb5c19d6c7814ceee992908290030190a25b505050565b61082933610e6d565b6005546001600160a01b0382811691161461070e57600580546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb24c0fc80a0c2a8c6a406f1f63ac240a949e45444715e77bcb06073a1a1d401c9181900360200190a150565b600054600160a01b900461ffff1681565b6005546001600160a01b031681565b63ffffffff821660009081526006602090815260408083206001600160a01b0380861685529252822054168015806108f057506108ee81610edf565b155b1561094a576007546001600160a01b0316610937576040805162461bcd60e51b8152602060048201526002602482015261667360f01b604482015290519081900360640190fd5b50506007546001600160a01b031661094d565b90505b92915050565b63ffffffff831660009081526006602090815260408083206001600160a01b03868116855292529091205416156109b5576040805162461bcd60e51b81526020600482015260016024820152605160f81b604482015290519081900360640190fd5b60006109c2848433610ee5565b80519060200120905060006109d783836110dd565b9050836001600160a01b0316816001600160a01b031614610a24576040805162461bcd60e51b8152602060048201526002602482015261777360f01b604482015290519081900360640190fd5b63ffffffff851660008181526006602090815260408083206001600160a01b0389168085529083529281902080546001600160a01b03191633908117909155815190815290519293927fa31b86f0827cd4eabf087b77e866f658278cb60e2d7c291d407edaada53408e0929181900390910190a35050505050565b610aa833610e6d565b6001600160a01b038116610ae9576040805162461bcd60e51b81526020600482015260036024820152626d623160e81b604482015290519081900360640190fd5b6007546001600160a01b031615610b2d576040805162461bcd60e51b815260206004820152600360248201526236b11960e91b604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f9678384f56a2d29e9db5747e5910c194dde921293922f2463582d8c25b96533090600090a250565b6005546001600160a01b03163314610bbb576040805162461bcd60e51b8152602060048201526002602482015261314560f01b604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205461ffff1615610c0f576040805162461bcd60e51b8152602060048201526002602482015261316560f01b604482015290519081900360640190fd5b6000546103ff600160a01b90910461ffff1610610c58576040805162461bcd60e51b815260206004820152600260248201526118b360f11b604482015290519081900360640190fd5b60008054600161ffff600160a01b808404821683018216810261ffff60a01b1990941693909317808555929092049091168083526020918252604080842080546001600160a01b0387166001600160a01b031990911681179091558085526002909352808420805461ffff1916831790555190928392917ffe74dea79bde70d1990ddb655bac45735b14f495ddc508cfab80b7729aa9d6689190a35050565b6007546001600160a01b031681565b60066020908152600092835260408084209091529082529020546001600160a01b031681565b600054600160a01b900461ffff9081169116111590565b6001600160a01b038116610d83576040805162461bcd60e51b815260206004820152600260248201526118b760f11b604482015290519081900360640190fd5b610d8c33610e6d565b6000546001600160a01b0382811691161461070e57600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5425363a03f182281120f5919107c49c7a1a623acc1cbc6df468b6f0c11fcf8c9181900360200190a150565b6001600160a01b03811660009081526002602052604081205461ffff168061094d576040805162461bcd60e51b8152602060048201526002602482015261316960f01b604482015290519081900360640190fd5b6000546001600160a01b031681565b60046020526000908152604090205460ff1681565b6000546001600160a01b0382811691161461070e576040805162461bcd60e51b8152602060048201526002602482015261316760f01b604482015290519081900360640190fd5b60036020526000908152604090205460ff1681565b60026020526000908152604090205461ffff1681565b3b151590565b6060610f1884604051602001808263ffffffff1660e01b81526004019150506040516020818303038152906040526111e9565b610f4c8460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b610f808460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3134310000006020820190815290603d0160216112ac823960210184805190602001908083835b60208310610fe45780518252601f199092019160209182019101610fc5565b51815160209384036101000a600019018019909216911617905268521b932b0ba37b91d160b51b919093019081528551600a90910192860191508083835b602083106110415780518252601f199092019160209182019101611022565b51815160209384036101000a60001901801990921691161790526852330b1ba37b93c9d160b51b919093019081528451600a90910192850191508083835b6020831061109e5780518252601f19909201916020918201910161107f565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405290509392505050565b60008251604114611119576040805162461bcd60e51b81526020600482015260016024820152600560fc1b604482015290519081900360640190fd5b60008060006020860151925060408601519150606086015160001a9050600060018683868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611192573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166111df576040805162461bcd60e51b81526020600482015260026024820152611c0d60f21b604482015290519081900360640190fd5b9695505050505050565b60606000825160020267ffffffffffffffff8111801561120857600080fd5b506040519080825280601f01601f191660200182016040528015611233576020820181803683370190505b5090506020830183518101602083015b818310156112a157825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050611243565b509194935050505056fe0a43726561746f722773206163636f756e7420494420696e207a6b53796e633a20a2646970667358221220c6a0c5ae82a2b4caaf3089a086a98d6633657bec5a18916b0fbdfbe041616c7b64736f6c63430007060033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061014d5760003560e01c8063ce09e20d116100c3578063ead317621161007c578063ead3176214610514578063f39349ef1461053a578063f3a65bf914610542578063f5f84ed414610563578063fa52c7d814610589578063fc97a303146105af5761014d565b8063ce09e20d14610433578063d48bfca714610459578063d4b6846d1461047f578063e122b7d114610487578063e2c79268146104b9578063e4c0aaf4146104ee5761014d565b8063622574701161011557806362257470146102c557806378393d22146102f35780637e1c0c09146103195780638d1db94014610338578063b79eb8c714610340578063c4dcb92c146103725761014d565b806310603dad14610152578063253946451461018f578063439fab91146102015780634623c91d146102715780634b18bd0f1461029f575b600080fd5b6101736004803603602081101561016857600080fd5b503561ffff166105d5565b604080516001600160a01b039092168252519081900360200190f35b6101ff600480360360208110156101a557600080fd5b8101906020810181356401000000008111156101c057600080fd5b8201836020820111156101d257600080fd5b803590602001918460018302840111640100000000831117156101f457600080fd5b5090925090506105f0565b005b6101ff6004803603602081101561021757600080fd5b81019060208101813564010000000081111561023257600080fd5b82018360208201111561024457600080fd5b8035906020019184600183028401116401000000008311171561026657600080fd5b5090925090506105f4565b6101ff6004803603604081101561028757600080fd5b506001600160a01b038135169060200135151561062d565b6101ff600480360360208110156102b557600080fd5b50356001600160a01b03166106bc565b6101ff600480360360408110156102db57600080fd5b506001600160a01b0381351690602001351515610711565b6101ff6004803603602081101561030957600080fd5b50356001600160a01b0316610820565b610321610892565b6040805161ffff9092168252519081900360200190f35b6101736108a3565b6101736004803603604081101561035657600080fd5b50803563ffffffff1690602001356001600160a01b03166108b2565b6101ff6004803603606081101561038857600080fd5b63ffffffff823516916001600160a01b03602082013516918101906060810160408201356401000000008111156103be57600080fd5b8201836020820111156103d057600080fd5b803590602001918460018302840111640100000000831117156103f257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610953945050505050565b6101ff6004803603602081101561044957600080fd5b50356001600160a01b0316610a9f565b6101ff6004803603602081101561046f57600080fd5b50356001600160a01b0316610b77565b610173610cf7565b6101736004803603604081101561049d57600080fd5b50803563ffffffff1690602001356001600160a01b0316610d06565b6104da600480360360208110156104cf57600080fd5b503561ffff16610d2c565b604080519115158252519081900360200190f35b6101ff6004803603602081101561050457600080fd5b50356001600160a01b0316610d43565b6103216004803603602081101561052a57600080fd5b50356001600160a01b0316610df5565b610173610e49565b6104da6004803603602081101561055857600080fd5b503561ffff16610e58565b6101ff6004803603602081101561057957600080fd5b50356001600160a01b0316610e6d565b6104da6004803603602081101561059f57600080fd5b50356001600160a01b0316610eb4565b610321600480360360208110156105c557600080fd5b50356001600160a01b0316610ec9565b6001602052600090815260409020546001600160a01b031681565b5050565b60008282602081101561060657600080fd5b506000805491356001600160a01b03166001600160a01b0319909216919091179055505050565b61063633610e6d565b6001600160a01b03821660009081526003602052604090205460ff161515811515146105f0576001600160a01b038216600081815260036020908152604091829020805460ff1916851515908117909155825190815291517f065b77b53864e46fda3d8986acb51696223d6dde7ced42441eb150bae6d481369281900390910190a25050565b6001600160a01b03811660009081526003602052604090205460ff1661070e576040805162461bcd60e51b8152602060048201526002602482015261062d60f31b604482015290519081900360640190fd5b50565b61071a33610e6d565b6000306001600160a01b031663ead31762846040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561076957600080fd5b505afa15801561077d573d6000803e3d6000fd5b505050506040513d602081101561079357600080fd5b505161ffff811660009081526004602052604090205490915060ff1615158215151461081b5761ffff8116600090815260046020908152604091829020805460ff1916851515908117909155825190815291516001600160a01b038616927ff72cbadf0693609a042637541df35c63e7e074363dea6efb5c19d6c7814ceee992908290030190a25b505050565b61082933610e6d565b6005546001600160a01b0382811691161461070e57600580546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb24c0fc80a0c2a8c6a406f1f63ac240a949e45444715e77bcb06073a1a1d401c9181900360200190a150565b600054600160a01b900461ffff1681565b6005546001600160a01b031681565b63ffffffff821660009081526006602090815260408083206001600160a01b0380861685529252822054168015806108f057506108ee81610edf565b155b1561094a576007546001600160a01b0316610937576040805162461bcd60e51b8152602060048201526002602482015261667360f01b604482015290519081900360640190fd5b50506007546001600160a01b031661094d565b90505b92915050565b63ffffffff831660009081526006602090815260408083206001600160a01b03868116855292529091205416156109b5576040805162461bcd60e51b81526020600482015260016024820152605160f81b604482015290519081900360640190fd5b60006109c2848433610ee5565b80519060200120905060006109d783836110dd565b9050836001600160a01b0316816001600160a01b031614610a24576040805162461bcd60e51b8152602060048201526002602482015261777360f01b604482015290519081900360640190fd5b63ffffffff851660008181526006602090815260408083206001600160a01b0389168085529083529281902080546001600160a01b03191633908117909155815190815290519293927fa31b86f0827cd4eabf087b77e866f658278cb60e2d7c291d407edaada53408e0929181900390910190a35050505050565b610aa833610e6d565b6001600160a01b038116610ae9576040805162461bcd60e51b81526020600482015260036024820152626d623160e81b604482015290519081900360640190fd5b6007546001600160a01b031615610b2d576040805162461bcd60e51b815260206004820152600360248201526236b11960e91b604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f9678384f56a2d29e9db5747e5910c194dde921293922f2463582d8c25b96533090600090a250565b6005546001600160a01b03163314610bbb576040805162461bcd60e51b8152602060048201526002602482015261314560f01b604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205461ffff1615610c0f576040805162461bcd60e51b8152602060048201526002602482015261316560f01b604482015290519081900360640190fd5b6000546103ff600160a01b90910461ffff1610610c58576040805162461bcd60e51b815260206004820152600260248201526118b360f11b604482015290519081900360640190fd5b60008054600161ffff600160a01b808404821683018216810261ffff60a01b1990941693909317808555929092049091168083526020918252604080842080546001600160a01b0387166001600160a01b031990911681179091558085526002909352808420805461ffff1916831790555190928392917ffe74dea79bde70d1990ddb655bac45735b14f495ddc508cfab80b7729aa9d6689190a35050565b6007546001600160a01b031681565b60066020908152600092835260408084209091529082529020546001600160a01b031681565b600054600160a01b900461ffff9081169116111590565b6001600160a01b038116610d83576040805162461bcd60e51b815260206004820152600260248201526118b760f11b604482015290519081900360640190fd5b610d8c33610e6d565b6000546001600160a01b0382811691161461070e57600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5425363a03f182281120f5919107c49c7a1a623acc1cbc6df468b6f0c11fcf8c9181900360200190a150565b6001600160a01b03811660009081526002602052604081205461ffff168061094d576040805162461bcd60e51b8152602060048201526002602482015261316960f01b604482015290519081900360640190fd5b6000546001600160a01b031681565b60046020526000908152604090205460ff1681565b6000546001600160a01b0382811691161461070e576040805162461bcd60e51b8152602060048201526002602482015261316760f01b604482015290519081900360640190fd5b60036020526000908152604090205460ff1681565b60026020526000908152604090205461ffff1681565b3b151590565b6060610f1884604051602001808263ffffffff1660e01b81526004019150506040516020818303038152906040526111e9565b610f4c8460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b610f808460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3134310000006020820190815290603d0160216112ac823960210184805190602001908083835b60208310610fe45780518252601f199092019160209182019101610fc5565b51815160209384036101000a600019018019909216911617905268521b932b0ba37b91d160b51b919093019081528551600a90910192860191508083835b602083106110415780518252601f199092019160209182019101611022565b51815160209384036101000a60001901801990921691161790526852330b1ba37b93c9d160b51b919093019081528451600a90910192850191508083835b6020831061109e5780518252601f19909201916020918201910161107f565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405290509392505050565b60008251604114611119576040805162461bcd60e51b81526020600482015260016024820152600560fc1b604482015290519081900360640190fd5b60008060006020860151925060408601519150606086015160001a9050600060018683868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611192573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166111df576040805162461bcd60e51b81526020600482015260026024820152611c0d60f21b604482015290519081900360640190fd5b9695505050505050565b60606000825160020267ffffffffffffffff8111801561120857600080fd5b506040519080825280601f01601f191660200182016040528015611233576020820181803683370190505b5090506020830183518101602083015b818310156112a157825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050611243565b509194935050505056fe0a43726561746f722773206163636f756e7420494420696e207a6b53796e633a20a2646970667358221220c6a0c5ae82a2b4caaf3089a086a98d6633657bec5a18916b0fbdfbe041616c7b64736f6c63430007060033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.