ETH Price: $2,874.41 (-10.25%)
Gas: 13 Gwei

Contract

0x2Dbc18A3ac126abE1fF90A83Bbc3947ff7912Afb
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x60806040151147022022-07-10 11:42:52725 days ago1657453372IN
 Create: TokensAndRamping
0 ETH0.0485167211.02548458

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokensAndRamping

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity Multiple files format)

File 1 of 37: TokensAndRamping.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "StarkExForcedActionState.sol";
import "ERC721Receiver.sol";
import "ERC1155Receiver.sol";
import "Freezable.sol";
import "KeyGetters.sol";
import "TokenRegister.sol";
import "TokenTransfers.sol";
import "MainGovernance.sol";
import "AcceptModifications.sol";
import "Deposits.sol";
import "TokenAssetData.sol";
import "TokenQuantization.sol";
import "Withdrawals.sol";
import "SubContractor.sol";

contract TokensAndRamping is
    ERC1155Receiver,
    ERC721Receiver,
    SubContractor,
    Freezable,
    MainGovernance,
    AcceptModifications,
    StarkExForcedActionState,
    TokenAssetData,
    TokenQuantization,
    TokenRegister,
    TokenTransfers,
    KeyGetters,
    Deposits,
    Withdrawals
{
    function initialize(
        bytes calldata /* data */
    ) external override {
        revert("NOT_IMPLEMENTED");
    }

    function initializerSize() external view override returns (uint256) {
        return 0;
    }

    function validatedSelectors() external pure override returns (bytes4[] memory selectors) {
        uint256 len_ = 6;
        uint256 index_ = 0;

        selectors = new bytes4[](len_);
        selectors[index_++] = Deposits.depositCancel.selector;
        selectors[index_++] = Deposits.depositWithTokenIdReclaim.selector;
        selectors[index_++] = Deposits.depositReclaim.selector;
        selectors[index_++] = Withdrawals.withdraw.selector;
        selectors[index_++] = Withdrawals.withdrawAndMint.selector;
        selectors[index_++] = Withdrawals.withdrawWithTokenId.selector;
        require(index_ == len_, "INCORRECT_SELECTORS_ARRAY_LENGTH");
    }

    function identify() external pure override returns (string memory) {
        return "StarkWare_TokensAndRamping_2022_2";
    }
}

File 2 of 37: AcceptModifications.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "LibConstants.sol";
import "MAcceptModifications.sol";
import "MTokenQuantization.sol";
import "MainStorage.sol";

/*
  Interface containing actions a verifier can invoke on the state.
  The contract containing the state should implement these and verify correctness.
*/
abstract contract AcceptModifications is
    MainStorage,
    LibConstants,
    MAcceptModifications,
    MTokenQuantization
{
    event LogWithdrawalAllowed(
        uint256 ownerKey,
        uint256 assetType,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount
    );

    event LogNftWithdrawalAllowed(uint256 ownerKey, uint256 assetId);

    event LogAssetWithdrawalAllowed(uint256 ownerKey, uint256 assetId, uint256 quantizedAmount);

    event LogMintableWithdrawalAllowed(uint256 ownerKey, uint256 assetId, uint256 quantizedAmount);

    /*
      Transfers funds from the on-chain deposit area to the off-chain area.
      Implemented in the Deposits contracts.
    */
    function acceptDeposit(
        uint256 ownerKey,
        uint256 vaultId,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal virtual override {
        // Fetch deposit.
        require(
            pendingDeposits[ownerKey][assetId][vaultId] >= quantizedAmount,
            "DEPOSIT_INSUFFICIENT"
        );

        // Subtract accepted quantized amount.
        pendingDeposits[ownerKey][assetId][vaultId] -= quantizedAmount;
    }

    /*
      Transfers funds from the off-chain area to the on-chain withdrawal area.
    */
    function allowWithdrawal(
        uint256 ownerKey,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal override {
        // Fetch withdrawal.
        uint256 withdrawal = pendingWithdrawals[ownerKey][assetId];

        // Add accepted quantized amount.
        withdrawal += quantizedAmount;
        require(withdrawal >= quantizedAmount, "WITHDRAWAL_OVERFLOW");

        // Store withdrawal.
        pendingWithdrawals[ownerKey][assetId] = withdrawal;

        // Log event.
        uint256 presumedAssetType = assetId;
        if (registeredAssetType[presumedAssetType]) {
            emit LogWithdrawalAllowed(
                ownerKey,
                presumedAssetType,
                fromQuantized(presumedAssetType, quantizedAmount),
                quantizedAmount
            );
        } else if (assetId == ((assetId & MASK_240) | MINTABLE_ASSET_ID_FLAG)) {
            emit LogMintableWithdrawalAllowed(ownerKey, assetId, quantizedAmount);
        } else {
            // Default case is Non-Mintable ERC721 or ERC1155 asset id.
            // In ERC721 and ERC1155 cases, assetId is not the assetType.
            require(assetId == assetId & MASK_250, "INVALID_ASSET_ID");
            // If withdrawal amount is 1, the asset could be either NFT or SFT. In that case, both
            // NFT and general events will be emitted so that the listened for event is captured.
            // When withdrawal is greater than 1, it must be SFT and only one event will be emitted.
            if (withdrawal <= 1) {
                emit LogNftWithdrawalAllowed(ownerKey, assetId);
            }
            emit LogAssetWithdrawalAllowed(ownerKey, assetId, quantizedAmount);
        }
    }

    // Verifier authorizes withdrawal.
    function acceptWithdrawal(
        uint256 ownerKey,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal virtual override {
        allowWithdrawal(ownerKey, assetId, quantizedAmount);
    }
}

File 3 of 37: ActionHash.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MainStorage.sol";
import "LibConstants.sol";

/*
  Calculation action hash for the various forced actions in a generic manner.
*/
contract ActionHash is MainStorage, LibConstants {
    function getActionHash(string memory actionName, bytes memory packedActionParameters)
        internal
        pure
        returns (bytes32 actionHash)
    {
        actionHash = keccak256(abi.encodePacked(actionName, packedActionParameters));
    }

    function setActionHash(bytes32 actionHash, bool premiumCost) internal {
        // The rate of forced trade requests is restricted.
        // First restriction is by capping the number of requests in a block.
        // User can override this cap by requesting with a permium flag set,
        // in this case, the gas cost is high (~1M) but no "technical" limit is set.
        // However, the high gas cost creates an obvious limitation due to the block gas limit.
        if (premiumCost) {
            for (uint256 i = 0; i < 21129; i++) {}
        } else {
            require(
                forcedRequestsInBlock[block.number] < MAX_FORCED_ACTIONS_REQS_PER_BLOCK,
                "MAX_REQUESTS_PER_BLOCK_REACHED"
            );
            forcedRequestsInBlock[block.number] += 1;
        }
        forcedActionRequests[actionHash] = block.timestamp;
        actionHashList.push(actionHash);
    }

    function getActionCount() external view returns (uint256) {
        return actionHashList.length;
    }

    function getActionHashByIndex(uint256 actionIndex) external view returns (bytes32) {
        require(actionIndex < actionHashList.length, "ACTION_INDEX_TOO_HIGH");
        return actionHashList[actionIndex];
    }
}

File 4 of 37: Common.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/*
  Common Utility librarries.
  I. Addresses (extending address).
*/
library Addresses {
    function isContract(address account) internal view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    function performEthTransfer(address recipient, uint256 amount) internal {
        (bool success, ) = recipient.call{value: amount}(""); // NOLINT: low-level-calls.
        require(success, "ETH_TRANSFER_FAILED");
    }

    /*
      Safe wrapper around ERC20/ERC721 calls.
      This is required because many deployed ERC20 contracts don't return a value.
      See https://github.com/ethereum/solidity/issues/4116.
    */
    function safeTokenContractCall(address tokenAddress, bytes memory callData) internal {
        require(isContract(tokenAddress), "BAD_TOKEN_ADDRESS");
        // NOLINTNEXTLINE: low-level-calls.
        (bool success, bytes memory returndata) = tokenAddress.call(callData);
        require(success, string(returndata));

        if (returndata.length > 0) {
            require(abi.decode(returndata, (bool)), "TOKEN_OPERATION_FAILED");
        }
    }

    /*
      Validates that the passed contract address is of a real contract,
      and that its id hash (as infered fromn identify()) matched the expected one.
    */
    function validateContractId(address contractAddress, bytes32 expectedIdHash) internal {
        require(isContract(contractAddress), "ADDRESS_NOT_CONTRACT");
        (bool success, bytes memory returndata) = contractAddress.call( // NOLINT: low-level-calls.
            abi.encodeWithSignature("identify()")
        );
        require(success, "FAILED_TO_IDENTIFY_CONTRACT");
        string memory realContractId = abi.decode(returndata, (string));
        require(
            keccak256(abi.encodePacked(realContractId)) == expectedIdHash,
            "UNEXPECTED_CONTRACT_IDENTIFIER"
        );
    }
}

/*
  II. StarkExTypes - Common data types.
*/
library StarkExTypes {
    // Structure representing a list of verifiers (validity/availability).
    // A statement is valid only if all the verifiers in the list agree on it.
    // Adding a verifier to the list is immediate - this is used for fast resolution of
    // any soundness issues.
    // Removing from the list is time-locked, to ensure that any user of the system
    // not content with the announced removal has ample time to leave the system before it is
    // removed.
    struct ApprovalChainData {
        address[] list;
        // Represents the time after which the verifier with the given address can be removed.
        // Removal of the verifier with address A is allowed only in the case the value
        // of unlockedForRemovalTime[A] != 0 and unlockedForRemovalTime[A] < (current time).
        mapping(address => uint256) unlockedForRemovalTime;
    }
}

File 5 of 37: Deposits.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "LibConstants.sol";
import "MAcceptModifications.sol";
import "MDeposits.sol";
import "MTokenQuantization.sol";
import "MTokenAssetData.sol";
import "MFreezable.sol";
import "MKeyGetters.sol";
import "MTokenTransfers.sol";
import "MainStorage.sol";

/**
  For a user to perform a deposit to the contract two calls need to take place:

  1. A call to an ERC20 contract, authorizing this contract to transfer funds on behalf of the user.
  2. A call to :sol:func:`deposit` indicating the starkKey, amount, asset type and target vault ID to which to send the deposit.

  The amount should be quantized, according to the specific quantization defined for the asset type.

  The result of the operation, assuming all requirements are met, is that an amount of ERC20 tokens
  equaling the amount specified in the :sol:func:`deposit` call times the quantization factor is
  transferred on behalf of the user to the contract. In addition, the contract adds the funds to an
  accumulator of pending deposits for the provided user, asset ID and vault ID.

  Once a deposit is made, the exchange may include it in a proof which will result in addition
  of the amount(s) deposited to the off-chain vault with the specified ID. When the contract
  receives such valid proof, it deducts the transfered funds from the pending deposits for the
  specified Stark key, asset ID and vault ID.

  The exchange will not be able to move the deposited funds to the off-chain vault if the Stark key
  is not registered in the system.

  Until that point, the user may cancel the deposit by performing a time-locked cancel-deposit
  operation consisting of two calls:

  1. A call to :sol:func:`depositCancel`, setting a timer to enable reclaiming the deposit. Until this timer expires the user cannot reclaim funds as the exchange may still be processing the deposit for inclusion in the off chain vault.
  2. A call to :sol:func:`depositReclaim`, to perform the actual transfer of funds from the contract back to the ERC20 contract. This will only succeed if the timer set in the previous call has expired. The result should be the transfer of all funds not accounted for in proofs for off-chain inclusion, back to the user account on the ERC20 contract.

  Calling depositCancel and depositReclaim can only be done via an ethKey that is associated with
  that vault's starkKey. This is enforced by the contract.

*/
abstract contract Deposits is
    MainStorage,
    LibConstants,
    MAcceptModifications,
    MDeposits,
    MTokenQuantization,
    MTokenAssetData,
    MFreezable,
    MKeyGetters,
    MTokenTransfers
{
    event LogDeposit(
        address depositorEthKey,
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount
    );

    event LogNftDeposit(
        address depositorEthKey,
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId
    );

    event LogDepositWithTokenId(
        address depositorEthKey,
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount
    );

    event LogDepositCancel(uint256 starkKey, uint256 vaultId, uint256 assetId);

    event LogDepositCancelReclaimed(
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount
    );

    event LogDepositNftCancelReclaimed(
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId
    );

    event LogDepositWithTokenIdCancelReclaimed(
        uint256 starkKey,
        uint256 vaultId,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount
    );

    function getDepositBalance(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId
    ) external view returns (uint256) {
        uint256 presumedAssetType = assetId;
        return fromQuantized(presumedAssetType, pendingDeposits[starkKey][assetId][vaultId]);
    }

    function getQuantizedDepositBalance(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId
    ) external view returns (uint256) {
        return pendingDeposits[starkKey][assetId][vaultId];
    }

    function depositNft(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId,
        uint256 tokenId
    ) external notFrozen {
        require(isERC721(assetType), "NOT_ERC721_TOKEN");
        depositWithTokenId(starkKey, assetType, tokenId, vaultId, 1);
    }

    function depositERC1155(
        uint256 starkKey,
        uint256 assetType,
        uint256 tokenId,
        uint256 vaultId,
        uint256 quantizedAmount
    ) external notFrozen {
        require(isERC1155(assetType), "NOT_ERC1155_TOKEN");
        depositWithTokenId(starkKey, assetType, tokenId, vaultId, quantizedAmount);
    }

    function depositStateUpdate(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId,
        uint256 quantizedAmount
    ) private returns (uint256) {
        // Checks for overflow and updates the pendingDeposits balance.
        uint256 vaultBalance = pendingDeposits[starkKey][assetId][vaultId];
        vaultBalance += quantizedAmount;
        require(vaultBalance >= quantizedAmount, "DEPOSIT_OVERFLOW");
        pendingDeposits[starkKey][assetId][vaultId] = vaultBalance;

        // Disable the cancellationRequest timeout when users deposit into their own account.
        if (
            isMsgSenderKeyOwner(starkKey) && cancellationRequests[starkKey][assetId][vaultId] != 0
        ) {
            delete cancellationRequests[starkKey][assetId][vaultId];
        }

        // Returns the updated vault balance.
        return vaultBalance;
    }

    function depositWithTokenId(
        uint256 starkKey,
        uint256 assetType,
        uint256 tokenId,
        uint256 vaultId,
        uint256 quantizedAmount
    ) public notFrozen {
        // The vaultId is not validated but should be in the allowed range supported by the
        // exchange. If not, it will be ignored by the exchange and the starkKey owner may reclaim
        // the funds by using depositCancel + depositReclaim.
        require(isAssetTypeWithTokenId(assetType), "INVALID_ASSET_TYPE");

        uint256 assetId = calculateAssetIdWithTokenId(assetType, tokenId);

        // Updates the pendingDeposits balance and clears cancellationRequests when applicable.
        uint256 newVaultBalance = depositStateUpdate(starkKey, assetId, vaultId, quantizedAmount);

        // No need to verify amount > 0, a deposit with amount = 0 can be used to undo cancellation.
        if (isERC721(assetType)) {
            require(newVaultBalance <= 1, "ILLEGAL_ERC721_AMOUNT");
            emit LogNftDeposit(msg.sender, starkKey, vaultId, assetType, tokenId, assetId);
        }
        // Transfer the tokens to the Deposit contract.
        transferInWithTokenId(assetType, tokenId, quantizedAmount);
        // Log event.
        emit LogDepositWithTokenId(
            msg.sender,
            starkKey,
            vaultId,
            assetType,
            tokenId,
            assetId,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount
        );
    }

    function getCancellationRequest(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId
    ) external view returns (uint256 request) {
        request = cancellationRequests[starkKey][assetId][vaultId];
    }

    function depositERC20(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId,
        uint256 quantizedAmount
    ) public override {
        deposit(starkKey, assetType, vaultId, quantizedAmount);
    }

    // NOLINTNEXTLINE: locked-ether.
    function depositEth(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId
    ) public payable override {
        require(isEther(assetType), "INVALID_ASSET_TYPE");
        deposit(starkKey, assetType, vaultId, toQuantized(assetType, msg.value));
    }

    function deposit(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId,
        uint256 quantizedAmount
    ) public notFrozen {
        // The vaultId is not validated but should be in the allowed range supported by the
        // exchange. If not, it will be ignored by the exchange and the starkKey owner may reclaim
        // the funds by using depositCancel + depositReclaim.

        // No need to verify amount > 0, a deposit with amount = 0 can be used to undo cancellation.
        require(!isMintableAssetType(assetType), "MINTABLE_ASSET_TYPE");
        require(isFungibleAssetType(assetType), "NON_FUNGIBLE_ASSET_TYPE");

        uint256 assetId = assetType;

        // Updates the pendingDeposits balance and clears cancellationRequests when applicable.
        depositStateUpdate(starkKey, assetId, vaultId, quantizedAmount);

        // Transfer the tokens to the Deposit contract.
        transferIn(assetType, quantizedAmount);

        // Log event.
        emit LogDeposit(
            msg.sender,
            starkKey,
            vaultId,
            assetType,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount
        );
    }

    function deposit(
        // NOLINT: locked-ether.
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId
    ) external payable {
        require(isEther(assetType), "INVALID_ASSET_TYPE");
        deposit(starkKey, assetType, vaultId, toQuantized(assetType, msg.value));
    }

    function depositCancel(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId
    )
        external
        onlyKeyOwner(starkKey)
    // No notFrozen modifier: This function can always be used, even when frozen.
    {
        // Start the timeout.
        cancellationRequests[starkKey][assetId][vaultId] = block.timestamp;

        // Log event.
        emit LogDepositCancel(starkKey, vaultId, assetId);
    }

    function clearCancelledDeposit(
        uint256 starkKey,
        uint256 assetId,
        uint256 vaultId
    ) private returns (uint256) {
        // Make sure enough time has passed.
        uint256 requestTime = cancellationRequests[starkKey][assetId][vaultId];
        require(requestTime != 0, "DEPOSIT_NOT_CANCELED");
        uint256 freeTime = requestTime + DEPOSIT_CANCEL_DELAY;
        assert(freeTime >= DEPOSIT_CANCEL_DELAY);
        require(block.timestamp >= freeTime, "DEPOSIT_LOCKED"); // NOLINT: timestamp.

        // Clear deposit.
        uint256 quantizedAmount = pendingDeposits[starkKey][assetId][vaultId];
        delete pendingDeposits[starkKey][assetId][vaultId];
        delete cancellationRequests[starkKey][assetId][vaultId];

        // Return the cleared amount so it can be transferred back to the reclaimer.
        return quantizedAmount;
    }

    function depositReclaim(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId
    )
        external
        onlyKeyOwner(starkKey)
    // No notFrozen modifier: This function can always be used, even when frozen.
    {
        require(isFungibleAssetType(assetType), "NON_FUNGIBLE_ASSET_TYPE");

        // Clear deposit and attain the cleared amount to be transferred out.
        uint256 assetId = assetType;
        uint256 quantizedAmount = clearCancelledDeposit(starkKey, assetId, vaultId);

        // Refund deposit.
        transferOut(msg.sender, assetType, quantizedAmount);

        // Log event.
        emit LogDepositCancelReclaimed(
            starkKey,
            vaultId,
            assetType,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount
        );
    }

    function depositWithTokenIdReclaim(
        uint256 starkKey,
        uint256 assetType,
        uint256 tokenId,
        uint256 vaultId
    )
        public
        onlyKeyOwner(starkKey)
    // No notFrozen modifier: This function can always be used, even when frozen.
    {
        require(isAssetTypeWithTokenId(assetType), "INVALID_ASSET_TYPE");

        // Clear deposit and attain the cleared amount to be transferred out.
        uint256 assetId = calculateAssetIdWithTokenId(assetType, tokenId);
        uint256 quantizedAmount = clearCancelledDeposit(starkKey, assetId, vaultId);

        if (quantizedAmount > 0) {
            // Refund deposit.
            transferOutWithTokenId(msg.sender, assetType, tokenId, quantizedAmount);
        }

        // Log event.
        if (isERC721(assetType)) {
            emit LogDepositNftCancelReclaimed(starkKey, vaultId, assetType, tokenId, assetId);
        }
        emit LogDepositWithTokenIdCancelReclaimed(
            starkKey,
            vaultId,
            assetType,
            tokenId,
            assetId,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount
        );
    }

    function depositNftReclaim(
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId,
        uint256 tokenId
    )
        external
        onlyKeyOwner(starkKey)
    // No notFrozen modifier: This function can always be used, even when frozen.
    {
        depositWithTokenIdReclaim(starkKey, assetType, tokenId, vaultId);
    }
}

File 6 of 37: ERC1155Receiver.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "IERC1155Receiver.sol";

/*
  ERC1155 token receiver interface.
  EIP-1155 requires any contract receiving ERC1155 tokens to implement IERC1155Receiver interface.
  By EIP:
  1. safeTransferFrom API of ERC1155 shall call onERC1155Received on the receiving contract.
  2. safeBatchTransferFrom API of ERC1155 to call onERC1155BatchReceived on the receiving contract.

  Have the receiving contract failed to respond as expected, the safe transfer functions shall be reverted.
*/
contract ERC1155Receiver is IERC1155Receiver {
    /**
      Handles the receipt of a single ERC1155 token type.
      @param `operator` The address which called `safeTransferFrom` function
      @param `from` The address which previously owned the token
      @param `id` The identifier of the token which is being transferred
      @param `value` the amount of token units being transferred
      @param `data` Additional data with no specified format
      Returns:
      When invoked by the receiving contract, satisfying the deposit pattern (i.e. operator == this)
      `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` is returned.
      In all other cases returns `bytes4(0)`, which should invoke an error of the form
      `ERC1155: ERC1155Receiver rejected tokens`.
    */
    function onERC1155Received(
        address operator,
        address, // from
        uint256, // id
        uint256, // value
        bytes calldata // data
    ) external override returns (bytes4) {
        return (operator == address(this) ? this.onERC1155Received.selector : bytes4(0));
    }

    /**
      Handles the receipt of multiple ERC1155 token types.
      @param `operator` The address which called `safeBatchTransferFrom` function
      @param `from` The address which previously owned the token
      @param `ids` The identifier of the token which is being transferred
      @param `values` the amount of token units being transferred
      @param `data` Additional data with no specified format
      Returns:
      When invoked by the receiving contract, satisfying the deposit pattern (i.e. operator == this)
      `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256,uint256,bytes)"))` is returned.
      In all other cases returns `bytes4(0)`, which should invoke an error of the form
      `ERC1155: ERC1155Receiver rejected tokens`.

      Note: a rejection value `bytes4(0)` is to be expected. Batch deposits are unsupported by StarkEx.
    */
    function onERC1155BatchReceived(
        address operator,
        address, // from
        uint256[] calldata, // ids
        uint256[] calldata, // values
        bytes calldata // data
    ) external override returns (bytes4) {
        return (operator == address(this) ? this.onERC1155BatchReceived.selector : bytes4(0));
    }
}

File 7 of 37: ERC721Receiver.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "IERC721Receiver.sol";

/*
  ERC721 token receiver interface
  EIP-721 requires any contract receiving ERC721 tokens to implement IERC721Receiver interface.
  By EIP, safeTransferFrom API of ERC721 shall call onERC721Received on the receiving contract.

  Have the receiving contract failed to respond as expected, the safeTransferFrom shall be reverted.

  Params:
  `operator` The address which called `safeTransferFrom` function
  `from` The address which previously owned the token
  `tokenId` The NFT identifier which is being transferred
  `data` Additional data with no specified format

  Returns:
  When invoked by the main contract, following the deposit pattern:
   `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, which indicates success.
  In all other cases: `bytes4(0)`, which should fail ERC721's safeTransferFrom.
*/
contract ERC721Receiver is IERC721Receiver {
    function onERC721Received(
        address operator, // The address which called `safeTransferFrom` function.
        address, // from - The address which previously owned the token.
        uint256, // tokenId -  The NFT identifier which is being transferred.
        bytes calldata // data - Additional data with no specified format.
    ) external override returns (bytes4) {
        return (operator == address(this) ? this.onERC721Received.selector : bytes4(0));
    }
}

File 8 of 37: Freezable.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "LibConstants.sol";
import "MFreezable.sol";
import "MGovernance.sol";
import "MainStorage.sol";

/*
  Implements MFreezable.
*/
abstract contract Freezable is MainStorage, LibConstants, MGovernance, MFreezable {
    event LogFrozen();
    event LogUnFrozen();

    function isFrozen() public view override returns (bool) {
        return stateFrozen;
    }

    function validateFreezeRequest(uint256 requestTime) internal override {
        require(requestTime != 0, "FORCED_ACTION_UNREQUESTED");
        // Verify timer on escape request.
        uint256 freezeTime = requestTime + FREEZE_GRACE_PERIOD;

        // Prevent wraparound.
        assert(freezeTime >= FREEZE_GRACE_PERIOD);
        require(block.timestamp >= freezeTime, "FORCED_ACTION_PENDING"); // NOLINT: timestamp.

        // Forced action requests placed before freeze, are no longer valid after the un-freeze.
        require(freezeTime > unFreezeTime, "REFREEZE_ATTEMPT");
    }

    function freeze() internal override notFrozen {
        unFreezeTime = block.timestamp + UNFREEZE_DELAY;

        // Update state.
        stateFrozen = true;

        // Log event.
        emit LogFrozen();
    }

    function unFreeze() external onlyFrozen onlyGovernance {
        require(block.timestamp >= unFreezeTime, "UNFREEZE_NOT_ALLOWED_YET");

        // Update state.
        stateFrozen = false;

        // Increment roots to invalidate them, w/o losing information.
        validiumVaultRoot += 1;
        rollupVaultRoot += 1;
        orderRoot += 1;

        // Log event.
        emit LogUnFrozen();
    }
}

File 9 of 37: Governance.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MGovernance.sol";

/*
  Implements Generic Governance, applicable for both proxy and main contract, and possibly others.
  Notes:
   The use of the same function names by both the Proxy and a delegated implementation
   is not possible since calling the implementation functions is done via the default function
   of the Proxy. For this reason, for example, the implementation of MainContract (MainGovernance)
   exposes mainIsGovernor, which calls the internal _isGovernor method.
*/
abstract contract Governance is MGovernance {
    event LogNominatedGovernor(address nominatedGovernor);
    event LogNewGovernorAccepted(address acceptedGovernor);
    event LogRemovedGovernor(address removedGovernor);
    event LogNominationCancelled();

    function getGovernanceInfo() internal view virtual returns (GovernanceInfoStruct storage);

    /*
      Current code intentionally prevents governance re-initialization.
      This may be a problem in an upgrade situation, in a case that the upgrade-to implementation
      performs an initialization (for real) and within that calls initGovernance().

      Possible workarounds:
      1. Clearing the governance info altogether by changing the MAIN_GOVERNANCE_INFO_TAG.
         This will remove existing main governance information.
      2. Modify the require part in this function, so that it will exit quietly
         when trying to re-initialize (uncomment the lines below).
    */
    function initGovernance() internal {
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        require(!gub.initialized, "ALREADY_INITIALIZED");
        gub.initialized = true; // to ensure addGovernor() won't fail.
        // Add the initial governer.
        addGovernor(msg.sender);
    }

    function _isGovernor(address testGovernor) internal view override returns (bool) {
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        return gub.effectiveGovernors[testGovernor];
    }

    /*
      Cancels the nomination of a governor candidate.
    */
    function _cancelNomination() internal onlyGovernance {
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        gub.candidateGovernor = address(0x0);
        emit LogNominationCancelled();
    }

    function _nominateNewGovernor(address newGovernor) internal onlyGovernance {
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        require(!_isGovernor(newGovernor), "ALREADY_GOVERNOR");
        gub.candidateGovernor = newGovernor;
        emit LogNominatedGovernor(newGovernor);
    }

    /*
      The addGovernor is called in two cases:
      1. by _acceptGovernance when a new governor accepts its role.
      2. by initGovernance to add the initial governor.
      The difference is that the init path skips the nominate step
      that would fail because of the onlyGovernance modifier.
    */
    function addGovernor(address newGovernor) private {
        require(!_isGovernor(newGovernor), "ALREADY_GOVERNOR");
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        gub.effectiveGovernors[newGovernor] = true;
    }

    function _acceptGovernance() internal {
        // The new governor was proposed as a candidate by the current governor.
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        require(msg.sender == gub.candidateGovernor, "ONLY_CANDIDATE_GOVERNOR");

        // Update state.
        addGovernor(gub.candidateGovernor);
        gub.candidateGovernor = address(0x0);

        // Send a notification about the change of governor.
        emit LogNewGovernorAccepted(msg.sender);
    }

    /*
      Remove a governor from office.
    */
    function _removeGovernor(address governorForRemoval) internal onlyGovernance {
        require(msg.sender != governorForRemoval, "GOVERNOR_SELF_REMOVE");
        GovernanceInfoStruct storage gub = getGovernanceInfo();
        require(_isGovernor(governorForRemoval), "NOT_GOVERNOR");
        gub.effectiveGovernors[governorForRemoval] = false;
        emit LogRemovedGovernor(governorForRemoval);
    }
}

File 10 of 37: GovernanceStorage.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;
import "MGovernance.sol";

/*
  Holds the governance slots for ALL entities, including proxy and the main contract.
*/
contract GovernanceStorage {
    // A map from a Governor tag to its own GovernanceInfoStruct.
    mapping(string => GovernanceInfoStruct) internal governanceInfo; //NOLINT uninitialized-state.
}

File 11 of 37: Identity.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

interface Identity {
    /*
      Allows a caller, typically another contract,
      to ensure that the provided address is of the expected type and version.
    */
    function identify() external pure returns (string memory);
}

File 12 of 37: IERC1155.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: MIT.
pragma solidity ^0.6.12;

/**
  Required interface of an ERC1155 compliant contract, as defined in the
  https://eips.ethereum.org/EIPS/eip-1155[EIP].

  _Available since v3.1.
*/
interface IERC1155 {
    /**
      Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
    */
    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 value
    );

    /**
      Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
      transfers.
    */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
      Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
      `approved`.
    */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
      Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.

      If an {URI} event was emitted for `id`, the standard
      https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
      returned by {IERC1155MetadataURI-uri}.
    */
    event URI(string value, uint256 indexed id);

    /**
      Returns the amount of tokens of token type `id` owned by `account`.

      Requirements:

      - `account` cannot be the zero address.
    */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
      Requirements:

      - `accounts` and `ids` must have the same length.
    */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
      Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,

      Emits an {ApprovalForAll} event.

      Requirements:

      - `operator` cannot be the caller.
    */
    function setApprovalForAll(address operator, bool approved) external;

    /**
      Returns true if `operator` is approved to transfer ``account``'s tokens.

      See {setApprovalForAll}.
    */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
      Transfers `amount` tokens of token type `id` from `from` to `to`.

      Emits a {TransferSingle} event.

      Requirements:

      - `to` cannot be the zero address.
      - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
      - `from` must have a balance of tokens of type `id` of at least `amount`.
      - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
      acceptance magic value.
    */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
      Emits a {TransferBatch} event.

      Requirements:

      - `ids` and `amounts` must have the same length.
      - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
      acceptance magic value.
    */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 13 of 37: IERC1155Receiver.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/**
  Note: The ERC-165 identifier for this interface is 0x4e2312e0.
*/
interface IERC1155Receiver {
    /**
      Handles the receipt of a single ERC1155 token type.
      @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
      This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
      This function MUST revert if it rejects the transfer.
      Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
      @param operator  The address which initiated the transfer (i.e. msg.sender)
      @param from      The address which previously owned the token
      @param id        The ID of the token being transferred
      @param value     The amount of tokens being transferred
      @param data      Additional data with no specified format
      @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` .
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
      Handles the receipt of multiple ERC1155 token types.
      @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
      This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
      This function MUST revert if it rejects the transfer(s).
      Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
      @param operator  The address which initiated the batch transfer (i.e. msg.sender)
      @param from      The address which previously owned the token
      @param ids       An array containing ids of each token being transferred (order and length must match values array)
      @param values    An array containing amounts of each token being transferred (order and length must match ids array)
      @param data      Additional data with no specified format
      @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` .
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 14 of 37: IERC20.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/*
  Interface of the ERC20 standard as defined in the EIP. Does not include
  the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 15 of 37: IERC721Receiver.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 16 of 37: KeyGetters.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MainStorage.sol";
import "MKeyGetters.sol";

/*
  Implements MKeyGetters.
*/
contract KeyGetters is MainStorage, MKeyGetters {
    uint256 internal constant MASK_ADDRESS = (1 << 160) - 1;

    /*
      Returns the Ethereum public key (address) that owns the given ownerKey.
      If the ownerKey size is within the range of an Ethereum address (i.e. < 2**160)
      it returns the owner key itself.

      If the ownerKey is larger than a potential eth address, the eth address for which the starkKey
      was registered is returned, and 0 if the starkKey is not registered.

      Note - prior to version 4.0 this function reverted on an unregistered starkKey.
      For a variant of this function that reverts on an unregistered starkKey, use strictGetEthKey.
    */
    function getEthKey(uint256 ownerKey) public view override returns (address) {
        address registeredEth = ethKeys[ownerKey];

        if (registeredEth != address(0x0)) {
            return registeredEth;
        }

        return ownerKey == (ownerKey & MASK_ADDRESS) ? address(ownerKey) : address(0x0);
    }

    /*
      Same as getEthKey, but fails when a stark key is not registered.
    */
    function strictGetEthKey(uint256 ownerKey) internal view override returns (address ethKey) {
        ethKey = getEthKey(ownerKey);
        require(ethKey != address(0x0), "USER_UNREGISTERED");
    }

    function isMsgSenderKeyOwner(uint256 ownerKey) internal view override returns (bool) {
        return msg.sender == getEthKey(ownerKey);
    }
}

File 17 of 37: LibConstants.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

contract LibConstants {
    // Durations for time locked mechanisms (in seconds).
    // Note that it is known that miners can manipulate block timestamps
    // up to a deviation of a few seconds.
    // This mechanism should not be used for fine grained timing.

    // The time required to cancel a deposit, in the case the operator does not move the funds
    // to the off-chain storage.
    uint256 public constant DEPOSIT_CANCEL_DELAY = 2 days;

    // The time required to freeze the exchange, in the case the operator does not execute a
    // requested full withdrawal.
    uint256 public constant FREEZE_GRACE_PERIOD = 7 days;

    // The time after which the exchange may be unfrozen after it froze. This should be enough time
    // for users to perform escape hatches to get back their funds.
    uint256 public constant UNFREEZE_DELAY = 365 days;

    // Maximal number of verifiers which may co-exist.
    uint256 public constant MAX_VERIFIER_COUNT = uint256(64);

    // The time required to remove a verifier in case of a verifier upgrade.
    uint256 public constant VERIFIER_REMOVAL_DELAY = FREEZE_GRACE_PERIOD + (21 days);

    address constant ZERO_ADDRESS = address(0x0);

    uint256 constant K_MODULUS = 0x800000000000011000000000000000000000000000000000000000000000001;

    uint256 constant K_BETA = 0x6f21413efbe40de150e596d72f7a8c5609ad26c15c915c1f4cdfcb99cee9e89;

    uint256 internal constant MASK_250 =
        0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
    uint256 internal constant MASK_240 =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    uint256 public constant MAX_FORCED_ACTIONS_REQS_PER_BLOCK = 10;

    uint256 constant QUANTUM_UPPER_BOUND = 2**128;
    uint256 internal constant MINTABLE_ASSET_ID_FLAG = 1 << 250;

    // The 64th bit (indexed 63, counting from 0) is a flag indicating a rollup vault id.
    uint256 constant ROLLUP_VAULTS_BIT = 63;
}

File 18 of 37: MAcceptModifications.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

/*
  Interface containing actions a verifier can invoke on the state.
  The contract containing the state should implement these and verify correctness.
*/
abstract contract MAcceptModifications {
    function acceptDeposit(
        uint256 ownerKey,
        uint256 vaultId,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal virtual;

    function allowWithdrawal(
        uint256 ownerKey,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal virtual;

    function acceptWithdrawal(
        uint256 ownerKey,
        uint256 assetId,
        uint256 quantizedAmount
    ) internal virtual;
}

File 19 of 37: MainGovernance.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "Governance.sol";
import "GovernanceStorage.sol";

/**
  The StarkEx contract is governed by one or more Governors of which the initial one is the
  deployer of the contract.

  A governor has the sole authority to perform the following operations:

  1. Nominate additional governors (:sol:func:`mainNominateNewGovernor`)
  2. Remove other governors (:sol:func:`mainRemoveGovernor`)
  3. Add new :sol:mod:`Verifiers` and :sol:mod:`AvailabilityVerifiers`
  4. Remove :sol:mod:`Verifiers` and :sol:mod:`AvailabilityVerifiers` after a timelock allows it
  5. Nominate Operators (see :sol:mod:`Operator`) and Token Administrators (see :sol:mod:`TokenRegister`)

  Adding governors is performed in a two step procedure:

  1. First, an existing governor nominates a new governor (:sol:func:`mainNominateNewGovernor`)
  2. Then, the new governor must accept governance to become a governor (:sol:func:`mainAcceptGovernance`)

  This two step procedure ensures that a governor public key cannot be nominated unless there is an
  entity that has the corresponding private key. This is intended to prevent errors in the addition
  process.

  The governor private key should typically be held in a secure cold wallet.
*/
/*
  Implements Governance for the StarkDex main contract.
  The wrapper methods (e.g. mainIsGovernor wrapping _isGovernor) are needed to give
  the method unique names.
  Both Proxy and StarkExchange inherit from Governance. Thus, the logical contract method names
  must have unique names in order for the proxy to successfully delegate to them.
*/
contract MainGovernance is GovernanceStorage, Governance {
    // The tag is the sting key that is used in the Governance storage mapping.
    string public constant MAIN_GOVERNANCE_INFO_TAG = "StarkEx.Main.2019.GovernorsInformation";

    /*
      Returns the GovernanceInfoStruct associated with the governance tag.
    */
    function getGovernanceInfo() internal view override returns (GovernanceInfoStruct storage) {
        return governanceInfo[MAIN_GOVERNANCE_INFO_TAG];
    }

    function mainIsGovernor(address testGovernor) external view returns (bool) {
        return _isGovernor(testGovernor);
    }

    function mainNominateNewGovernor(address newGovernor) external {
        _nominateNewGovernor(newGovernor);
    }

    function mainRemoveGovernor(address governorForRemoval) external {
        _removeGovernor(governorForRemoval);
    }

    function mainAcceptGovernance() external {
        _acceptGovernance();
    }

    function mainCancelNomination() external {
        _cancelNomination();
    }
}

File 20 of 37: MainStorage.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "ProxyStorage.sol";
import "Common.sol";

/*
  Holds ALL the main contract state (storage) variables.
*/
contract MainStorage is ProxyStorage {
    uint256 internal constant LAYOUT_LENGTH = 2**64;

    address escapeVerifierAddress; // NOLINT: constable-states.

    // Global dex-frozen flag.
    bool stateFrozen; // NOLINT: constable-states.

    // Time when unFreeze can be successfully called (UNFREEZE_DELAY after freeze).
    uint256 unFreezeTime; // NOLINT: constable-states.

    // Pending deposits.
    // A map STARK key => asset id => vault id => quantized amount.
    mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) pendingDeposits;

    // Cancellation requests.
    // A map STARK key => asset id => vault id => request timestamp.
    mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) cancellationRequests;

    // Pending withdrawals.
    // A map STARK key => asset id => quantized amount.
    mapping(uint256 => mapping(uint256 => uint256)) pendingWithdrawals;

    // vault_id => escape used boolean.
    mapping(uint256 => bool) escapesUsed;

    // Number of escapes that were performed when frozen.
    uint256 escapesUsedCount; // NOLINT: constable-states.

    // NOTE: fullWithdrawalRequests is deprecated, and replaced by forcedActionRequests.
    // NOLINTNEXTLINE naming-convention.
    mapping(uint256 => mapping(uint256 => uint256)) fullWithdrawalRequests_DEPRECATED;

    // State sequence number.
    uint256 sequenceNumber; // NOLINT: constable-states uninitialized-state.

    // Validium Vaults Tree Root & Height.
    uint256 validiumVaultRoot; // NOLINT: constable-states uninitialized-state.
    uint256 validiumTreeHeight; // NOLINT: constable-states uninitialized-state.

    // Order Tree Root & Height.
    uint256 orderRoot; // NOLINT: constable-states uninitialized-state.
    uint256 orderTreeHeight; // NOLINT: constable-states uninitialized-state.

    // True if and only if the address is allowed to add tokens.
    mapping(address => bool) tokenAdmins;

    // This mapping is no longer in use, remains for backwards compatibility.
    mapping(address => bool) userAdmins_DEPRECATED; // NOLINT: naming-convention.

    // True if and only if the address is an operator (allowed to update state).
    mapping(address => bool) operators; // NOLINT: uninitialized-state.

    // Mapping of contract ID to asset data.
    mapping(uint256 => bytes) assetTypeToAssetInfo; // NOLINT: uninitialized-state.

    // Mapping of registered contract IDs.
    mapping(uint256 => bool) registeredAssetType; // NOLINT: uninitialized-state.

    // Mapping from contract ID to quantum.
    mapping(uint256 => uint256) assetTypeToQuantum; // NOLINT: uninitialized-state.

    // This mapping is no longer in use, remains for backwards compatibility.
    mapping(address => uint256) starkKeys_DEPRECATED; // NOLINT: naming-convention.

    // Mapping from STARK public key to the Ethereum public key of its owner.
    mapping(uint256 => address) ethKeys; // NOLINT: uninitialized-state.

    // Timelocked state transition and availability verification chain.
    StarkExTypes.ApprovalChainData verifiersChain;
    StarkExTypes.ApprovalChainData availabilityVerifiersChain;

    // Batch id of last accepted proof.
    uint256 lastBatchId; // NOLINT: constable-states uninitialized-state.

    // Mapping between sub-contract index to sub-contract address.
    mapping(uint256 => address) subContracts; // NOLINT: uninitialized-state.

    mapping(uint256 => bool) permissiveAssetType_DEPRECATED; // NOLINT: naming-convention.
    // ---- END OF MAIN STORAGE AS DEPLOYED IN STARKEX2.0 ----

    // Onchain-data version configured for the system.
    uint256 onchainDataVersion_DEPRECATED; // NOLINT: naming-convention constable-states.

    // Counter of forced action request in block. The key is the block number.
    mapping(uint256 => uint256) forcedRequestsInBlock;

    // ForcedAction requests: actionHash => requestTime.
    mapping(bytes32 => uint256) forcedActionRequests;

    // Mapping for timelocked actions.
    // A actionKey => activation time.
    mapping(bytes32 => uint256) actionsTimeLock;

    // Append only list of requested forced action hashes.
    bytes32[] actionHashList;
    // ---- END OF MAIN STORAGE AS DEPLOYED IN STARKEX3.0 ----
    // ---- END OF MAIN STORAGE AS DEPLOYED IN STARKEX4.0 ----

    // Rollup Vaults Tree Root & Height.
    uint256 rollupVaultRoot; // NOLINT: constable-states uninitialized-state.
    uint256 rollupTreeHeight; // NOLINT: constable-states uninitialized-state.

    uint256 globalConfigCode; // NOLINT: constable-states uninitialized-state.

    // Reserved storage space for Extensibility.
    // Every added MUST be added above the end gap, and the __endGap size must be reduced
    // accordingly.
    // NOLINTNEXTLINE: naming-convention.
    uint256[LAYOUT_LENGTH - 40] private __endGap; // __endGap complements layout to LAYOUT_LENGTH.
}

File 21 of 37: MDeposits.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MDeposits {
    function depositERC20(
        // NOLINT external-function.
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId,
        uint256 quantizedAmount
    ) public virtual;

    function depositEth(
        // NOLINT external-function.
        uint256 starkKey,
        uint256 assetType,
        uint256 vaultId
    ) public payable virtual;
}

File 22 of 37: MFreezable.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MFreezable {
    /*
      Returns true if the exchange is frozen.
    */
    function isFrozen() public view virtual returns (bool); // NOLINT: external-function.

    /*
      Forbids calling the function if the exchange is frozen.
    */
    modifier notFrozen() {
        require(!isFrozen(), "STATE_IS_FROZEN");
        _;
    }

    function validateFreezeRequest(uint256 requestTime) internal virtual;

    /*
      Allows calling the function only if the exchange is frozen.
    */
    modifier onlyFrozen() {
        require(isFrozen(), "STATE_NOT_FROZEN");
        _;
    }

    /*
      Freezes the exchange.
    */
    function freeze() internal virtual;
}

File 23 of 37: MGovernance.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

struct GovernanceInfoStruct {
    mapping(address => bool) effectiveGovernors;
    address candidateGovernor;
    bool initialized;
}

abstract contract MGovernance {
    function _isGovernor(address testGovernor) internal view virtual returns (bool);

    /*
      Allows calling the function only by a Governor.
    */
    modifier onlyGovernance() {
        require(_isGovernor(msg.sender), "ONLY_GOVERNANCE");
        _;
    }
}

File 24 of 37: MKeyGetters.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MKeyGetters {
    // NOLINTNEXTLINE: external-function.
    function getEthKey(uint256 ownerKey) public view virtual returns (address);

    function strictGetEthKey(uint256 ownerKey) internal view virtual returns (address);

    function isMsgSenderKeyOwner(uint256 ownerKey) internal view virtual returns (bool);

    /*
      Allows calling the function only if ownerKey is registered to msg.sender.
    */
    modifier onlyKeyOwner(uint256 ownerKey) {
        // Require the calling user to own the stark key.
        require(msg.sender == strictGetEthKey(ownerKey), "MISMATCHING_STARK_ETH_KEYS");
        _;
    }
}

File 25 of 37: MStarkExForcedActionState.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MStarkExForcedActionState {
    function fullWithdrawActionHash(uint256 ownerKey, uint256 vaultId)
        internal
        pure
        virtual
        returns (bytes32);

    function clearFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId) internal virtual;

    // NOLINTNEXTLINE: external-function.
    function getFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId)
        public
        view
        virtual
        returns (uint256);

    function setFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId) internal virtual;
}

File 26 of 37: MTokenAssetData.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MTokenAssetData {
    // NOLINTNEXTLINE: external-function.
    function getAssetInfo(uint256 assetType) public view virtual returns (bytes memory);

    function isEther(uint256 assetType) internal view virtual returns (bool);

    function isERC20(uint256 assetType) internal view virtual returns (bool);

    function isERC721(uint256 assetType) internal view virtual returns (bool);

    function isERC1155(uint256 assetType) internal view virtual returns (bool);

    function isFungibleAssetType(uint256 assetType) internal view virtual returns (bool);

    function isMintableAssetType(uint256 assetType) internal view virtual returns (bool);

    function isAssetTypeWithTokenId(uint256 assetType) internal view virtual returns (bool);

    function extractContractAddress(uint256 assetType) internal view virtual returns (address);

    function verifyAssetInfo(bytes memory assetInfo) internal view virtual;

    function isNonFungibleAssetInfo(bytes memory assetInfo) internal pure virtual returns (bool);

    function calculateAssetIdWithTokenId(uint256 assetType, uint256 tokenId)
        public
        view
        virtual
        returns (uint256);

    function calculateMintableAssetId(uint256 assetType, bytes memory mintingBlob)
        public
        pure
        virtual
        returns (uint256);
}

File 27 of 37: MTokenQuantization.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MTokenQuantization {
    function fromQuantized(uint256 presumedAssetType, uint256 quantizedAmount)
        internal
        view
        virtual
        returns (uint256 amount);

    // NOLINTNEXTLINE: external-function.
    function getQuantum(uint256 presumedAssetType) public view virtual returns (uint256 quantum);

    function toQuantized(uint256 presumedAssetType, uint256 amount)
        internal
        view
        virtual
        returns (uint256 quantizedAmount);
}

File 28 of 37: MTokenTransfers.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

abstract contract MTokenTransfers {
    function transferIn(uint256 assetType, uint256 quantizedAmount) internal virtual;

    function transferInWithTokenId(
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) internal virtual;

    function transferOut(
        address payable recipient,
        uint256 assetType,
        uint256 quantizedAmount
    ) internal virtual;

    function transferOutWithTokenId(
        address recipient,
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) internal virtual;

    function transferOutMint(
        uint256 assetType,
        uint256 quantizedAmount,
        address recipient,
        bytes calldata mintingBlob
    ) internal virtual;
}

File 29 of 37: ProxyStorage.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "GovernanceStorage.sol";

/*
  Holds the Proxy-specific state variables.
  This contract is inherited by the GovernanceStorage (and indirectly by MainStorage)
  to prevent collision hazard.
*/
contract ProxyStorage is GovernanceStorage {
    // NOLINTNEXTLINE: naming-convention uninitialized-state.
    mapping(address => bytes32) internal initializationHash_DEPRECATED;

    // The time after which we can switch to the implementation.
    // Hash(implementation, data, finalize) => time.
    mapping(bytes32 => uint256) internal enabledTime;

    // A central storage of the flags whether implementation has been initialized.
    // Note - it can be used flexibly enough to accommodate multiple levels of initialization
    // (i.e. using different key salting schemes for different initialization levels).
    mapping(bytes32 => bool) internal initialized;
}

File 30 of 37: StarkExForcedActionState.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "StarkExStorage.sol";
import "MStarkExForcedActionState.sol";
import "ActionHash.sol";

/*
  StarkExchange specific action hashses.
*/
contract StarkExForcedActionState is StarkExStorage, ActionHash, MStarkExForcedActionState {
    function fullWithdrawActionHash(uint256 ownerKey, uint256 vaultId)
        internal
        pure
        override
        returns (bytes32)
    {
        return getActionHash("FULL_WITHDRAWAL", abi.encode(ownerKey, vaultId));
    }

    /*
      Implemented in the FullWithdrawal contracts.
    */
    function clearFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId)
        internal
        virtual
        override
    {
        // Reset escape request.
        delete forcedActionRequests[fullWithdrawActionHash(ownerKey, vaultId)];
    }

    function getFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId)
        public
        view
        override
        returns (uint256)
    {
        // Return request value. Expect zero if the request doesn't exist or has been serviced, and
        // a non-zero value otherwise.
        return forcedActionRequests[fullWithdrawActionHash(ownerKey, vaultId)];
    }

    function setFullWithdrawalRequest(uint256 ownerKey, uint256 vaultId) internal override {
        // FullWithdrawal is always at premium cost, hence the `true`.
        setActionHash(fullWithdrawActionHash(ownerKey, vaultId), true);
    }
}

File 31 of 37: StarkExStorage.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MainStorage.sol";

/*
  Extends MainStorage, holds StarkEx App specific state (storage) variables.

  ALL State variables that are common to all applications, reside in MainStorage,
  whereas ALL the StarkEx app specific ones reside here.
*/
contract StarkExStorage is MainStorage {
    // Onchain vaults balances.
    // A map eth_address => asset_id => vault_id => quantized amount.
    mapping(address => mapping(uint256 => mapping(uint256 => uint256))) vaultsBalances;

    // Onchain vaults withdrawal lock time.
    // A map eth_address => asset_id => vault_id => lock expiration timestamp.
    mapping(address => mapping(uint256 => mapping(uint256 => uint256))) vaultsWithdrawalLocks;

    // Enforces the minimal balance requirement (as output by Cairo) on onchain vault updates.
    // When disabled, flash loans are enabled.
    bool strictVaultBalancePolicy; // NOLINT: constable-states, uninitialized-state.

    // The default time, in seconds, that an onchain vault is locked for withdrawal after a deposit.
    uint256 public defaultVaultWithdrawalLock; // NOLINT: constable-states.

    // Address of the message registry contract that is used to sign and verify L1 orders.
    address public orderRegistryAddress; // NOLINT: constable-states.

    // Reserved storage space for Extensibility.
    // Every added MUST be added above the end gap, and the __endGap size must be reduced
    // accordingly.
    // NOLINTNEXTLINE: naming-convention shadowing-abstract.
    uint256[LAYOUT_LENGTH - 5] private __endGap; // __endGap complements layout to LAYOUT_LENGTH.
}

File 32 of 37: SubContractor.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "Identity.sol";

interface SubContractor is Identity {
    function initialize(bytes calldata data) external;

    function initializerSize() external view returns (uint256);

    /*
      Returns an array with selectors for validation.
      These selectors are the critical ones for maintaining self custody and anti censorship.
      During the upgrade process, as part of the sub-contract validation, the MainDispatcher
      validates that the selectos are mapped to the correct sub-contract.
    */
    function validatedSelectors() external pure returns (bytes4[] memory);
}

File 33 of 37: TokenAssetData.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MainStorage.sol";
import "MTokenAssetData.sol";
import "Common.sol";
import "LibConstants.sol";

contract TokenAssetData is MainStorage, LibConstants, MTokenAssetData {
    bytes4 internal constant ERC20_SELECTOR = bytes4(keccak256("ERC20Token(address)"));
    bytes4 internal constant ETH_SELECTOR = bytes4(keccak256("ETH()"));
    bytes4 internal constant ERC721_SELECTOR = bytes4(keccak256("ERC721Token(address,uint256)"));
    bytes4 internal constant ERC1155_SELECTOR = bytes4(keccak256("ERC1155Token(address,uint256)"));
    bytes4 internal constant MINTABLE_ERC20_SELECTOR =
        bytes4(keccak256("MintableERC20Token(address)"));
    bytes4 internal constant MINTABLE_ERC721_SELECTOR =
        bytes4(keccak256("MintableERC721Token(address,uint256)"));

    // The selector follows the 0x20 bytes assetInfo.length field.
    uint256 internal constant SELECTOR_OFFSET = 0x20;
    uint256 internal constant SELECTOR_SIZE = 4;
    uint256 internal constant TOKEN_CONTRACT_ADDRESS_OFFSET = SELECTOR_OFFSET + SELECTOR_SIZE;
    string internal constant NFT_ASSET_ID_PREFIX = "NFT:";
    string internal constant NON_MINTABLE_PREFIX = "NON_MINTABLE:";
    string internal constant MINTABLE_PREFIX = "MINTABLE:";

    using Addresses for address;

    /*
      Extract the tokenSelector from assetInfo.

      Works like bytes4 tokenSelector = abi.decode(assetInfo, (bytes4))
      but does not revert when assetInfo.length < SELECTOR_OFFSET.
    */
    function extractTokenSelectorFromAssetInfo(bytes memory assetInfo)
        private
        pure
        returns (bytes4 selector)
    {
        assembly {
            selector := and(
                0xffffffff00000000000000000000000000000000000000000000000000000000,
                mload(add(assetInfo, SELECTOR_OFFSET))
            )
        }
    }

    function getAssetInfo(uint256 assetType) public view override returns (bytes memory assetInfo) {
        // Verify that the registration is set and valid.
        require(registeredAssetType[assetType], "ASSET_TYPE_NOT_REGISTERED");

        // Retrieve registration.
        assetInfo = assetTypeToAssetInfo[assetType];
    }

    function extractTokenSelectorFromAssetType(uint256 assetType) private view returns (bytes4) {
        return extractTokenSelectorFromAssetInfo(getAssetInfo(assetType));
    }

    function isEther(uint256 assetType) internal view override returns (bool) {
        return extractTokenSelectorFromAssetType(assetType) == ETH_SELECTOR;
    }

    function isERC20(uint256 assetType) internal view override returns (bool) {
        return extractTokenSelectorFromAssetType(assetType) == ERC20_SELECTOR;
    }

    function isERC721(uint256 assetType) internal view override returns (bool) {
        return extractTokenSelectorFromAssetType(assetType) == ERC721_SELECTOR;
    }

    function isERC1155(uint256 assetType) internal view override returns (bool) {
        return extractTokenSelectorFromAssetType(assetType) == ERC1155_SELECTOR;
    }

    function isFungibleAssetType(uint256 assetType) internal view override returns (bool) {
        bytes4 tokenSelector = extractTokenSelectorFromAssetType(assetType);
        return
            tokenSelector == ETH_SELECTOR ||
            tokenSelector == ERC20_SELECTOR ||
            tokenSelector == MINTABLE_ERC20_SELECTOR;
    }

    function isMintableAssetType(uint256 assetType) internal view override returns (bool) {
        bytes4 tokenSelector = extractTokenSelectorFromAssetType(assetType);
        return
            tokenSelector == MINTABLE_ERC20_SELECTOR || tokenSelector == MINTABLE_ERC721_SELECTOR;
    }

    function isAssetTypeWithTokenId(uint256 assetType) internal view override returns (bool) {
        bytes4 tokenSelector = extractTokenSelectorFromAssetType(assetType);
        return tokenSelector == ERC721_SELECTOR || tokenSelector == ERC1155_SELECTOR;
    }

    function isTokenSupported(bytes4 tokenSelector) private pure returns (bool) {
        return
            tokenSelector == ETH_SELECTOR ||
            tokenSelector == ERC20_SELECTOR ||
            tokenSelector == ERC721_SELECTOR ||
            tokenSelector == MINTABLE_ERC20_SELECTOR ||
            tokenSelector == MINTABLE_ERC721_SELECTOR ||
            tokenSelector == ERC1155_SELECTOR;
    }

    function extractContractAddressFromAssetInfo(bytes memory assetInfo)
        private
        pure
        returns (address)
    {
        uint256 offset = TOKEN_CONTRACT_ADDRESS_OFFSET;
        uint256 res;
        assembly {
            res := mload(add(assetInfo, offset))
        }
        return address(res);
    }

    function extractContractAddress(uint256 assetType) internal view override returns (address) {
        return extractContractAddressFromAssetInfo(getAssetInfo(assetType));
    }

    function verifyAssetInfo(bytes memory assetInfo) internal view override {
        bytes4 tokenSelector = extractTokenSelectorFromAssetInfo(assetInfo);

        // Ensure the selector is of an asset type we know.
        require(isTokenSupported(tokenSelector), "UNSUPPORTED_TOKEN_TYPE");

        if (tokenSelector == ETH_SELECTOR) {
            // Assset info for ETH assetType is only a selector, i.e. 4 bytes length.
            require(assetInfo.length == 4, "INVALID_ASSET_STRING");
        } else {
            // Assset info for other asset types are a selector + uint256 concatanation.
            // We pass the address as a uint256 (zero padded),
            // thus its length is 0x04 + 0x20 = 0x24.
            require(assetInfo.length == 0x24, "INVALID_ASSET_STRING");
            address tokenAddress = extractContractAddressFromAssetInfo(assetInfo);
            require(tokenAddress.isContract(), "BAD_TOKEN_ADDRESS");
        }
    }

    function isNonFungibleAssetInfo(bytes memory assetInfo) internal pure override returns (bool) {
        bytes4 tokenSelector = extractTokenSelectorFromAssetInfo(assetInfo);
        return tokenSelector == ERC721_SELECTOR || tokenSelector == MINTABLE_ERC721_SELECTOR;
    }

    function calculateAssetIdWithTokenId(uint256 assetType, uint256 tokenId)
        public
        view
        override
        returns (uint256)
    {
        require(isAssetTypeWithTokenId(assetType), "ASSET_TYPE_DOES_NOT_TAKE_TOKEN_ID");

        string memory prefix = isERC721(assetType) ? NFT_ASSET_ID_PREFIX : NON_MINTABLE_PREFIX;
        return uint256(keccak256(abi.encodePacked(prefix, assetType, tokenId))) & MASK_250;
    }

    function calculateMintableAssetId(uint256 assetType, bytes memory mintingBlob)
        public
        pure
        override
        returns (uint256 assetId)
    {
        uint256 blobHash = uint256(keccak256(mintingBlob));
        assetId =
            (uint256(keccak256(abi.encodePacked(MINTABLE_PREFIX, assetType, blobHash))) &
                MASK_240) |
            MINTABLE_ASSET_ID_FLAG;
    }
}

File 34 of 37: TokenQuantization.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MainStorage.sol";
import "MTokenQuantization.sol";

contract TokenQuantization is MainStorage, MTokenQuantization {
    function fromQuantized(uint256 presumedAssetType, uint256 quantizedAmount)
        internal
        view
        override
        returns (uint256 amount)
    {
        uint256 quantum = getQuantum(presumedAssetType);
        amount = quantizedAmount * quantum;
        require(amount / quantum == quantizedAmount, "DEQUANTIZATION_OVERFLOW");
    }

    function getQuantum(uint256 presumedAssetType) public view override returns (uint256 quantum) {
        if (!registeredAssetType[presumedAssetType]) {
            // Default quantization, for NFTs etc.
            quantum = 1;
        } else {
            // Retrieve registration.
            quantum = assetTypeToQuantum[presumedAssetType];
        }
    }

    function toQuantized(uint256 presumedAssetType, uint256 amount)
        internal
        view
        override
        returns (uint256 quantizedAmount)
    {
        uint256 quantum = getQuantum(presumedAssetType);
        require(amount % quantum == 0, "INVALID_AMOUNT");
        quantizedAmount = amount / quantum;
    }
}

File 35 of 37: TokenRegister.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "LibConstants.sol";
import "MGovernance.sol";
import "MTokenAssetData.sol";
import "IERC20.sol";
import "MainStorage.sol";

/**
  Registration of a new token (:sol:func:`registerToken`) entails defining a new asset type within
  the system, and associating it with an `assetInfo` array of
  bytes and a quantization factor (`quantum`).

  The `assetInfo` is a byte array, with a size depending on the token.
  For ETH, assetInfo is 4 bytes long. For ERC20 tokens, it is 36 bytes long.

  For each token type, the following constant 4-byte hash is defined, called the `selector`:

   | `ETH_SELECTOR = bytes4(keccak256("ETH()"));`
   | `ERC20_SELECTOR = bytes4(keccak256("ERC20Token(address)"));`
   | `ERC721_SELECTOR = bytes4(keccak256("ERC721Token(address,uint256)"));`
   | `MINTABLE_ERC20_SELECTOR = bytes4(keccak256("MintableERC20Token(address)"));`
   | `MINTABLE_ERC721_SELECTOR = bytes4(keccak256("MintableERC721Token(address,uint256)"));`

  For each token type, `assetInfo` is defined as follows:


  The `quantum` quantization factor defines the multiplicative transformation from the native token
  denomination as a 256b unsigned integer to a 63b unsigned integer representation as used by the
  Stark exchange. Only amounts in the native representation that represent an integer number of
  quanta are allowed in the system.

  The asset type is restricted to be the result of a hash of the `assetInfo` and the
  `quantum` masked to 250 bits (to be less than the prime used) according to the following formula:

  | ``uint256 assetType = uint256(keccak256(abi.encodePacked(assetInfo, quantum))) &``
  | ``0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;``

  Once registered, tokens cannot be removed from the system, as their IDs may be used by off-chain
  accounts.

  New tokens may only be registered by a Token Administrator. A Token Administrator may be instantly
  appointed or removed by the contract Governor (see :sol:mod:`MainGovernance`). Typically, the
  Token Administrator's private key should be kept in a cold wallet.
*/
abstract contract TokenRegister is MainStorage, LibConstants, MGovernance, MTokenAssetData {
    event LogTokenRegistered(uint256 assetType, bytes assetInfo, uint256 quantum);
    event LogTokenAdminAdded(address tokenAdmin);
    event LogTokenAdminRemoved(address tokenAdmin);

    modifier onlyTokensAdmin() {
        require(isTokenAdmin(msg.sender), "ONLY_TOKENS_ADMIN");
        _;
    }

    function isTokenAdmin(address testedAdmin) public view returns (bool) {
        return tokenAdmins[testedAdmin];
    }

    function registerTokenAdmin(address newAdmin) external onlyGovernance {
        tokenAdmins[newAdmin] = true;
        emit LogTokenAdminAdded(newAdmin);
    }

    function unregisterTokenAdmin(address oldAdmin) external onlyGovernance {
        tokenAdmins[oldAdmin] = false;
        emit LogTokenAdminRemoved(oldAdmin);
    }

    function isAssetRegistered(uint256 assetType) public view returns (bool) {
        return registeredAssetType[assetType];
    }

    /*
      Registers a new asset to the system.
      Once added, it can not be removed and there is a limited number
      of slots available.
    */
    function registerToken(
        uint256 assetType,
        bytes calldata assetInfo,
        uint256 quantum
    ) public virtual onlyTokensAdmin {
        // Make sure it is not invalid or already registered.
        require(!isAssetRegistered(assetType), "ASSET_ALREADY_REGISTERED");
        require(assetType < K_MODULUS, "INVALID_ASSET_TYPE");
        require(quantum > 0, "INVALID_QUANTUM");
        require(quantum < QUANTUM_UPPER_BOUND, "INVALID_QUANTUM");

        // Require that the assetType is the hash of the assetInfo and quantum truncated to 250 bits.
        uint256 enforcedId = uint256(keccak256(abi.encodePacked(assetInfo, quantum))) & MASK_250;
        require(assetType == enforcedId, "INVALID_ASSET_TYPE");

        verifyAssetInfo(assetInfo);
        // NFTs quantum must equal one.
        if (isNonFungibleAssetInfo(assetInfo)) {
            require(quantum == 1, "INVALID_NFT_QUANTUM");
        }

        // Add token to the in-storage structures.
        registeredAssetType[assetType] = true;
        assetTypeToAssetInfo[assetType] = assetInfo;
        assetTypeToQuantum[assetType] = quantum;

        // Log the registration of a new token.
        emit LogTokenRegistered(assetType, assetInfo, quantum);
    }

    function registerToken(uint256 assetType, bytes calldata assetInfo) external virtual {
        registerToken(assetType, assetInfo, 1);
    }
}

File 36 of 37: TokenTransfers.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "Common.sol";
import "MTokenTransfers.sol";
import "MTokenAssetData.sol";
import "MTokenQuantization.sol";
import "IERC1155.sol";
import "IERC20.sol";

/*
  Implements various transferIn and transferOut functionalities.
*/
abstract contract TokenTransfers is MTokenQuantization, MTokenAssetData, MTokenTransfers {
    using Addresses for address;
    using Addresses for address payable;

    /*
      Transfers funds from msg.sender to the exchange.
    */
    function transferIn(uint256 assetType, uint256 quantizedAmount) internal override {
        uint256 amount = fromQuantized(assetType, quantizedAmount);
        if (isERC20(assetType)) {
            if (quantizedAmount == 0) return;
            address tokenAddress = extractContractAddress(assetType);
            IERC20 token = IERC20(tokenAddress);
            uint256 exchangeBalanceBefore = token.balanceOf(address(this));
            bytes memory callData = abi.encodeWithSelector(
                token.transferFrom.selector,
                msg.sender,
                address(this),
                amount
            );
            tokenAddress.safeTokenContractCall(callData);
            uint256 exchangeBalanceAfter = token.balanceOf(address(this));
            require(exchangeBalanceAfter >= exchangeBalanceBefore, "OVERFLOW");
            // NOLINTNEXTLINE(incorrect-equality): strict equality needed.
            require(
                exchangeBalanceAfter == exchangeBalanceBefore + amount,
                "INCORRECT_AMOUNT_TRANSFERRED"
            );
        } else if (isEther(assetType)) {
            require(msg.value == amount, "INCORRECT_DEPOSIT_AMOUNT");
        } else {
            revert("UNSUPPORTED_TOKEN_TYPE");
        }
    }

    /*
      Transfers non fungible and semi fungible tokens from a user to the exchange.
    */
    function transferInWithTokenId(
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) internal override {
        require(isAssetTypeWithTokenId(assetType), "FUNGIBLE_ASSET_TYPE");

        if (isERC721(assetType)) {
            require(quantizedAmount == 1, "ILLEGAL_NFT_BALANCE");
            transferInNft(assetType, tokenId);
        } else if (quantizedAmount > 0) {
            transferInSft(assetType, tokenId, quantizedAmount);
        }
    }

    function transferInNft(uint256 assetType, uint256 tokenId) private {
        require(isERC721(assetType), "NOT_ERC721_TOKEN");
        address tokenAddress = extractContractAddress(assetType);

        tokenAddress.safeTokenContractCall(
            abi.encodeWithSignature(
                "safeTransferFrom(address,address,uint256)",
                msg.sender,
                address(this),
                tokenId
            )
        );
    }

    function transferInSft(
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) private {
        require(isERC1155(assetType), "NOT_ERC1155_TOKEN");
        if (quantizedAmount == 0) return;

        uint256 amount = fromQuantized(assetType, quantizedAmount);
        address tokenAddress = extractContractAddress(assetType);
        IERC1155 token = IERC1155(tokenAddress);
        uint256 exchangeBalanceBefore = token.balanceOf(address(this), tokenId);

        // Call an ERC1155 token transfer.
        tokenAddress.safeTokenContractCall(
            abi.encodeWithSelector(
                token.safeTransferFrom.selector,
                msg.sender,
                address(this),
                tokenId,
                amount,
                bytes("")
            )
        );

        uint256 exchangeBalanceAfter = token.balanceOf(address(this), tokenId);
        require(exchangeBalanceAfter >= exchangeBalanceBefore, "OVERFLOW");
        // NOLINTNEXTLINE(incorrect-equality): strict equality needed.
        require(
            exchangeBalanceAfter == exchangeBalanceBefore + amount,
            "INCORRECT_AMOUNT_TRANSFERRED"
        );
    }

    /*
      Transfers funds from the exchange to recipient.
    */
    function transferOut(
        address payable recipient,
        uint256 assetType,
        uint256 quantizedAmount
    ) internal override {
        // Make sure we don't accidentally burn funds.
        require(recipient != address(0x0), "INVALID_RECIPIENT");
        uint256 amount = fromQuantized(assetType, quantizedAmount);
        if (isERC20(assetType)) {
            if (quantizedAmount == 0) return;
            address tokenAddress = extractContractAddress(assetType);
            IERC20 token = IERC20(tokenAddress);
            uint256 exchangeBalanceBefore = token.balanceOf(address(this));
            bytes memory callData = abi.encodeWithSelector(
                token.transfer.selector,
                recipient,
                amount
            );
            tokenAddress.safeTokenContractCall(callData);
            uint256 exchangeBalanceAfter = token.balanceOf(address(this));
            require(exchangeBalanceAfter <= exchangeBalanceBefore, "UNDERFLOW");
            // NOLINTNEXTLINE(incorrect-equality): strict equality needed.
            require(
                exchangeBalanceAfter == exchangeBalanceBefore - amount,
                "INCORRECT_AMOUNT_TRANSFERRED"
            );
        } else if (isEther(assetType)) {
            if (quantizedAmount == 0) return;
            recipient.performEthTransfer(amount);
        } else {
            revert("UNSUPPORTED_TOKEN_TYPE");
        }
    }

    /*
      Transfers non fungible and semi fungible tokens from the exchange to recipient.
    */
    function transferOutWithTokenId(
        address recipient,
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) internal override {
        require(isAssetTypeWithTokenId(assetType), "FUNGIBLE_ASSET_TYPE");
        if (isERC721(assetType)) {
            require(quantizedAmount == 1, "ILLEGAL_NFT_BALANCE");
            transferOutNft(recipient, assetType, tokenId);
        } else if (quantizedAmount > 0) {
            transferOutSft(recipient, assetType, tokenId, quantizedAmount);
        }
    }

    /*
      Transfers NFT from the exchange to recipient.
    */
    function transferOutNft(
        address recipient,
        uint256 assetType,
        uint256 tokenId
    ) private {
        // Make sure we don't accidentally burn funds.
        require(recipient != address(0x0), "INVALID_RECIPIENT");
        require(isERC721(assetType), "NOT_ERC721_TOKEN");
        address tokenAddress = extractContractAddress(assetType);

        tokenAddress.safeTokenContractCall(
            abi.encodeWithSignature(
                "safeTransferFrom(address,address,uint256)",
                address(this),
                recipient,
                tokenId
            )
        );
    }

    /*
      Transfers Semi Fungible Tokens from the exchange to recipient.
    */
    function transferOutSft(
        address recipient,
        uint256 assetType,
        uint256 tokenId,
        uint256 quantizedAmount
    ) private {
        // Make sure we don't accidentally burn funds.
        require(recipient != address(0x0), "INVALID_RECIPIENT");
        require(isERC1155(assetType), "NOT_ERC1155_TOKEN");
        if (quantizedAmount == 0) return;

        uint256 amount = fromQuantized(assetType, quantizedAmount);
        address tokenAddress = extractContractAddress(assetType);
        IERC1155 token = IERC1155(tokenAddress);
        uint256 exchangeBalanceBefore = token.balanceOf(address(this), tokenId);

        // Call an ERC1155 token transfer.
        tokenAddress.safeTokenContractCall(
            abi.encodeWithSelector(
                token.safeTransferFrom.selector,
                address(this),
                recipient,
                tokenId,
                amount,
                bytes("")
            )
        );

        uint256 exchangeBalanceAfter = token.balanceOf(address(this), tokenId);
        require(exchangeBalanceAfter <= exchangeBalanceBefore, "UNDERFLOW");
        // NOLINTNEXTLINE(incorrect-equality): strict equality needed.
        require(
            exchangeBalanceAfter == exchangeBalanceBefore - amount,
            "INCORRECT_AMOUNT_TRANSFERRED"
        );
    }

    function transferOutMint(
        uint256 assetType,
        uint256 quantizedAmount,
        address recipient,
        bytes calldata mintingBlob
    ) internal override {
        // Make sure we don't accidentally burn funds.
        require(recipient != address(0x0), "INVALID_RECIPIENT");
        require(isMintableAssetType(assetType), "NON_MINTABLE_ASSET_TYPE");
        require(quantizedAmount > 0, "INVALID_MINT_AMOUNT");
        uint256 amount = fromQuantized(assetType, quantizedAmount);
        address tokenAddress = extractContractAddress(assetType);
        tokenAddress.safeTokenContractCall(
            abi.encodeWithSignature(
                "mintFor(address,uint256,bytes)",
                recipient,
                amount,
                mintingBlob
            )
        );
    }
}

File 37 of 37: Withdrawals.sol
/*
  Copyright 2019-2022 StarkWare Industries Ltd.

  Licensed under the Apache License, Version 2.0 (the "License").
  You may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.starkware.co/open-source-license/

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions
  and limitations under the License.
*/
// SPDX-License-Identifier: Apache-2.0.
pragma solidity ^0.6.12;

import "MAcceptModifications.sol";
import "MTokenQuantization.sol";
import "MTokenAssetData.sol";
import "MFreezable.sol";
import "MKeyGetters.sol";
import "MTokenTransfers.sol";
import "MainStorage.sol";

/**
  For a user to perform a withdrawal operation from the Stark Exchange during normal operation
  two calls are required:

  1. A call to an offchain exchange API, requesting a withdrawal from a user account (vault).
  2. A call to the on-chain :sol:func:`withdraw` function to perform the actual withdrawal of funds transferring them to the users Eth or ERC20 account (depending on the token type).

  For simplicity, hereafter it is assumed that all tokens are ERC20 tokens but the text below
  applies to Eth in the same manner.

  In the first call mentioned above, anyone can call the API to request the withdrawal of an
  amount from a given vault. Following the request, the exchange may include the withdrawal in a
  STARK proof. The submission of a proof then results in the addition of the amount(s) withdrawn to
  an on-chain pending withdrawals account under the stark key of the vault owner and the appropriate
  asset ID. At the same time, this also implies that this amount is deducted from the off-chain
  vault.

  Once the amount to be withdrawn has been transfered to the on-chain pending withdrawals account,
  the user may perform the second call mentioned above to complete the transfer of funds from the
  Stark Exchange contract to the appropriate ERC20 account. Only a user holding the Eth key
  corresponding to the Stark Key of a pending withdrawals account may perform this operation.

  It is possible that for multiple withdrawal calls to the API, a single withdrawal call to the
  contract may retrieve all funds, as long as they are all for the same asset ID.

  The result of the operation, assuming all requirements are met, is that an amount of ERC20 tokens
  in the pending withdrawal account times the quantization factor is transferred to the ERC20
  account of the user.

  A withdrawal request cannot be cancelled. Once funds reach the pending withdrawals account
  on-chain, they cannot be moved back into an off-chain vault before completion of the withdrawal
  to the ERC20 account of the user.

  In the event that the exchange reaches a frozen state the user may perform a withdrawal operation
  via an alternative flow, known as the "Escape" flow. In this flow, the API call above is replaced
  with an :sol:func:`escape` call to the on-chain contract (see :sol:mod:`Escapes`) proving the
  ownership of off-chain funds. If such proof is accepted, the user may proceed as above with
  the :sol:func:`withdraw` call to the contract to complete the operation.
*/
abstract contract Withdrawals is
    MainStorage,
    MAcceptModifications,
    MTokenQuantization,
    MTokenAssetData,
    MFreezable,
    MKeyGetters,
    MTokenTransfers
{
    event LogWithdrawalPerformed(
        uint256 ownerKey,
        uint256 assetType,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount,
        address recipient
    );

    event LogNftWithdrawalPerformed(
        uint256 ownerKey,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId,
        address recipient
    );

    event LogWithdrawalWithTokenIdPerformed(
        uint256 ownerKey,
        uint256 assetType,
        uint256 tokenId,
        uint256 assetId,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount,
        address recipient
    );

    event LogMintWithdrawalPerformed(
        uint256 ownerKey,
        uint256 assetType,
        uint256 nonQuantizedAmount,
        uint256 quantizedAmount,
        uint256 assetId
    );

    function getWithdrawalBalance(uint256 ownerKey, uint256 assetId)
        external
        view
        returns (uint256)
    {
        uint256 presumedAssetType = assetId;
        return fromQuantized(presumedAssetType, pendingWithdrawals[ownerKey][assetId]);
    }

    /*
      Moves funds from the pending withdrawal account to the owner address.
      Note: this function can be called by anyone.
      Can be called normally while frozen.
    */
    function withdraw(uint256 ownerKey, uint256 assetType) external {
        address payable recipient = payable(strictGetEthKey(ownerKey));
        require(!isMintableAssetType(assetType), "MINTABLE_ASSET_TYPE");
        require(isFungibleAssetType(assetType), "NON_FUNGIBLE_ASSET_TYPE");
        uint256 assetId = assetType;
        // Fetch and clear quantized amount.
        uint256 quantizedAmount = pendingWithdrawals[ownerKey][assetId];
        pendingWithdrawals[ownerKey][assetId] = 0;

        // Transfer funds.
        transferOut(recipient, assetType, quantizedAmount);
        emit LogWithdrawalPerformed(
            ownerKey,
            assetType,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount,
            recipient
        );
    }

    /*
      Allows withdrawal of tokens to their owner's account.
      Note: this function can be called by anyone.
      This function can be called normally while frozen.
    */
    function withdrawWithTokenId(
        uint256 ownerKey,
        uint256 assetType,
        uint256 tokenId // No notFrozen modifier: This function can always be used, even when frozen.
    ) public {
        require(isAssetTypeWithTokenId(assetType), "INVALID_ASSET_TYPE");
        uint256 assetId = calculateAssetIdWithTokenId(assetType, tokenId);
        address recipient = strictGetEthKey(ownerKey);

        uint256 quantizedAmount = pendingWithdrawals[ownerKey][assetId];
        pendingWithdrawals[ownerKey][assetId] = 0;

        // Transfer funds.
        transferOutWithTokenId(recipient, assetType, tokenId, quantizedAmount);
        if (isERC721(assetType)) {
            emit LogNftWithdrawalPerformed(ownerKey, assetType, tokenId, assetId, recipient);
        }
        emit LogWithdrawalWithTokenIdPerformed(
            ownerKey,
            assetType,
            tokenId,
            assetId,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount,
            recipient
        );
    }

    /*
      Allows withdrawal of an NFT to its owner's account.
      Note: this function can be called by anyone.
      This function can be called normally while frozen.
    */
    function withdrawNft(
        uint256 ownerKey,
        uint256 assetType,
        uint256 tokenId // No notFrozen modifier: This function can always be used, even when frozen.
    ) external {
        withdrawWithTokenId(ownerKey, assetType, tokenId);
    }

    function withdrawAndMint(
        uint256 ownerKey,
        uint256 assetType,
        bytes calldata mintingBlob
    ) external {
        address recipient = strictGetEthKey(ownerKey);
        require(registeredAssetType[assetType], "INVALID_ASSET_TYPE");
        require(isMintableAssetType(assetType), "NON_MINTABLE_ASSET_TYPE");
        uint256 assetId = calculateMintableAssetId(assetType, mintingBlob);
        require(pendingWithdrawals[ownerKey][assetId] > 0, "NO_PENDING_WITHDRAWAL_BALANCE");
        uint256 quantizedAmount = pendingWithdrawals[ownerKey][assetId];
        pendingWithdrawals[ownerKey][assetId] = 0;
        // Transfer funds.
        transferOutMint(assetType, quantizedAmount, recipient, mintingBlob);
        emit LogMintWithdrawalPerformed(
            ownerKey,
            assetType,
            fromQuantized(assetType, quantizedAmount),
            quantizedAmount,
            assetId
        );
    }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogAssetWithdrawalAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositorEthKey","type":"address"},{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"LogDepositCancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogDepositCancelReclaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"LogDepositNftCancelReclaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositorEthKey","type":"address"},{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogDepositWithTokenId","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogDepositWithTokenIdCancelReclaimed","type":"event"},{"anonymous":false,"inputs":[],"name":"LogFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"LogMintWithdrawalPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogMintableWithdrawalAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"acceptedGovernor","type":"address"}],"name":"LogNewGovernorAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositorEthKey","type":"address"},{"indexed":false,"internalType":"uint256","name":"starkKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"LogNftDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"LogNftWithdrawalAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"LogNftWithdrawalPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nominatedGovernor","type":"address"}],"name":"LogNominatedGovernor","type":"event"},{"anonymous":false,"inputs":[],"name":"LogNominationCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"removedGovernor","type":"address"}],"name":"LogRemovedGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAdmin","type":"address"}],"name":"LogTokenAdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenAdmin","type":"address"}],"name":"LogTokenAdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"assetInfo","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"quantum","type":"uint256"}],"name":"LogTokenRegistered","type":"event"},{"anonymous":false,"inputs":[],"name":"LogUnFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"LogWithdrawalAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"LogWithdrawalPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"ownerKey","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonQuantizedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"quantizedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"LogWithdrawalWithTokenIdPerformed","type":"event"},{"inputs":[],"name":"DEPOSIT_CANCEL_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FREEZE_GRACE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAIN_GOVERNANCE_INFO_TAG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FORCED_ACTIONS_REQS_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_VERIFIER_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNFREEZE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFIER_REMOVAL_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"calculateAssetIdWithTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"bytes","name":"mintingBlob","type":"bytes"}],"name":"calculateMintableAssetId","outputs":[{"internalType":"uint256","name":"assetId","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"defaultVaultWithdrawalLock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"depositCancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"depositERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"depositEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"depositNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"depositNftReclaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"depositReclaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"uint256","name":"quantizedAmount","type":"uint256"}],"name":"depositWithTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"depositWithTokenIdReclaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getActionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionIndex","type":"uint256"}],"name":"getActionHashByIndex","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"}],"name":"getAssetInfo","outputs":[{"internalType":"bytes","name":"assetInfo","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"getCancellationRequest","outputs":[{"internalType":"uint256","name":"request","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"getDepositBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"}],"name":"getEthKey","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"getFullWithdrawalRequest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"starkKey","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"getQuantizedDepositBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"presumedAssetType","type":"uint256"}],"name":"getQuantum","outputs":[{"internalType":"uint256","name":"quantum","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"getWithdrawalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"identify","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializerSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"}],"name":"isAssetRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"testedAdmin","type":"address"}],"name":"isTokenAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainAcceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mainCancelNomination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"testGovernor","type":"address"}],"name":"mainIsGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newGovernor","type":"address"}],"name":"mainNominateNewGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governorForRemoval","type":"address"}],"name":"mainRemoveGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"orderRegistryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"bytes","name":"assetInfo","type":"bytes"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"bytes","name":"assetInfo","type":"bytes"},{"internalType":"uint256","name":"quantum","type":"uint256"}],"name":"registerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"registerTokenAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unFreeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oldAdmin","type":"address"}],"name":"unregisterTokenAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"validatedSelectors","outputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"bytes","name":"mintingBlob","type":"bytes"}],"name":"withdrawAndMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ownerKey","type":"uint256"},{"internalType":"uint256","name":"assetType","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawWithTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50614e9c806100206000396000f3fe6080604052600436106102e95760003560e01c80638c4bce1c11610186578063bc197c81116100d7578063e30a5cff11610085578063e30a5cff14610f48578063e6de628214610f5d578063ec3161b014610f72578063eeb7286614610fa2578063f23a6e6114610fb7578063f637d95014611057578063fcb0582214611081576102e9565b8063bc197c8114610b99578063be2b110514610ccd578063c23b60ef14610d09578063c8b1031a14610d93578063d88d8b3814610e15578063d91443b714610e97578063dd7202d814610f1e576102e9565b8063a45d784111610134578063a45d7841146109dc578063a6fa6e90146109f1578063abf98fe114610a24578063ae1cdde614610a5a578063ae87381614610a96578063b12773fb14610acc578063b766311214610b84576102e9565b80638c4bce1c146108ad578063993f3639146108e05780639c6a2837146108f55780639ed170841461090a578063a1cc5e1314610946578063a1cc921e14610976578063a2bdde3d146109a9576102e9565b80633cc660ad116102405780635eecd218116101ee5780635eecd218146107ed57806364d84842146108025780636ce5d9571461031557806372eb36881461083857806377e84e0d1461084d5780637cf12b90146108625780637df7dc0414610877576102e9565b80633cc660ad14610658578063439fab911461066d578063441a3e70146106e857806345f5cd971461071857806349325bac1461074b5780634e8912da1461078d5780635e586cd1146107c3576102e9565b80631dbd1da71161029d5780631dbd1da7146105045780632505c3d91461054a57806328700a1514610586578063296e2f371461059b57806329e411ac146105cb578063333ac20b1461060d57806333eeb14714610643576102e9565b8062717542146102ee578062aeef8a14610315578063019b417a14610340578063049f5ade146103765780630b3a2d21146103b45780630ebdac03146103e7578063150b7a021461044c575b600080fd5b3480156102fa57600080fd5b506103036110bd565b60408051918252519081900360200190f35b61033e6004803603606081101561032b57600080fd5b50803590602081013590604001356110c4565b005b34801561034c57600080fd5b5061033e6004803603606081101561036357600080fd5b508035906020810135906040013561112d565b34801561038257600080fd5b506103a06004803603602081101561039957600080fd5b5035611138565b604080519115158252519081900360200190f35b3480156103c057600080fd5b5061033e600480360360208110156103d757600080fd5b50356001600160a01b0316611150565b3480156103f357600080fd5b506103fc6111f7565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104e76004803603608081101561046f57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156104a957600080fd5b8201836020820111156104bb57600080fd5b803590602001918460018302840111600160201b831117156104dc57600080fd5b5090925090506113b0565b604080516001600160e01b03199092168252519081900360200190f35b34801561051057600080fd5b5061052e6004803603602081101561052757600080fd5b50356113dc565b604080516001600160a01b039092168252519081900360200190f35b34801561055657600080fd5b5061033e6004803603608081101561056d57600080fd5b5080359060208101359060408101359060600135611421565b34801561059257600080fd5b5061033e61159b565b3480156105a757600080fd5b50610303600480360360408110156105be57600080fd5b50803590602001356115a5565b3480156105d757600080fd5b5061033e600480360360a08110156105ee57600080fd5b50803590602081013590604081013590606081013590608001356115cc565b34801561061957600080fd5b506103036004803603606081101561063057600080fd5b50803590602081013590604001356117c5565b34801561064f57600080fd5b506103a06117e9565b34801561066457600080fd5b506103036117f9565b34801561067957600080fd5b5061033e6004803603602081101561069057600080fd5b810190602081018135600160201b8111156106aa57600080fd5b8201836020820111156106bc57600080fd5b803590602001918460018302840111600160201b831117156106dd57600080fd5b5090925090506117fe565b3480156106f457600080fd5b5061033e6004803603604081101561070b57600080fd5b508035906020013561183d565b34801561072457600080fd5b506103a06004803603602081101561073b57600080fd5b50356001600160a01b0316611981565b34801561075757600080fd5b5061033e600480360360a081101561076e57600080fd5b5080359060208101359060408101359060608101359060800135611992565b34801561079957600080fd5b50610303600480360360608110156107b057600080fd5b5080359060208101359060400135611a40565b3480156107cf57600080fd5b50610303600480360360208110156107e657600080fd5b5035611a64565b3480156107f957600080fd5b50610303611ad4565b34801561080e57600080fd5b5061033e6004803603606081101561082557600080fd5b5080359060208101359060400135611ada565b34801561084457600080fd5b5061033e611c4b565b34801561085957600080fd5b50610303611c53565b34801561086e57600080fd5b5061033e611c5a565b34801561088357600080fd5b5061033e6004803603606081101561089a57600080fd5b5080359060208101359060400135611d99565b3480156108b957600080fd5b5061033e600480360360208110156108d057600080fd5b50356001600160a01b0316611e5e565b3480156108ec57600080fd5b50610303611e6a565b34801561090157600080fd5b5061052e611e72565b34801561091657600080fd5b5061033e6004803603608081101561092d57600080fd5b5080359060208101359060408101359060600135611e89565b34801561095257600080fd5b506103036004803603604081101561096957600080fd5b5080359060200135611e9b565b34801561098257600080fd5b5061033e6004803603602081101561099957600080fd5b50356001600160a01b0316611fc2565b3480156109b557600080fd5b506103a0600480360360208110156109cc57600080fd5b50356001600160a01b0316611fcb565b3480156109e857600080fd5b50610303611fe9565b3480156109fd57600080fd5b5061033e60048036036020811015610a1457600080fd5b50356001600160a01b0316611ff7565b348015610a3057600080fd5b5061030360048036036060811015610a4757600080fd5b508035906020810135906040013561209b565b348015610a6657600080fd5b5061033e60048036036080811015610a7d57600080fd5b50803590602081013590604081013590606001356120d3565b348015610aa257600080fd5b5061033e60048036036060811015610ab957600080fd5b508035906020810135906040013561217a565b348015610ad857600080fd5b5061030360048036036040811015610aef57600080fd5b81359190810190604081016020820135600160201b811115610b1057600080fd5b820183602082011115610b2257600080fd5b803590602001918460018302840111600160201b83111715610b4357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122a8945050505050565b348015610b9057600080fd5b50610303612369565b348015610ba557600080fd5b506104e7600480360360a0811015610bbc57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b811115610bef57600080fd5b820183602082011115610c0157600080fd5b803590602001918460208302840111600160201b83111715610c2257600080fd5b919390929091602081019035600160201b811115610c3f57600080fd5b820183602082011115610c5157600080fd5b803590602001918460208302840111600160201b83111715610c7257600080fd5b919390929091602081019035600160201b811115610c8f57600080fd5b820183602082011115610ca157600080fd5b803590602001918460018302840111600160201b83111715610cc257600080fd5b509092509050612370565b348015610cd957600080fd5b5061033e60048036036080811015610cf057600080fd5b508035906020810135906040810135906060013561239f565b348015610d1557600080fd5b50610d1e612549565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610d58578181015183820152602001610d40565b50505050905090810190601f168015610d855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610d9f57600080fd5b5061033e60048036036040811015610db657600080fd5b81359190810190604081016020820135600160201b811115610dd757600080fd5b820183602082011115610de957600080fd5b803590602001918460018302840111600160201b83111715610e0a57600080fd5b509092509050612565565b348015610e2157600080fd5b5061033e60048036036060811015610e3857600080fd5b81359190810190604081016020820135600160201b811115610e5957600080fd5b820183602082011115610e6b57600080fd5b803590602001918460018302840111600160201b83111715610e8c57600080fd5b91935091503561256e565b348015610ea357600080fd5b5061033e60048036036060811015610eba57600080fd5b813591602081013591810190606081016040820135600160201b811115610ee057600080fd5b820183602082011115610ef257600080fd5b803590602001918460018302840111600160201b83111715610f1357600080fd5b509092509050612910565b348015610f2a57600080fd5b5061030360048036036020811015610f4157600080fd5b5035612b06565b348015610f5457600080fd5b50610303612b37565b348015610f6957600080fd5b50610303612b3c565b348015610f7e57600080fd5b5061030360048036036040811015610f9557600080fd5b5080359060200135612b41565b348015610fae57600080fd5b50610d1e612b70565b348015610fc357600080fd5b506104e7600480360360a0811015610fda57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561101957600080fd5b82018360208201111561102b57600080fd5b803590602001918460018302840111600160201b8311171561104c57600080fd5b509092509050612b90565b34801561106357600080fd5b50610d1e6004803603602081101561107a57600080fd5b5035612bbd565b34801561108d57600080fd5b5061033e600480360360808110156110a457600080fd5b5080359060208101359060408101359060600135612cbe565b62093a8081565b6110cd82612d27565b611113576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6111288383836111238634612d4b565b611421565b505050565b611128838383611ada565b60008181526015602052604090205460ff165b919050565b61115933612db8565b61119c576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6001600160a01b038116600081815260116020908152604091829020805460ff19166001179055815192835290517f9085a9044aeb6daeeb5b4bf84af42b1a1613d4056f503c4e992b6396c16bd52f9281900390910190a150565b60408051600680825260e0820190925260609190600090826020820160c08036833750508151919450506001820191631f7df70160e21b91859190811061123a57fe5b6001600160e01b0319909216602092830291909101909101528251600182019163be2b110560e01b91859190811061126e57fe5b6001600160e01b031990921660209283029190910190910152825160018201916357439c0b60e11b9185919081106112a257fe5b6001600160e01b03199092166020928302919091019091015282516001820191630441a3e760e41b9185919081106112d657fe5b6001600160e01b0319909216602092830291909101909101528251600182019163d91443b760e01b91859190811061130a57fe5b6001600160e01b0319909216602092830291909101909101528251600182019163326c242160e11b91859190811061133e57fe5b6001600160e01b0319909216602092830291909101909101528082146113ab576040805162461bcd60e51b815260206004820181905260248201527f494e434f52524543545f53454c4543544f52535f41525241595f4c454e475448604482015290519081900360640190fd5b505090565b60006001600160a01b03861630146113c95760006113d2565b630a85bd0160e11b5b9695505050505050565b6000818152601860205260408120546001600160a01b0316801561140157905061114b565b6001600160a01b038316831461141857600061141a565b825b9392505050565b6114296117e9565b1561146d576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b61147683612de7565b156114be576040805162461bcd60e51b81526020600482015260136024820152724d494e5441424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6114c783612e2b565b611512576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b8261151f85828585612e8a565b5061152a8483612f7f565b7f06724742ccc8c330a39a641ef02a0b419bd09248360680bb38159b0a8c2635d6338685876115598988613244565b604080516001600160a01b0390961686526020860194909452848401929092526060840152608083015260a08201859052519081900360c00190a15050505050565b6115a36132b5565b565b6000602260006115b5858561337c565b815260200190815260200160002054905092915050565b6115d46117e9565b15611618576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b611621846133d6565b611667576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b60006116738585611e9b565b9050600061168387838686612e8a565b905061168e8661341a565b156117375760018111156116e1576040805162461bcd60e51b81526020600482015260156024820152741253131151d05317d15490cdcc8c57d05353d55395605a1b604482015290519081900360640190fd5b6040805133815260208101899052808201869052606081018890526080810187905260a0810184905290517f0fcf2162832b2d6033d4d34d2f45a28d9cfee523f1899945bbdd32529cfda67b9181900360c00190a15b61174286868561342d565b7fed94dc026fa9364c53bc0af51cde7f54f3109b3f31fceb26d01396d80e20453b3388868989876117738d8b613244565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c083015260e0820186905251908190036101000190a150505050505050565b60009283526007602090815260408085209385529281528284209184525290205490565b600454600160a01b900460ff1690565b600090565b6040805162461bcd60e51b815260206004820152600f60248201526e1393d517d253541311535153951151608a1b604482015290519081900360640190fd5b6000611848836134f1565b905061185382612de7565b1561189b576040805162461bcd60e51b81526020600482015260136024820152724d494e5441424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6118a482612e2b565b6118ef576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b600083815260086020908152604080832085845290915281208054919055829061191a83838361354d565b7fb7477a7b93b2addc5272bbd7ad0986ef1c0d0bd265f26c3dc4bbe42727c2ac0c85856119478785613244565b60408051938452602084019290925282820152606082018490526001600160a01b0386166080830152519081900360a00190a15050505050565b600061198c82612db8565b92915050565b61199a6117e9565b156119de576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b6119e7846137e4565b611a2c576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b611a3985858585856115cc565b5050505050565b60009283526006602090815260408085209385529281528284209184525290205490565b6024546000908210611ab5576040805162461bcd60e51b815260206004820152601560248201527408286a8929e9cbe929c888ab0bea89e9ebe90928e9605b1b604482015290519081900360640190fd5b60248281548110611ac257fe5b90600052602060002001549050919050565b60245490565b611ae3826133d6565b611b29576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6000611b358383611e9b565b90506000611b42856134f1565b600086815260086020908152604080832086845290915281208054919055909150611b6f828686846137f7565b611b788561341a565b15611bd4576040805187815260208101879052808201869052606081018590526001600160a01b038416608082015290517fa5cfa8e2199ec5b8ca319288bcab72734207d30569756ee594a74b4df7abbf419181900360a00190a15b7fc6ba68235f3229e53f3a95cda25543ad54c0f6df2493a06c05fb930bea7966fe86868686611c038a87613244565b604080519586526020860194909452848401929092526060840152608083015260a082018490526001600160a01b03851660c0830152519081900360e00190a1505050505050565b6115a36138bd565b6202a30081565b611c626117e9565b611ca6576040805162461bcd60e51b815260206004820152601060248201526f29aa20aa22afa727aa2fa32927ad22a760811b604482015290519081900360640190fd5b611caf33612db8565b611cf2576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b600554421015611d44576040805162461bcd60e51b8152602060048201526018602482015277155391949151569157d393d517d0531313d5d15117d6515560421b604482015290519081900360640190fd5b6004805460ff60a01b19169055600d805460019081019091556025805482019055600f805490910190556040517f07017fe9180629cfffba412f65a9affcf9a121de02294179f5c058f881dcc9f890600090a1565b82611da3816134f1565b6001600160a01b0316336001600160a01b031614611df6576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b60008481526007602090815260408083208684528252808320858452825291829020429055815186815290810184905280820185905290517f0bc1df35228095c37da66a6ffcc755ea79dfc437345685f618e05fafad6b445e9181900360600190a150505050565b611e6781613954565b50565b6301e1338081565b68010000000000000004546001600160a01b031681565b611e9584848484611421565b50505050565b6000611ea6836133d6565b611ee15760405162461bcd60e51b8152600401808060200182810382526021815260200180614dff6021913960400191505060405180910390fd5b6060611eec8461341a565b611f1b576040518060400160405280600d81526020016c2727a72fa6a4a72a20a126229d60991b815250611f39565b6040518060400160405280600481526020016327232a1d60e11b8152505b90506001600160fa1b038185856040516020018084805190602001908083835b60208310611f785780518252601f199092019160209182019101611f59565b51815160209384036101000a600019018019909216911617905292019485525083810192909252506040805180840383018152928101905281519101209190911695945050505050565b611e6781613a51565b6001600160a01b031660009081526011602052604090205460ff1690565b680100000000000000035481565b61200033612db8565b612043576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6001600160a01b038116600081815260116020908152604091829020805460ff19169055815192835290517ffa49aecb996ea8d99950bb051552dfcc0b5460a0bb209867a1ed8067c32c21779281900390910190a150565b6000838152600660209081526040808320858452825280832084845290915281205483906120ca908290613244565b95945050505050565b6120db6117e9565b1561211f576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b6121288361341a565b61216c576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b611e958484838560016115cc565b82612184816134f1565b6001600160a01b0316336001600160a01b0316146121d7576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b6121e083612e2b565b61222b576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b826000612239868386613b9e565b905061224633868361354d565b7fe3e46ecf1138180bf93cba62a0b7e661d976a8ab3d40243f7b082667d8f500af8685876122748986613244565b60408051948552602085019390935283830191909152606083015260808201849052519081900360a00190a1505050505050565b600080828051906020012060001c9050600160fa1b6001600160f01b036040518060400160405280600981526020016826a4a72a20a126229d60b91b81525086846040516020018084805190602001908083835b6020831061231b5780518252601f1990920191602091820191016122fc565b51815160209384036101000a60001901801990921691161790529201948552508381019290925250604080518084038301815292810190528151910120919091169190911795945050505050565b6224ea0081565b60006001600160a01b0389163014612389576000612392565b63bc197c8160e01b5b9998505050505050505050565b836123a9816134f1565b6001600160a01b0316336001600160a01b0316146123fc576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b612405846133d6565b61244b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b60006124578585611e9b565b90506000612466878386613b9e565b9050801561247a5761247a338787846137f7565b6124838661341a565b156124d7576040805188815260208101869052808201889052606081018790526080810184905290517ff00c0c1a754f6df7545d96a7e12aad552728b94ca6aa94f81e297bdbcf1dab9c9181900360a00190a15b7fcc00f2179d127845242252f3c3b6b238c5ed33c2e933179f09653cfb1cdee7ca87858888866125078c88613244565b604080519687526020870195909552858501939093526060850191909152608084015260a083015260c08201849052519081900360e00190a150505050505050565b604051806060016040528060268152602001614e206026913981565b61112883838360015b61257733611fcb565b6125bc576040805162461bcd60e51b815260206004820152601160248201527027a7262cafaa27a5a2a729afa0a226a4a760791b604482015290519081900360640190fd5b6125c584611138565b15612612576040805162461bcd60e51b81526020600482015260186024820152771054d4d15517d053149150511657d49151d254d51154915160421b604482015290519081900360640190fd5b600167080000000000001160c01b018410612669576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b600081116126b0576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5155414e54554d60881b604482015290519081900360640190fd5b600160801b81106126fa576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5155414e54554d60881b604482015290519081900360640190fd5b60006001600160fa1b0384848460405160200180848480828437919091019283525050604080518083038152602092830190915280519101209290921692505050848114612784576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6127c384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cab92505050565b61280284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e2792505050565b156128525781600114612852576040805162461bcd60e51b8152602060048201526013602482015272494e56414c49445f4e46545f5155414e54554d60681b604482015290519081900360640190fd5b6000858152601560209081526040808320805460ff1916600117905560149091529020612880908585614d2b565b508160166000878152602001908152602001600020819055507f7a0efbc885500f3b4a895231945be4520e4c0ba5ef7274a225a0272c81ccbcb78585858560405180858152602001806020018381526020018281038252858582818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b600061291b856134f1565b60008581526015602052604090205490915060ff16612976576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b61297f84612de7565b6129ca576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f4d494e5441424c455f41535345545f5459504560481b604482015290519081900360640190fd5b6000612a0c8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122a892505050565b6000878152600860209081526040808320848452909152902054909150612a7a576040805162461bcd60e51b815260206004820152601d60248201527f4e4f5f50454e44494e475f5749544844524157414c5f42414c414e4345000000604482015290519081900360640190fd5b600086815260086020908152604080832084845290915281208054919055612aa58682858888613e6b565b7f7e6e15df814c1a309a57686de672b2bedd128eacde35c5370c36d6840d4e9a928787612ad28985613244565b604080519384526020840192909252828201526060820184905260808201859052519081900360a00190a150505050505050565b60008181526015602052604081205460ff16612b245750600161114b565b5060009081526016602052604090205490565b600a81565b604081565b60008281526008602090815260408083208484529091528120548290612b68908290613244565b949350505050565b6060604051806060016040528060218152602001614e4660219139905090565b60006001600160a01b0387163014612ba9576000612bb2565b63f23a6e6160e01b5b979650505050505050565b60008181526015602052604090205460609060ff16612c1f576040805162461bcd60e51b81526020600482015260196024820152781054d4d15517d516541157d393d517d49151d254d511549151603a1b604482015290519081900360640190fd5b60008281526014602090815260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015612cb25780601f10612c8757610100808354040283529160200191612cb2565b820191906000526020600020905b815481529060010190602001808311612c9557829003601f168201915b50505050509050919050565b83612cc8816134f1565b6001600160a01b0316336001600160a01b031614612d1b576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b611a398585848661239f565b60006341917ff960e11b612d3a8361400d565b6001600160e01b0319161492915050565b600080612d5784612b06565b9050808381612d6257fe5b0615612da6576040805162461bcd60e51b815260206004820152600e60248201526d1253959053125117d05353d5539560921b604482015290519081900360640190fd5b808381612daf57fe5b04949350505050565b600080612dc3614020565b6001600160a01b039390931660009081526020939093525050604090205460ff1690565b600080612df38361400d565b90506001600160e01b031981166368646e2d60e01b148061141a57506001600160e01b03198116635c5c333960e11b14915050919050565b600080612e378361400d565b90506001600160e01b031981166341917ff960e11b1480612e6857506001600160e01b03198116630f47261b60e41b145b8061141a57506001600160e01b031981166368646e2d60e01b14915050919050565b60008481526006602090815260408083208684528252808320858452909152812054820182811015612ef6576040805162461bcd60e51b815260206004820152601060248201526f4445504f5349545f4f564552464c4f5760801b604482015290519081900360640190fd5b600086815260066020908152604080832088845282528083208784529091529020819055612f238661409d565b8015612f4f57506000868152600760209081526040808320888452825280832087845290915290205415155b156120ca576000868152600760209081526040808320888452825280832087845290915281205595945050505050565b6000612f8b8383613244565b9050612f96836140c3565b156131985781612fa65750613240565b6000612fb1846140d6565b905060008190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d602081101561303157600080fd5b50516040805133602482015230604482015260648082018890528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905290915061308d6001600160a01b038516826140e9565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505190508281101561314a576040805162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015290519081900360640190fd5b858301811461318e576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050611128565b6131a183612d27565b156131fa578034146131f5576040805162461bcd60e51b8152602060048201526018602482015277125390d3d4949150d517d1115413d4d25517d05353d5539560421b604482015290519081900360640190fd5b611128565b6040805162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f544f4b454e5f5459504560501b604482015290519081900360640190fd5b5050565b60008061325084612b06565b905080830291508281838161326157fe5b04146132ae576040805162461bcd60e51b815260206004820152601760248201527644455155414e54495a4154494f4e5f4f564552464c4f5760481b604482015290519081900360640190fd5b5092915050565b60006132bf614020565b60018101549091506001600160a01b0316331461331d576040805162461bcd60e51b815260206004820152601760248201527627a7262cafa1a0a72224a220aa22afa3a7ab22a92727a960491b604482015290519081900360640190fd5b6001810154613334906001600160a01b03166142d5565b6001810180546001600160a01b03191690556040805133815290517fcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d29181900360200190a150565b600061141a6040518060400160405280600f81526020016e1195531317d5d2551211149055d053608a1b81525084846040516020018083815260200182815260200192505050604051602081830303815290604052614355565b6000806133e28361400d565b90506001600160e01b0319811663012b8bc960e11b148061141a57506001600160e01b03198116633348691d60e01b14915050919050565b600063012b8bc960e11b612d3a8361400d565b613436836133d6565b61347d576040805162461bcd60e51b815260206004820152601360248201527246554e4749424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6134868361341a565b156134e057806001146134d6576040805162461bcd60e51b8152602060048201526013602482015272494c4c4547414c5f4e46545f42414c414e434560681b604482015290519081900360640190fd5b6131f58383614417565b8015611128576111288383836144ca565b60006134fc826113dc565b90506001600160a01b03811661114b576040805162461bcd60e51b81526020600482015260116024820152701554d15497d553949151d254d511549151607a1b604482015290519081900360640190fd5b6001600160a01b03831661359c576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b60006135a88383613244565b90506135b3836140c3565b156137b357816135c35750611128565b60006135ce846140d6565b905060008190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561362457600080fd5b505afa158015613638573d6000803e3d6000fd5b505050506040513d602081101561364e57600080fd5b5051604080516001600160a01b03808b16602483015260448083018990528351808403909101815260649092019092526020810180516001600160e01b031663a9059cbb60e01b1790529192506136a7908516826140e9565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156136f657600080fd5b505afa15801561370a573d6000803e3d6000fd5b505050506040513d602081101561372057600080fd5b5051905082811115613765576040805162461bcd60e51b8152602060048201526009602482015268554e444552464c4f5760b81b604482015290519081900360640190fd5b85830381146137a9576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050611e95565b6137bc83612d27565b156131fa57816137cc5750611128565b6137df6001600160a01b038516826147e0565b611e95565b6000633348691d60e01b612d3a8361400d565b613800836133d6565b613847576040805162461bcd60e51b815260206004820152601360248201527246554e4749424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6138508361341a565b156138ab57806001146138a0576040805162461bcd60e51b8152602060048201526013602482015272494c4c4547414c5f4e46545f42414c414e434560681b604482015290519081900360640190fd5b6137df84848461487c565b8015611e9557611e9584848484614981565b6138c633612db8565b613909576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6000613913614020565b6001810180546001600160a01b03191690556040519091507f7a8dc7dd7fffb43c4807438fa62729225156941e641fd877938f4edade3429f590600090a150565b61395d33612db8565b6139a0576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b60006139aa614020565b90506139b582612db8565b156139fa576040805162461bcd60e51b815260206004820152601060248201526f20a62922a0a22cafa3a7ab22a92727a960811b604482015290519081900360640190fd5b6001810180546001600160a01b0384166001600160a01b0319909116811790915560408051918252517f6166272c8d3f5f579082f2827532732f97195007983bb5b83ac12c56700b01a69181900360200190a15050565b613a5a33612db8565b613a9d576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b336001600160a01b0382161415613af2576040805162461bcd60e51b8152602060048201526014602482015273474f5645524e4f525f53454c465f52454d4f564560601b604482015290519081900360640190fd5b6000613afc614020565b9050613b0782612db8565b613b47576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa3a7ab22a92727a960a11b604482015290519081900360640190fd5b6001600160a01b03821660008181526020838152604091829020805460ff19169055815192835290517fd75f94825e770b8b512be8e74759e252ad00e102e38f50cce2f7c6f868a295999281900390910190a15050565b6000838152600760209081526040808320858452825280832084845290915281205480613c09576040805162461bcd60e51b815260206004820152601460248201527311115413d4d25517d393d517d0d05390d153115160621b604482015290519081900360640190fd5b6202a30081810190811015613c1a57fe5b80421015613c60576040805162461bcd60e51b815260206004820152600e60248201526d11115413d4d25517d313d0d2d15160921b604482015290519081900360640190fd5b50505060008381526006602090815260408083208584528252808320848452825280832080549084905595835260078252808320948352938152838220928252919091529081205590565b6000613cb682614c6e565b9050613cc181614c7f565b613d0b576040805162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f544f4b454e5f5459504560501b604482015290519081900360640190fd5b6001600160e01b031981166341917ff960e11b1415613d76578151600414613d71576040805162461bcd60e51b8152602060048201526014602482015273494e56414c49445f41535345545f535452494e4760601b604482015290519081900360640190fd5b613240565b8151602414613dc3576040805162461bcd60e51b8152602060048201526014602482015273494e56414c49445f41535345545f535452494e4760601b604482015290519081900360640190fd5b6000613dce83614d1e565b9050613de2816001600160a01b0316614d25565b611128576040805162461bcd60e51b81526020600482015260116024820152704241445f544f4b454e5f4144445245535360781b604482015290519081900360640190fd5b600080613e3383614c6e565b90506001600160e01b0319811663012b8bc960e11b148061141a57506001600160e01b03198116635c5c333960e11b14915050919050565b6001600160a01b038316613eba576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b613ec385612de7565b613f0e576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f4d494e5441424c455f41535345545f5459504560481b604482015290519081900360640190fd5b60008411613f59576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d352539517d05353d55395606a1b604482015290519081900360640190fd5b6000613f658686613244565b90506000613f72876140d6565b90506140048583868660405160240180856001600160a01b0316815260200184815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516319ee6e3f60e01b6001600160e01b039091161790526001600160a01b038916965094506140e99350505050565b50505050505050565b600061198c61401b83612bbd565b614c6e565b600080604051806060016040528060268152602001614e20602691396040518082805190602001908083835b6020831061406b5780518252601f19909201916020918201910161404c565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092209392505050565b60006140a8826113dc565b6001600160a01b0316336001600160a01b0316149050919050565b6000630f47261b60e41b612d3a8361400d565b600061198c6140e483612bbd565b614d1e565b6140f282614d25565b614137576040805162461bcd60e51b81526020600482015260116024820152704241445f544f4b454e5f4144445245535360781b604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106141755780518252601f199092019160209182019101614156565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146141d7576040519150601f19603f3d011682016040523d82523d6000602084013e6141dc565b606091505b509150915081819061426c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614231578181015183820152602001614219565b50505050905090810190601f16801561425e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50805115611e955780806020019051602081101561428957600080fd5b5051611e95576040805162461bcd60e51b81526020600482015260166024820152751513d2d15397d3d4115490551253d397d1905253115160521b604482015290519081900360640190fd5b6142de81612db8565b15614323576040805162461bcd60e51b815260206004820152601060248201526f20a62922a0a22cafa3a7ab22a92727a960811b604482015290519081900360640190fd5b600061432d614020565b6001600160a01b0390921660009081526020929092525060409020805460ff19166001179055565b600082826040516020018083805190602001908083835b6020831061438b5780518252601f19909201916020918201910161436c565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106143d35780518252601f1990920191602091820191016143b4565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905092915050565b6144208261341a565b614464576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b600061446f836140d6565b6040805133602482015230604482015260648082018690528251808303909101815260849091019091526020810180516001600160e01b0316632142170760e11b179052909150611128906001600160a01b038316906140e9565b6144d3836137e4565b614518576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b8061452257611128565b600061452e8483613244565b9050600061453b856140d6565b60408051627eeac760e11b815230600482015260248101879052905191925082916000916001600160a01b0384169162fdd58e91604480820192602092909190829003018186803b15801561458f57600080fd5b505afa1580156145a3573d6000803e3d6000fd5b505050506040513d60208110156145b957600080fd5b810190808051906020019092919050505090506146ce63f242432a60e01b333089886040518060200160405280600081525060405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561465557818101518382015260200161463d565b50505050905090810190601f1680156146825780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909a169990991790985250506001600160a01b038a16959450506140e992505050565b6000826001600160a01b031662fdd58e30896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561472457600080fd5b505afa158015614738573d6000803e3d6000fd5b505050506040513d602081101561474e57600080fd5b5051905081811015614792576040805162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015290519081900360640190fd5b84820181146147d6576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050505050565b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461482b576040519150601f19603f3d011682016040523d82523d6000602084013e614830565b606091505b5050905080611128576040805162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b604482015290519081900360640190fd5b6001600160a01b0383166148cb576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b6148d48261341a565b614918576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b6000614923836140d6565b604080513060248201526001600160a01b03808816604483015260648083018790528351808403909101815260849092019092526020810180516001600160e01b0316632142170760e11b179052919250611e9591908316906140e9565b6001600160a01b0384166149d0576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b6149d9836137e4565b614a1e576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b80614a2857611e95565b6000614a348483613244565b90506000614a41856140d6565b60408051627eeac760e11b815230600482015260248101879052905191925082916000916001600160a01b0384169162fdd58e91604480820192602092909190829003018186803b158015614a9557600080fd5b505afa158015614aa9573d6000803e3d6000fd5b505050506040513d6020811015614abf57600080fd5b81019080805190602001909291905050509050614b5a63f242432a60e01b308a89886040518060200160405280600081525060405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360008381101561465557818101518382015260200161463d565b6000826001600160a01b031662fdd58e30896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b158015614bb057600080fd5b505afa158015614bc4573d6000803e3d6000fd5b505050506040513d6020811015614bda57600080fd5b5051905081811115614c1f576040805162461bcd60e51b8152602060048201526009602482015268554e444552464c4f5760b81b604482015290519081900360640190fd5b8482038114614c63576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b505050505050505050565b602001516001600160e01b03191690565b60006001600160e01b031982166341917ff960e11b1480614cb057506001600160e01b03198216630f47261b60e41b145b80614ccb57506001600160e01b0319821663012b8bc960e11b145b80614ce657506001600160e01b031982166368646e2d60e01b145b80614d0157506001600160e01b03198216635c5c333960e11b145b8061198c5750506001600160e01b031916633348691d60e01b1490565b6024015190565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614d6c5782800160ff19823516178555614d99565b82800160010185558215614d99579182015b82811115614d99578235825591602001919060010190614d7e565b50614da5929150614da9565b5090565b5b80821115614da55760008155600101614daa56fe494e434f52524543545f414d4f554e545f5452414e53464552524544000000004d49534d41544348494e475f535441524b5f4554485f4b45595300000000000041535345545f545950455f444f45535f4e4f545f54414b455f544f4b454e5f4944537461726b45782e4d61696e2e323031392e476f7665726e6f7273496e666f726d6174696f6e537461726b576172655f546f6b656e73416e6452616d70696e675f323032325f32a2646970667358221220dceb72817044db7cba290582a0d8c7b21878ca86d2edb87a60b1165772a90f3664736f6c634300060c0033

Deployed Bytecode

0x6080604052600436106102e95760003560e01c80638c4bce1c11610186578063bc197c81116100d7578063e30a5cff11610085578063e30a5cff14610f48578063e6de628214610f5d578063ec3161b014610f72578063eeb7286614610fa2578063f23a6e6114610fb7578063f637d95014611057578063fcb0582214611081576102e9565b8063bc197c8114610b99578063be2b110514610ccd578063c23b60ef14610d09578063c8b1031a14610d93578063d88d8b3814610e15578063d91443b714610e97578063dd7202d814610f1e576102e9565b8063a45d784111610134578063a45d7841146109dc578063a6fa6e90146109f1578063abf98fe114610a24578063ae1cdde614610a5a578063ae87381614610a96578063b12773fb14610acc578063b766311214610b84576102e9565b80638c4bce1c146108ad578063993f3639146108e05780639c6a2837146108f55780639ed170841461090a578063a1cc5e1314610946578063a1cc921e14610976578063a2bdde3d146109a9576102e9565b80633cc660ad116102405780635eecd218116101ee5780635eecd218146107ed57806364d84842146108025780636ce5d9571461031557806372eb36881461083857806377e84e0d1461084d5780637cf12b90146108625780637df7dc0414610877576102e9565b80633cc660ad14610658578063439fab911461066d578063441a3e70146106e857806345f5cd971461071857806349325bac1461074b5780634e8912da1461078d5780635e586cd1146107c3576102e9565b80631dbd1da71161029d5780631dbd1da7146105045780632505c3d91461054a57806328700a1514610586578063296e2f371461059b57806329e411ac146105cb578063333ac20b1461060d57806333eeb14714610643576102e9565b8062717542146102ee578062aeef8a14610315578063019b417a14610340578063049f5ade146103765780630b3a2d21146103b45780630ebdac03146103e7578063150b7a021461044c575b600080fd5b3480156102fa57600080fd5b506103036110bd565b60408051918252519081900360200190f35b61033e6004803603606081101561032b57600080fd5b50803590602081013590604001356110c4565b005b34801561034c57600080fd5b5061033e6004803603606081101561036357600080fd5b508035906020810135906040013561112d565b34801561038257600080fd5b506103a06004803603602081101561039957600080fd5b5035611138565b604080519115158252519081900360200190f35b3480156103c057600080fd5b5061033e600480360360208110156103d757600080fd5b50356001600160a01b0316611150565b3480156103f357600080fd5b506103fc6111f7565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104e76004803603608081101561046f57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156104a957600080fd5b8201836020820111156104bb57600080fd5b803590602001918460018302840111600160201b831117156104dc57600080fd5b5090925090506113b0565b604080516001600160e01b03199092168252519081900360200190f35b34801561051057600080fd5b5061052e6004803603602081101561052757600080fd5b50356113dc565b604080516001600160a01b039092168252519081900360200190f35b34801561055657600080fd5b5061033e6004803603608081101561056d57600080fd5b5080359060208101359060408101359060600135611421565b34801561059257600080fd5b5061033e61159b565b3480156105a757600080fd5b50610303600480360360408110156105be57600080fd5b50803590602001356115a5565b3480156105d757600080fd5b5061033e600480360360a08110156105ee57600080fd5b50803590602081013590604081013590606081013590608001356115cc565b34801561061957600080fd5b506103036004803603606081101561063057600080fd5b50803590602081013590604001356117c5565b34801561064f57600080fd5b506103a06117e9565b34801561066457600080fd5b506103036117f9565b34801561067957600080fd5b5061033e6004803603602081101561069057600080fd5b810190602081018135600160201b8111156106aa57600080fd5b8201836020820111156106bc57600080fd5b803590602001918460018302840111600160201b831117156106dd57600080fd5b5090925090506117fe565b3480156106f457600080fd5b5061033e6004803603604081101561070b57600080fd5b508035906020013561183d565b34801561072457600080fd5b506103a06004803603602081101561073b57600080fd5b50356001600160a01b0316611981565b34801561075757600080fd5b5061033e600480360360a081101561076e57600080fd5b5080359060208101359060408101359060608101359060800135611992565b34801561079957600080fd5b50610303600480360360608110156107b057600080fd5b5080359060208101359060400135611a40565b3480156107cf57600080fd5b50610303600480360360208110156107e657600080fd5b5035611a64565b3480156107f957600080fd5b50610303611ad4565b34801561080e57600080fd5b5061033e6004803603606081101561082557600080fd5b5080359060208101359060400135611ada565b34801561084457600080fd5b5061033e611c4b565b34801561085957600080fd5b50610303611c53565b34801561086e57600080fd5b5061033e611c5a565b34801561088357600080fd5b5061033e6004803603606081101561089a57600080fd5b5080359060208101359060400135611d99565b3480156108b957600080fd5b5061033e600480360360208110156108d057600080fd5b50356001600160a01b0316611e5e565b3480156108ec57600080fd5b50610303611e6a565b34801561090157600080fd5b5061052e611e72565b34801561091657600080fd5b5061033e6004803603608081101561092d57600080fd5b5080359060208101359060408101359060600135611e89565b34801561095257600080fd5b506103036004803603604081101561096957600080fd5b5080359060200135611e9b565b34801561098257600080fd5b5061033e6004803603602081101561099957600080fd5b50356001600160a01b0316611fc2565b3480156109b557600080fd5b506103a0600480360360208110156109cc57600080fd5b50356001600160a01b0316611fcb565b3480156109e857600080fd5b50610303611fe9565b3480156109fd57600080fd5b5061033e60048036036020811015610a1457600080fd5b50356001600160a01b0316611ff7565b348015610a3057600080fd5b5061030360048036036060811015610a4757600080fd5b508035906020810135906040013561209b565b348015610a6657600080fd5b5061033e60048036036080811015610a7d57600080fd5b50803590602081013590604081013590606001356120d3565b348015610aa257600080fd5b5061033e60048036036060811015610ab957600080fd5b508035906020810135906040013561217a565b348015610ad857600080fd5b5061030360048036036040811015610aef57600080fd5b81359190810190604081016020820135600160201b811115610b1057600080fd5b820183602082011115610b2257600080fd5b803590602001918460018302840111600160201b83111715610b4357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122a8945050505050565b348015610b9057600080fd5b50610303612369565b348015610ba557600080fd5b506104e7600480360360a0811015610bbc57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b811115610bef57600080fd5b820183602082011115610c0157600080fd5b803590602001918460208302840111600160201b83111715610c2257600080fd5b919390929091602081019035600160201b811115610c3f57600080fd5b820183602082011115610c5157600080fd5b803590602001918460208302840111600160201b83111715610c7257600080fd5b919390929091602081019035600160201b811115610c8f57600080fd5b820183602082011115610ca157600080fd5b803590602001918460018302840111600160201b83111715610cc257600080fd5b509092509050612370565b348015610cd957600080fd5b5061033e60048036036080811015610cf057600080fd5b508035906020810135906040810135906060013561239f565b348015610d1557600080fd5b50610d1e612549565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610d58578181015183820152602001610d40565b50505050905090810190601f168015610d855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610d9f57600080fd5b5061033e60048036036040811015610db657600080fd5b81359190810190604081016020820135600160201b811115610dd757600080fd5b820183602082011115610de957600080fd5b803590602001918460018302840111600160201b83111715610e0a57600080fd5b509092509050612565565b348015610e2157600080fd5b5061033e60048036036060811015610e3857600080fd5b81359190810190604081016020820135600160201b811115610e5957600080fd5b820183602082011115610e6b57600080fd5b803590602001918460018302840111600160201b83111715610e8c57600080fd5b91935091503561256e565b348015610ea357600080fd5b5061033e60048036036060811015610eba57600080fd5b813591602081013591810190606081016040820135600160201b811115610ee057600080fd5b820183602082011115610ef257600080fd5b803590602001918460018302840111600160201b83111715610f1357600080fd5b509092509050612910565b348015610f2a57600080fd5b5061030360048036036020811015610f4157600080fd5b5035612b06565b348015610f5457600080fd5b50610303612b37565b348015610f6957600080fd5b50610303612b3c565b348015610f7e57600080fd5b5061030360048036036040811015610f9557600080fd5b5080359060200135612b41565b348015610fae57600080fd5b50610d1e612b70565b348015610fc357600080fd5b506104e7600480360360a0811015610fda57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b81111561101957600080fd5b82018360208201111561102b57600080fd5b803590602001918460018302840111600160201b8311171561104c57600080fd5b509092509050612b90565b34801561106357600080fd5b50610d1e6004803603602081101561107a57600080fd5b5035612bbd565b34801561108d57600080fd5b5061033e600480360360808110156110a457600080fd5b5080359060208101359060408101359060600135612cbe565b62093a8081565b6110cd82612d27565b611113576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6111288383836111238634612d4b565b611421565b505050565b611128838383611ada565b60008181526015602052604090205460ff165b919050565b61115933612db8565b61119c576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6001600160a01b038116600081815260116020908152604091829020805460ff19166001179055815192835290517f9085a9044aeb6daeeb5b4bf84af42b1a1613d4056f503c4e992b6396c16bd52f9281900390910190a150565b60408051600680825260e0820190925260609190600090826020820160c08036833750508151919450506001820191631f7df70160e21b91859190811061123a57fe5b6001600160e01b0319909216602092830291909101909101528251600182019163be2b110560e01b91859190811061126e57fe5b6001600160e01b031990921660209283029190910190910152825160018201916357439c0b60e11b9185919081106112a257fe5b6001600160e01b03199092166020928302919091019091015282516001820191630441a3e760e41b9185919081106112d657fe5b6001600160e01b0319909216602092830291909101909101528251600182019163d91443b760e01b91859190811061130a57fe5b6001600160e01b0319909216602092830291909101909101528251600182019163326c242160e11b91859190811061133e57fe5b6001600160e01b0319909216602092830291909101909101528082146113ab576040805162461bcd60e51b815260206004820181905260248201527f494e434f52524543545f53454c4543544f52535f41525241595f4c454e475448604482015290519081900360640190fd5b505090565b60006001600160a01b03861630146113c95760006113d2565b630a85bd0160e11b5b9695505050505050565b6000818152601860205260408120546001600160a01b0316801561140157905061114b565b6001600160a01b038316831461141857600061141a565b825b9392505050565b6114296117e9565b1561146d576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b61147683612de7565b156114be576040805162461bcd60e51b81526020600482015260136024820152724d494e5441424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6114c783612e2b565b611512576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b8261151f85828585612e8a565b5061152a8483612f7f565b7f06724742ccc8c330a39a641ef02a0b419bd09248360680bb38159b0a8c2635d6338685876115598988613244565b604080516001600160a01b0390961686526020860194909452848401929092526060840152608083015260a08201859052519081900360c00190a15050505050565b6115a36132b5565b565b6000602260006115b5858561337c565b815260200190815260200160002054905092915050565b6115d46117e9565b15611618576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b611621846133d6565b611667576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b60006116738585611e9b565b9050600061168387838686612e8a565b905061168e8661341a565b156117375760018111156116e1576040805162461bcd60e51b81526020600482015260156024820152741253131151d05317d15490cdcc8c57d05353d55395605a1b604482015290519081900360640190fd5b6040805133815260208101899052808201869052606081018890526080810187905260a0810184905290517f0fcf2162832b2d6033d4d34d2f45a28d9cfee523f1899945bbdd32529cfda67b9181900360c00190a15b61174286868561342d565b7fed94dc026fa9364c53bc0af51cde7f54f3109b3f31fceb26d01396d80e20453b3388868989876117738d8b613244565b604080516001600160a01b0390981688526020880196909652868601949094526060860192909252608085015260a084015260c083015260e0820186905251908190036101000190a150505050505050565b60009283526007602090815260408085209385529281528284209184525290205490565b600454600160a01b900460ff1690565b600090565b6040805162461bcd60e51b815260206004820152600f60248201526e1393d517d253541311535153951151608a1b604482015290519081900360640190fd5b6000611848836134f1565b905061185382612de7565b1561189b576040805162461bcd60e51b81526020600482015260136024820152724d494e5441424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6118a482612e2b565b6118ef576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b600083815260086020908152604080832085845290915281208054919055829061191a83838361354d565b7fb7477a7b93b2addc5272bbd7ad0986ef1c0d0bd265f26c3dc4bbe42727c2ac0c85856119478785613244565b60408051938452602084019290925282820152606082018490526001600160a01b0386166080830152519081900360a00190a15050505050565b600061198c82612db8565b92915050565b61199a6117e9565b156119de576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b6119e7846137e4565b611a2c576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b611a3985858585856115cc565b5050505050565b60009283526006602090815260408085209385529281528284209184525290205490565b6024546000908210611ab5576040805162461bcd60e51b815260206004820152601560248201527408286a8929e9cbe929c888ab0bea89e9ebe90928e9605b1b604482015290519081900360640190fd5b60248281548110611ac257fe5b90600052602060002001549050919050565b60245490565b611ae3826133d6565b611b29576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6000611b358383611e9b565b90506000611b42856134f1565b600086815260086020908152604080832086845290915281208054919055909150611b6f828686846137f7565b611b788561341a565b15611bd4576040805187815260208101879052808201869052606081018590526001600160a01b038416608082015290517fa5cfa8e2199ec5b8ca319288bcab72734207d30569756ee594a74b4df7abbf419181900360a00190a15b7fc6ba68235f3229e53f3a95cda25543ad54c0f6df2493a06c05fb930bea7966fe86868686611c038a87613244565b604080519586526020860194909452848401929092526060840152608083015260a082018490526001600160a01b03851660c0830152519081900360e00190a1505050505050565b6115a36138bd565b6202a30081565b611c626117e9565b611ca6576040805162461bcd60e51b815260206004820152601060248201526f29aa20aa22afa727aa2fa32927ad22a760811b604482015290519081900360640190fd5b611caf33612db8565b611cf2576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b600554421015611d44576040805162461bcd60e51b8152602060048201526018602482015277155391949151569157d393d517d0531313d5d15117d6515560421b604482015290519081900360640190fd5b6004805460ff60a01b19169055600d805460019081019091556025805482019055600f805490910190556040517f07017fe9180629cfffba412f65a9affcf9a121de02294179f5c058f881dcc9f890600090a1565b82611da3816134f1565b6001600160a01b0316336001600160a01b031614611df6576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b60008481526007602090815260408083208684528252808320858452825291829020429055815186815290810184905280820185905290517f0bc1df35228095c37da66a6ffcc755ea79dfc437345685f618e05fafad6b445e9181900360600190a150505050565b611e6781613954565b50565b6301e1338081565b68010000000000000004546001600160a01b031681565b611e9584848484611421565b50505050565b6000611ea6836133d6565b611ee15760405162461bcd60e51b8152600401808060200182810382526021815260200180614dff6021913960400191505060405180910390fd5b6060611eec8461341a565b611f1b576040518060400160405280600d81526020016c2727a72fa6a4a72a20a126229d60991b815250611f39565b6040518060400160405280600481526020016327232a1d60e11b8152505b90506001600160fa1b038185856040516020018084805190602001908083835b60208310611f785780518252601f199092019160209182019101611f59565b51815160209384036101000a600019018019909216911617905292019485525083810192909252506040805180840383018152928101905281519101209190911695945050505050565b611e6781613a51565b6001600160a01b031660009081526011602052604090205460ff1690565b680100000000000000035481565b61200033612db8565b612043576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6001600160a01b038116600081815260116020908152604091829020805460ff19169055815192835290517ffa49aecb996ea8d99950bb051552dfcc0b5460a0bb209867a1ed8067c32c21779281900390910190a150565b6000838152600660209081526040808320858452825280832084845290915281205483906120ca908290613244565b95945050505050565b6120db6117e9565b1561211f576040805162461bcd60e51b815260206004820152600f60248201526e29aa20aa22afa4a9afa32927ad22a760891b604482015290519081900360640190fd5b6121288361341a565b61216c576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b611e958484838560016115cc565b82612184816134f1565b6001600160a01b0316336001600160a01b0316146121d7576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b6121e083612e2b565b61222b576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f46554e4749424c455f41535345545f5459504560481b604482015290519081900360640190fd5b826000612239868386613b9e565b905061224633868361354d565b7fe3e46ecf1138180bf93cba62a0b7e661d976a8ab3d40243f7b082667d8f500af8685876122748986613244565b60408051948552602085019390935283830191909152606083015260808201849052519081900360a00190a1505050505050565b600080828051906020012060001c9050600160fa1b6001600160f01b036040518060400160405280600981526020016826a4a72a20a126229d60b91b81525086846040516020018084805190602001908083835b6020831061231b5780518252601f1990920191602091820191016122fc565b51815160209384036101000a60001901801990921691161790529201948552508381019290925250604080518084038301815292810190528151910120919091169190911795945050505050565b6224ea0081565b60006001600160a01b0389163014612389576000612392565b63bc197c8160e01b5b9998505050505050505050565b836123a9816134f1565b6001600160a01b0316336001600160a01b0316146123fc576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b612405846133d6565b61244b576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b60006124578585611e9b565b90506000612466878386613b9e565b9050801561247a5761247a338787846137f7565b6124838661341a565b156124d7576040805188815260208101869052808201889052606081018790526080810184905290517ff00c0c1a754f6df7545d96a7e12aad552728b94ca6aa94f81e297bdbcf1dab9c9181900360a00190a15b7fcc00f2179d127845242252f3c3b6b238c5ed33c2e933179f09653cfb1cdee7ca87858888866125078c88613244565b604080519687526020870195909552858501939093526060850191909152608084015260a083015260c08201849052519081900360e00190a150505050505050565b604051806060016040528060268152602001614e206026913981565b61112883838360015b61257733611fcb565b6125bc576040805162461bcd60e51b815260206004820152601160248201527027a7262cafaa27a5a2a729afa0a226a4a760791b604482015290519081900360640190fd5b6125c584611138565b15612612576040805162461bcd60e51b81526020600482015260186024820152771054d4d15517d053149150511657d49151d254d51154915160421b604482015290519081900360640190fd5b600167080000000000001160c01b018410612669576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b600081116126b0576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5155414e54554d60881b604482015290519081900360640190fd5b600160801b81106126fa576040805162461bcd60e51b815260206004820152600f60248201526e494e56414c49445f5155414e54554d60881b604482015290519081900360640190fd5b60006001600160fa1b0384848460405160200180848480828437919091019283525050604080518083038152602092830190915280519101209290921692505050848114612784576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b6127c384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cab92505050565b61280284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613e2792505050565b156128525781600114612852576040805162461bcd60e51b8152602060048201526013602482015272494e56414c49445f4e46545f5155414e54554d60681b604482015290519081900360640190fd5b6000858152601560209081526040808320805460ff1916600117905560149091529020612880908585614d2b565b508160166000878152602001908152602001600020819055507f7a0efbc885500f3b4a895231945be4520e4c0ba5ef7274a225a0272c81ccbcb78585858560405180858152602001806020018381526020018281038252858582818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b600061291b856134f1565b60008581526015602052604090205490915060ff16612976576040805162461bcd60e51b8152602060048201526012602482015271494e56414c49445f41535345545f5459504560701b604482015290519081900360640190fd5b61297f84612de7565b6129ca576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f4d494e5441424c455f41535345545f5459504560481b604482015290519081900360640190fd5b6000612a0c8585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122a892505050565b6000878152600860209081526040808320848452909152902054909150612a7a576040805162461bcd60e51b815260206004820152601d60248201527f4e4f5f50454e44494e475f5749544844524157414c5f42414c414e4345000000604482015290519081900360640190fd5b600086815260086020908152604080832084845290915281208054919055612aa58682858888613e6b565b7f7e6e15df814c1a309a57686de672b2bedd128eacde35c5370c36d6840d4e9a928787612ad28985613244565b604080519384526020840192909252828201526060820184905260808201859052519081900360a00190a150505050505050565b60008181526015602052604081205460ff16612b245750600161114b565b5060009081526016602052604090205490565b600a81565b604081565b60008281526008602090815260408083208484529091528120548290612b68908290613244565b949350505050565b6060604051806060016040528060218152602001614e4660219139905090565b60006001600160a01b0387163014612ba9576000612bb2565b63f23a6e6160e01b5b979650505050505050565b60008181526015602052604090205460609060ff16612c1f576040805162461bcd60e51b81526020600482015260196024820152781054d4d15517d516541157d393d517d49151d254d511549151603a1b604482015290519081900360640190fd5b60008281526014602090815260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015612cb25780601f10612c8757610100808354040283529160200191612cb2565b820191906000526020600020905b815481529060010190602001808311612c9557829003601f168201915b50505050509050919050565b83612cc8816134f1565b6001600160a01b0316336001600160a01b031614612d1b576040805162461bcd60e51b815260206004820152601a6024820152600080516020614ddf833981519152604482015290519081900360640190fd5b611a398585848661239f565b60006341917ff960e11b612d3a8361400d565b6001600160e01b0319161492915050565b600080612d5784612b06565b9050808381612d6257fe5b0615612da6576040805162461bcd60e51b815260206004820152600e60248201526d1253959053125117d05353d5539560921b604482015290519081900360640190fd5b808381612daf57fe5b04949350505050565b600080612dc3614020565b6001600160a01b039390931660009081526020939093525050604090205460ff1690565b600080612df38361400d565b90506001600160e01b031981166368646e2d60e01b148061141a57506001600160e01b03198116635c5c333960e11b14915050919050565b600080612e378361400d565b90506001600160e01b031981166341917ff960e11b1480612e6857506001600160e01b03198116630f47261b60e41b145b8061141a57506001600160e01b031981166368646e2d60e01b14915050919050565b60008481526006602090815260408083208684528252808320858452909152812054820182811015612ef6576040805162461bcd60e51b815260206004820152601060248201526f4445504f5349545f4f564552464c4f5760801b604482015290519081900360640190fd5b600086815260066020908152604080832088845282528083208784529091529020819055612f238661409d565b8015612f4f57506000868152600760209081526040808320888452825280832087845290915290205415155b156120ca576000868152600760209081526040808320888452825280832087845290915281205595945050505050565b6000612f8b8383613244565b9050612f96836140c3565b156131985781612fa65750613240565b6000612fb1846140d6565b905060008190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561300757600080fd5b505afa15801561301b573d6000803e3d6000fd5b505050506040513d602081101561303157600080fd5b50516040805133602482015230604482015260648082018890528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905290915061308d6001600160a01b038516826140e9565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505190508281101561314a576040805162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015290519081900360640190fd5b858301811461318e576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050611128565b6131a183612d27565b156131fa578034146131f5576040805162461bcd60e51b8152602060048201526018602482015277125390d3d4949150d517d1115413d4d25517d05353d5539560421b604482015290519081900360640190fd5b611128565b6040805162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f544f4b454e5f5459504560501b604482015290519081900360640190fd5b5050565b60008061325084612b06565b905080830291508281838161326157fe5b04146132ae576040805162461bcd60e51b815260206004820152601760248201527644455155414e54495a4154494f4e5f4f564552464c4f5760481b604482015290519081900360640190fd5b5092915050565b60006132bf614020565b60018101549091506001600160a01b0316331461331d576040805162461bcd60e51b815260206004820152601760248201527627a7262cafa1a0a72224a220aa22afa3a7ab22a92727a960491b604482015290519081900360640190fd5b6001810154613334906001600160a01b03166142d5565b6001810180546001600160a01b03191690556040805133815290517fcfb473e6c03f9a29ddaf990e736fa3de5188a0bd85d684f5b6e164ebfbfff5d29181900360200190a150565b600061141a6040518060400160405280600f81526020016e1195531317d5d2551211149055d053608a1b81525084846040516020018083815260200182815260200192505050604051602081830303815290604052614355565b6000806133e28361400d565b90506001600160e01b0319811663012b8bc960e11b148061141a57506001600160e01b03198116633348691d60e01b14915050919050565b600063012b8bc960e11b612d3a8361400d565b613436836133d6565b61347d576040805162461bcd60e51b815260206004820152601360248201527246554e4749424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6134868361341a565b156134e057806001146134d6576040805162461bcd60e51b8152602060048201526013602482015272494c4c4547414c5f4e46545f42414c414e434560681b604482015290519081900360640190fd5b6131f58383614417565b8015611128576111288383836144ca565b60006134fc826113dc565b90506001600160a01b03811661114b576040805162461bcd60e51b81526020600482015260116024820152701554d15497d553949151d254d511549151607a1b604482015290519081900360640190fd5b6001600160a01b03831661359c576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b60006135a88383613244565b90506135b3836140c3565b156137b357816135c35750611128565b60006135ce846140d6565b905060008190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561362457600080fd5b505afa158015613638573d6000803e3d6000fd5b505050506040513d602081101561364e57600080fd5b5051604080516001600160a01b03808b16602483015260448083018990528351808403909101815260649092019092526020810180516001600160e01b031663a9059cbb60e01b1790529192506136a7908516826140e9565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156136f657600080fd5b505afa15801561370a573d6000803e3d6000fd5b505050506040513d602081101561372057600080fd5b5051905082811115613765576040805162461bcd60e51b8152602060048201526009602482015268554e444552464c4f5760b81b604482015290519081900360640190fd5b85830381146137a9576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050611e95565b6137bc83612d27565b156131fa57816137cc5750611128565b6137df6001600160a01b038516826147e0565b611e95565b6000633348691d60e01b612d3a8361400d565b613800836133d6565b613847576040805162461bcd60e51b815260206004820152601360248201527246554e4749424c455f41535345545f5459504560681b604482015290519081900360640190fd5b6138508361341a565b156138ab57806001146138a0576040805162461bcd60e51b8152602060048201526013602482015272494c4c4547414c5f4e46545f42414c414e434560681b604482015290519081900360640190fd5b6137df84848461487c565b8015611e9557611e9584848484614981565b6138c633612db8565b613909576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b6000613913614020565b6001810180546001600160a01b03191690556040519091507f7a8dc7dd7fffb43c4807438fa62729225156941e641fd877938f4edade3429f590600090a150565b61395d33612db8565b6139a0576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b60006139aa614020565b90506139b582612db8565b156139fa576040805162461bcd60e51b815260206004820152601060248201526f20a62922a0a22cafa3a7ab22a92727a960811b604482015290519081900360640190fd5b6001810180546001600160a01b0384166001600160a01b0319909116811790915560408051918252517f6166272c8d3f5f579082f2827532732f97195007983bb5b83ac12c56700b01a69181900360200190a15050565b613a5a33612db8565b613a9d576040805162461bcd60e51b815260206004820152600f60248201526e4f4e4c595f474f5645524e414e434560881b604482015290519081900360640190fd5b336001600160a01b0382161415613af2576040805162461bcd60e51b8152602060048201526014602482015273474f5645524e4f525f53454c465f52454d4f564560601b604482015290519081900360640190fd5b6000613afc614020565b9050613b0782612db8565b613b47576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa3a7ab22a92727a960a11b604482015290519081900360640190fd5b6001600160a01b03821660008181526020838152604091829020805460ff19169055815192835290517fd75f94825e770b8b512be8e74759e252ad00e102e38f50cce2f7c6f868a295999281900390910190a15050565b6000838152600760209081526040808320858452825280832084845290915281205480613c09576040805162461bcd60e51b815260206004820152601460248201527311115413d4d25517d393d517d0d05390d153115160621b604482015290519081900360640190fd5b6202a30081810190811015613c1a57fe5b80421015613c60576040805162461bcd60e51b815260206004820152600e60248201526d11115413d4d25517d313d0d2d15160921b604482015290519081900360640190fd5b50505060008381526006602090815260408083208584528252808320848452825280832080549084905595835260078252808320948352938152838220928252919091529081205590565b6000613cb682614c6e565b9050613cc181614c7f565b613d0b576040805162461bcd60e51b8152602060048201526016602482015275554e535550504f525445445f544f4b454e5f5459504560501b604482015290519081900360640190fd5b6001600160e01b031981166341917ff960e11b1415613d76578151600414613d71576040805162461bcd60e51b8152602060048201526014602482015273494e56414c49445f41535345545f535452494e4760601b604482015290519081900360640190fd5b613240565b8151602414613dc3576040805162461bcd60e51b8152602060048201526014602482015273494e56414c49445f41535345545f535452494e4760601b604482015290519081900360640190fd5b6000613dce83614d1e565b9050613de2816001600160a01b0316614d25565b611128576040805162461bcd60e51b81526020600482015260116024820152704241445f544f4b454e5f4144445245535360781b604482015290519081900360640190fd5b600080613e3383614c6e565b90506001600160e01b0319811663012b8bc960e11b148061141a57506001600160e01b03198116635c5c333960e11b14915050919050565b6001600160a01b038316613eba576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b613ec385612de7565b613f0e576040805162461bcd60e51b81526020600482015260176024820152764e4f4e5f4d494e5441424c455f41535345545f5459504560481b604482015290519081900360640190fd5b60008411613f59576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d352539517d05353d55395606a1b604482015290519081900360640190fd5b6000613f658686613244565b90506000613f72876140d6565b90506140048583868660405160240180856001600160a01b0316815260200184815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516319ee6e3f60e01b6001600160e01b039091161790526001600160a01b038916965094506140e99350505050565b50505050505050565b600061198c61401b83612bbd565b614c6e565b600080604051806060016040528060268152602001614e20602691396040518082805190602001908083835b6020831061406b5780518252601f19909201916020918201910161404c565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092209392505050565b60006140a8826113dc565b6001600160a01b0316336001600160a01b0316149050919050565b6000630f47261b60e41b612d3a8361400d565b600061198c6140e483612bbd565b614d1e565b6140f282614d25565b614137576040805162461bcd60e51b81526020600482015260116024820152704241445f544f4b454e5f4144445245535360781b604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106141755780518252601f199092019160209182019101614156565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146141d7576040519150601f19603f3d011682016040523d82523d6000602084013e6141dc565b606091505b509150915081819061426c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614231578181015183820152602001614219565b50505050905090810190601f16801561425e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50805115611e955780806020019051602081101561428957600080fd5b5051611e95576040805162461bcd60e51b81526020600482015260166024820152751513d2d15397d3d4115490551253d397d1905253115160521b604482015290519081900360640190fd5b6142de81612db8565b15614323576040805162461bcd60e51b815260206004820152601060248201526f20a62922a0a22cafa3a7ab22a92727a960811b604482015290519081900360640190fd5b600061432d614020565b6001600160a01b0390921660009081526020929092525060409020805460ff19166001179055565b600082826040516020018083805190602001908083835b6020831061438b5780518252601f19909201916020918201910161436c565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106143d35780518252601f1990920191602091820191016143b4565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905092915050565b6144208261341a565b614464576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b600061446f836140d6565b6040805133602482015230604482015260648082018690528251808303909101815260849091019091526020810180516001600160e01b0316632142170760e11b179052909150611128906001600160a01b038316906140e9565b6144d3836137e4565b614518576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b8061452257611128565b600061452e8483613244565b9050600061453b856140d6565b60408051627eeac760e11b815230600482015260248101879052905191925082916000916001600160a01b0384169162fdd58e91604480820192602092909190829003018186803b15801561458f57600080fd5b505afa1580156145a3573d6000803e3d6000fd5b505050506040513d60208110156145b957600080fd5b810190808051906020019092919050505090506146ce63f242432a60e01b333089886040518060200160405280600081525060405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561465557818101518382015260200161463d565b50505050905090810190601f1680156146825780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909a169990991790985250506001600160a01b038a16959450506140e992505050565b6000826001600160a01b031662fdd58e30896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b15801561472457600080fd5b505afa158015614738573d6000803e3d6000fd5b505050506040513d602081101561474e57600080fd5b5051905081811015614792576040805162461bcd60e51b81526020600482015260086024820152674f564552464c4f5760c01b604482015290519081900360640190fd5b84820181146147d6576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b5050505050505050565b6040516000906001600160a01b0384169083908381818185875af1925050503d806000811461482b576040519150601f19603f3d011682016040523d82523d6000602084013e614830565b606091505b5050905080611128576040805162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b604482015290519081900360640190fd5b6001600160a01b0383166148cb576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b6148d48261341a565b614918576040805162461bcd60e51b815260206004820152601060248201526f2727aa2fa2a9219b9918afaa27a5a2a760811b604482015290519081900360640190fd5b6000614923836140d6565b604080513060248201526001600160a01b03808816604483015260648083018790528351808403909101815260849092019092526020810180516001600160e01b0316632142170760e11b179052919250611e9591908316906140e9565b6001600160a01b0384166149d0576040805162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b604482015290519081900360640190fd5b6149d9836137e4565b614a1e576040805162461bcd60e51b81526020600482015260116024820152702727aa2fa2a92198989a9aafaa27a5a2a760791b604482015290519081900360640190fd5b80614a2857611e95565b6000614a348483613244565b90506000614a41856140d6565b60408051627eeac760e11b815230600482015260248101879052905191925082916000916001600160a01b0384169162fdd58e91604480820192602092909190829003018186803b158015614a9557600080fd5b505afa158015614aa9573d6000803e3d6000fd5b505050506040513d6020811015614abf57600080fd5b81019080805190602001909291905050509050614b5a63f242432a60e01b308a89886040518060200160405280600081525060405160240180866001600160a01b03168152602001856001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360008381101561465557818101518382015260200161463d565b6000826001600160a01b031662fdd58e30896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b158015614bb057600080fd5b505afa158015614bc4573d6000803e3d6000fd5b505050506040513d6020811015614bda57600080fd5b5051905081811115614c1f576040805162461bcd60e51b8152602060048201526009602482015268554e444552464c4f5760b81b604482015290519081900360640190fd5b8482038114614c63576040805162461bcd60e51b815260206004820152601c6024820152600080516020614dbf833981519152604482015290519081900360640190fd5b505050505050505050565b602001516001600160e01b03191690565b60006001600160e01b031982166341917ff960e11b1480614cb057506001600160e01b03198216630f47261b60e41b145b80614ccb57506001600160e01b0319821663012b8bc960e11b145b80614ce657506001600160e01b031982166368646e2d60e01b145b80614d0157506001600160e01b03198216635c5c333960e11b145b8061198c5750506001600160e01b031916633348691d60e01b1490565b6024015190565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614d6c5782800160ff19823516178555614d99565b82800160010185558215614d99579182015b82811115614d99578235825591602001919060010190614d7e565b50614da5929150614da9565b5090565b5b80821115614da55760008155600101614daa56fe494e434f52524543545f414d4f554e545f5452414e53464552524544000000004d49534d41544348494e475f535441524b5f4554485f4b45595300000000000041535345545f545950455f444f45535f4e4f545f54414b455f544f4b454e5f4944537461726b45782e4d61696e2e323031392e476f7665726e6f7273496e666f726d6174696f6e537461726b576172655f546f6b656e73416e6452616d70696e675f323032325f32a2646970667358221220dceb72817044db7cba290582a0d8c7b21878ca86d2edb87a60b1165772a90f3664736f6c634300060c0033

Deployed Bytecode Sourcemap

1068:1336:35:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1246:52:15;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;10188:299:3;;;;;;;;;;;;;;;;-1:-1:-1;10188:299:3;;;;;;;;;;;;:::i;:::-;;7012:258:36;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7012:258:36;;;;;;;;;;;;:::i;3595:127:33:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3595:127:33;;:::i;:::-;;;;;;;;;;;;;;;;;;3262:158;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3262:158:33;-1:-1:-1;;;;;3262:158:33;;:::i;1607:663:35:-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1575:473:5;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1575:473:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1575:473:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1575:473:5;;;;;;;;;;-1:-1:-1;1575:473:5;;-1:-1:-1;1575:473:5;-1:-1:-1;1575:473:5;:::i;:::-;;;;-1:-1:-1;;;;;;1575:473:5;;;;;;;;;;;;;;1444:314:14;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1444:314:14;;:::i;:::-;;;;-1:-1:-1;;;;;1444:314:14;;;;;;;;;;;;;;8975:1207:3;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8975:1207:3;;;;;;;;;;;;;;;;;:::i;3095:77:25:-;;;;;;;;;;;;;:::i;1454:370:28:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1454:370:28;;;;;;;:::i;6675:1508:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6675:1508:3;;;;;;;;;;;;;;;;;;;;;;:::i;8189:229::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8189:229:3;;;;;;;;;;;;:::i;935:91:6:-;;;;;;;;;;;;;:::i;1508:93:35:-;;;;;;;;;;;;;:::i;1381:121::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1381:121:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1381:121:35;;;;;;;;;;-1:-1:-1;1381:121:35;;-1:-1:-1;1381:121:35;-1:-1:-1;1381:121:35;:::i;4820:785:36:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4820:785:36;;;;;;;:::i;2723:124:25:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2723:124:25;-1:-1:-1;;;;;2723:124:25;;:::i;5450:336:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5450:336:3;;;;;;;;;;;;;;;;;;;;;;:::i;4938:217::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4938:217:3;;;;;;;;;;;;:::i;2133:213:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2133:213:1;;:::i;2024:103::-;;;;;;;;;;;;;:::i;5793:1033:36:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5793:1033:36;;;;;;;;;;;;:::i;3178:77:25:-;;;;;;;;;;;;;:::i;1059:53:15:-;;;;;;;;;;;;;:::i;1845:404:6:-;;;;;;;;;;;;;:::i;10493:434:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10493:434:3;;;;;;;;;;;;:::i;2853:113:25:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2853:113:25;-1:-1:-1;;;;;2853:113:25;;:::i;1473:49:15:-;;;;;;;;;;;;;:::i;1864:35:29:-;;;;;;;;;;;;;:::i;8424:226:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8424:226:3;;;;;;;;;;;;;;;;;:::i;6701:433:31:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6701:433:31;;;;;;;:::i;2972:117:25:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2972:117:25;-1:-1:-1;;;;;2972:117:25;;:::i;3138:118:33:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3138:118:33;-1:-1:-1;;;;;3138:118:33;;:::i;1696:41:29:-;;;;;;;;;;;;;:::i;3426:163:33:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3426:163:33;-1:-1:-1;;;;;3426:163:33;;:::i;4645:287:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4645:287:3;;;;;;;;;;;;:::i;5161:283::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5161:283:3;;;;;;;;;;;;;;;;;:::i;11817:838::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11817:838:3;;;;;;;;;;;;:::i;7140:401:31:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7140:401:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7140:401:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7140:401:31;;-1:-1:-1;7140:401:31;;-1:-1:-1;;;;;7140:401:31:i;1724:80:15:-;;;;;;;;;;;;;:::i;3151:331:4:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3151:331:4;;;;;;;;;;-1:-1:-1;3151:331:4;;-1:-1:-1;3151:331:4;-1:-1:-1;3151:331:4;:::i;12661:1174:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12661:1174:3;;;;;;;;;;;;;;;;;:::i;2376:90:25:-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5129:140:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5129:140:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5129:140:33;;;;;;;;;;-1:-1:-1;5129:140:33;;-1:-1:-1;5129:140:33;-1:-1:-1;5129:140:33;:::i;3881:1242::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3881:1242:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3881:1242:33;;;;;;;;;;;;-1:-1:-1;3881:1242:33;-1:-1:-1;3881:1242:33;;:::i;7276:936:36:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7276:936:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7276:936:36;;;;;;;;;;-1:-1:-1;7276:936:36;;-1:-1:-1;7276:936:36;-1:-1:-1;7276:936:36;:::i;1144:358:32:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1144:358:32;;:::i;2292:62:15:-;;;;;;;;;;;;;:::i;1584:56::-;;;;;;;;;;;;;:::i;4365:265:36:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4365:265:36;;;;;;;:::i;2276:126:35:-;;;;;;;;;;;;;:::i;1964:297:4:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1964:297:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1964:297:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1964:297:4;;;;;;;;;;-1:-1:-1;1964:297:4;;-1:-1:-1;1964:297:4;-1:-1:-1;1964:297:4;:::i;2485:326:31:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2485:326:31;;:::i;13841:351:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;13841:351:3;;;;;;;;;;;;;;;;;:::i;1246:52:15:-;1292:6;1246:52;:::o;10188:299:3:-;10357:18;10365:9;10357:7;:18::i;:::-;10349:49;;;;;-1:-1:-1;;;10349:49:3;;;;;;;;;;;;-1:-1:-1;;;10349:49:3;;;;;;;;;;;;;;;10408:72;10416:8;10426:9;10437:7;10446:33;10458:9;10469;10446:11;:33::i;:::-;10408:7;:72::i;:::-;10188:299;;;:::o;7012:258:36:-;7214:49;7234:8;7244:9;7255:7;7214:19;:49::i;3595:127:33:-;3662:4;3685:30;;;:19;:30;;;;;;;;3595:127;;;;:::o;3262:158::-;1031:23:19;1043:10;1031:11;:23::i;:::-;1023:51;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;;;-1:-1:-1;;;;;3342:21:33;::::1;;::::0;;;:11:::1;:21;::::0;;;;;;;;:28;;-1:-1:-1;;3342:28:33::1;3366:4;3342:28;::::0;;3385;;;;;;;::::1;::::0;;;;;;;;::::1;3262:158:::0;:::o;1607:663:35:-;1773:18;;;1721:1;1773:18;;;;;;;;;1669:25;;1721:1;1706:12;;1721:1;1773:18;;;;;;;;-1:-1:-1;;1801:19:35;;1761:30;;-1:-1:-1;;1811:8:35;;;;-1:-1:-1;;;1823:31:35;1761:30;;1811:8;1801:19;;;;;;-1:-1:-1;;;;;;1801:53:35;;;:19;;;;;;;;;;;:53;1864:19;;1874:8;;;;-1:-1:-1;;;1886:43:35;1864:9;;1874:8;1864:19;;;;;;-1:-1:-1;;;;;;1864:65:35;;;:19;;;;;;;;;;;:65;1939:19;;1949:8;;;;-1:-1:-1;;;1961:32:35;1939:9;;1949:8;1939:19;;;;;;-1:-1:-1;;;;;;1939:54:35;;;:19;;;;;;;;;;;:54;2003:19;;2013:8;;;;-1:-1:-1;;;2025:29:35;2003:9;;2013:8;2003:19;;;;;;-1:-1:-1;;;;;;2003:51:35;;;:19;;;;;;;;;;;:51;2064:19;;2074:8;;;;-1:-1:-1;;;2086:36:35;2064:9;;2074:8;2064:19;;;;;;-1:-1:-1;;;;;;2064:58:35;;;:19;;;;;;;;;;;:58;2132:19;;2142:8;;;;-1:-1:-1;;;2154:40:35;2132:9;;2142:8;2132:19;;;;;;-1:-1:-1;;;;;;2132:62:35;;;:19;;;;;;;;;;;:62;2212:14;;;2204:59;;;;;-1:-1:-1;;;2204:59:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1607:663;;;:::o;1575:473:5:-;1944:6;-1:-1:-1;;;;;1970:25:5;;1990:4;1970:25;:70;;2038:1;1970:70;;;-1:-1:-1;;;1970:70:5;1962:79;1575:473;-1:-1:-1;;;;;;1575:473:5:o;1444:314:14:-;1511:7;1554:17;;;:7;:17;;;;;;-1:-1:-1;;;;;1554:17:14;1586:29;;1582:80;;1638:13;-1:-1:-1;1631:20:14;;1582:80;-1:-1:-1;;;;;1692:8:14;:23;1679:8;:37;:72;;1747:3;1679:72;;;1727:8;1679:72;1672:79;1444:314;-1:-1:-1;;;1444:314:14:o;8975:1207:3:-;964:10:18;:8;:10::i;:::-;963:11;955:39;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;;;;9500:30:3::1;9520:9;9500:19;:30::i;:::-;9499:31;9491:63;;;::::0;;-1:-1:-1;;;9491:63:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;9491:63:3;;;;;;;;;;;;;::::1;;9572:30;9592:9;9572:19;:30::i;:::-;9564:66;;;::::0;;-1:-1:-1;;;9564:66:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;9564:66:3;;;;;;;;;;;;;::::1;;9659:9:::0;9775:63:::1;9794:8:::0;9659:9;9813:7;9822:15;9775:18:::1;:63::i;:::-;;9905:38;9916:9;9927:15;9905:10;:38::i;:::-;9981:194;10005:10;10029:8;10051:7;10072:9;10095:41;10109:9;10120:15;10095:13;:41::i;:::-;9981:194;::::0;;-1:-1:-1;;;;;9981:194:3;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::1;1004:1:18;8975:1207:3::0;;;;:::o;3095:77:25:-;3146:19;:17;:19::i;:::-;3095:77::o;1454:370:28:-;1585:7;1754:20;:63;1775:41;1798:8;1808:7;1775:22;:41::i;:::-;1754:63;;;;;;;;;;;;1747:70;;1454:370;;;;:::o;6675:1508:3:-;964:10:18;:8;:10::i;:::-;963:11;955:39;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;;;;7133:33:3::1;7156:9;7133:22;:33::i;:::-;7125:64;;;::::0;;-1:-1:-1;;;7125:64:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;7125:64:3;;;;;;;;;;;;;::::1;;7200:15;7218:47;7246:9;7257:7;7218:27;:47::i;:::-;7200:65;;7372:23;7398:63;7417:8;7427:7;7436;7445:15;7398:18;:63::i;:::-;7372:89;;7577:19;7586:9;7577:8;:19::i;:::-;7573:196;;;7639:1;7620:15;:20;;7612:54;;;::::0;;-1:-1:-1;;;7612:54:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;7612:54:3;;;;;;;;;;;;;::::1;;7685:73;::::0;;7699:10:::1;7685:73:::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::1;::::0;;;;;;;::::1;7573:196;7834:58;7856:9;7867:7;7876:15;7834:21;:58::i;:::-;7929:247;7964:10;7988:8;8010:7;8031:9;8054:7;8075;8096:41;8110:9;8121:15;8096:13;:41::i;:::-;7929:247;::::0;;-1:-1:-1;;;;;7929:247:3;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::1;1004:1:18;;6675:1508:3::0;;;;;:::o;8189:229::-;8326:15;8363:30;;;:20;:30;;;;;;;;:39;;;;;;;;;:48;;;;;;;;8189:229::o;935:91:6:-;1008:11;;-1:-1:-1;;;1008:11:6;;;;;935:91::o;1508:93:35:-;1567:7;1508:93;:::o;1381:121::-;1470:25;;;-1:-1:-1;;;1470:25:35;;;;;;;;;;;;-1:-1:-1;;;1470:25:35;;;;;;;;;;;;;;4820:785:36;4894:25;4930;4946:8;4930:15;:25::i;:::-;4894:62;;4975:30;4995:9;4975:19;:30::i;:::-;4974:31;4966:63;;;;;-1:-1:-1;;;4966:63:36;;;;;;;;;;;;-1:-1:-1;;;4966:63:36;;;;;;;;;;;;;;;5047:30;5067:9;5047:19;:30::i;:::-;5039:66;;;;;-1:-1:-1;;;5039:66:36;;;;;;;;;;;;-1:-1:-1;;;5039:66:36;;;;;;;;;;;;;;;5115:15;5223:28;;;:18;:28;;;;;;;;:37;;;;;;;;;;5270:41;;;5223:37;;5349:50;5361:9;5223:37;;5349:11;:50::i;:::-;5414:184;5450:8;5472:9;5495:41;5509:9;5520:15;5495:13;:41::i;:::-;5414:184;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5414:184:36;;;;;;;;;;;;;;;4820:785;;;;;:::o;2723:124:25:-;2792:4;2815:25;2827:12;2815:11;:25::i;:::-;2808:32;2723:124;-1:-1:-1;;2723:124:25:o;5450:336:3:-;964:10:18;:8;:10::i;:::-;963:11;955:39;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;;;;5653:20:3::1;5663:9;5653;:20::i;:::-;5645:50;;;::::0;;-1:-1:-1;;;5645:50:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;5645:50:3;;;;;;;;;;;;;::::1;;5705:74;5724:8;5734:9;5745:7;5754;5763:15;5705:18;:74::i;:::-;5450:336:::0;;;;;:::o;4938:217::-;5079:7;5105:25;;;:15;:25;;;;;;;;:34;;;;;;;;;:43;;;;;;;;4938:217::o;2133:213:1:-;2248:14;:21;2207:7;;2234:35;;2226:69;;;;;-1:-1:-1;;;2226:69:1;;;;;;;;;;;;-1:-1:-1;;;2226:69:1;;;;;;;;;;;;;;;2312:14;2327:11;2312:27;;;;;;;;;;;;;;;;2305:34;;2133:213;;;:::o;2024:103::-;2099:14;:21;2024:103;:::o;5793:1033:36:-;6009:33;6032:9;6009:22;:33::i;:::-;6001:64;;;;;-1:-1:-1;;;6001:64:36;;;;;;;;;;;;-1:-1:-1;;;6001:64:36;;;;;;;;;;;;;;;6075:15;6093:47;6121:9;6132:7;6093:27;:47::i;:::-;6075:65;;6150:17;6170:25;6186:8;6170:15;:25::i;:::-;6206:23;6232:28;;;:18;:28;;;;;;;;:37;;;;;;;;;;6279:41;;;6150:45;;-1:-1:-1;6358:70:36;6150:45;6392:9;6403:7;6232:37;6358:22;:70::i;:::-;6442:19;6451:9;6442:8;:19::i;:::-;6438:130;;;6482:75;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6482:75:36;;;;;;;;;;;;;;;;;6438:130;6582:237;6629:8;6651:9;6674:7;6695;6716:41;6730:9;6741:15;6716:13;:41::i;:::-;6582:237;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6582:237:36;;;;;;;;;;;;;;;5793:1033;;;;;;:::o;3178:77:25:-;3229:19;:17;:19::i;1059:53:15:-;1106:6;1059:53;:::o;1845:404:6:-;1213:10:18;:8;:10::i;:::-;1205:39;;;;;-1:-1:-1;;;1205:39:18;;;;;;;;;;;;-1:-1:-1;;;1205:39:18;;;;;;;;;;;;;;;1031:23:19::1;1043:10;1031:11;:23::i;:::-;1023:51;;;::::0;;-1:-1:-1;;;1023:51:19;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;::::1;;1937:12:6::2;;1918:15;:31;;1910:68;;;::::0;;-1:-1:-1;;;1910:68:6;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;1910:68:6;;;;;;;;;;;;;::::2;;2014:11;:19:::0;;-1:-1:-1;;;;2014:19:6::2;::::0;;2115:17:::2;:22:::0;;2014:19;2115:22;;::::2;::::0;;;2147:15:::2;:20:::0;;;::::2;::::0;;2177:9:::2;:14:::0;;;;::::2;::::0;;2229:13:::2;::::0;::::2;::::0;2028:5:::2;::::0;2229:13:::2;1845:404::o:0;10493:434:3:-;10636:8;1224:25:20;1240:8;1224:15;:25::i;:::-;-1:-1:-1;;;;;1210:39:20;:10;-1:-1:-1;;;;;1210:39:20;;1202:78;;;;;-1:-1:-1;;;1202:78:20;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1202:78:20;;;;;;;;;;;;;;;10772:30:3::1;::::0;;;:20:::1;:30;::::0;;;;;;;:39;;;;;;;;:48;;;;;;;;;10823:15:::1;10772:66:::0;;10876:44;;;;;;;::::1;::::0;;;;;;;;;;;::::1;::::0;;;;;;;::::1;10493:434:::0;;;;:::o;2853:113:25:-;2926:33;2947:11;2926:20;:33::i;:::-;2853:113;:::o;1473:49:15:-;1514:8;1473:49;:::o;1864:35:29:-;;;-1:-1:-1;;;;;1864:35:29;;:::o;8424:226:3:-;8589:54;8597:8;8607:9;8618:7;8627:15;8589:7;:54::i;:::-;8424:226;;;;:::o;6701:433:31:-;6836:7;6867:33;6890:9;6867:22;:33::i;:::-;6859:79;;;;-1:-1:-1;;;6859:79:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6949:20;6972:19;6981:9;6972:8;:19::i;:::-;:63;;7016:19;;;;;;;;;;;;;-1:-1:-1;;;7016:19:31;;;6972:63;;;6994:19;;;;;;;;;;;;;-1:-1:-1;;;6994:19:31;;;6972:63;6949:86;;-1:-1:-1;;;;;7087:6:31;7095:9;7106:7;7070:44;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7070:44:31;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7070:44:31;;;;;;;;;;;;;;;;-1:-1:-1;7070:44:31;;;;;;;-1:-1:-1;7070:44:31;;;;;;;;;;;;;;;7060:55;;;;;7052:75;;;;;6701:433;-1:-1:-1;;;;;6701:433:31:o;2972:117:25:-;3047:35;3063:18;3047:15;:35::i;3138:118:33:-;-1:-1:-1;;;;;3225:24:33;3202:4;3225:24;;;:11;:24;;;;;;;;;3138:118::o;1696:41:29:-;;;;:::o;3426:163:33:-;1031:23:19;1043:10;1031:11;:23::i;:::-;1023:51;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;;;-1:-1:-1;;;;;3508:21:33;::::1;3532:5;3508:21:::0;;;:11:::1;:21;::::0;;;;;;;;:29;;-1:-1:-1;;3508:29:33::1;::::0;;3552:30;;;;;;;::::1;::::0;;;;;;;;::::1;3426:163:::0;:::o;4645:287:3:-;4777:7;4881:25;;;:15;:25;;;;;;;;:34;;;;;;;;:43;;;;;;;;;4824:7;;4848:77;;4824:7;;4848:13;:77::i;:::-;4841:84;4645:287;-1:-1:-1;;;;;4645:287:3:o;5161:283::-;964:10:18;:8;:10::i;:::-;963:11;955:39;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;-1:-1:-1;;;955:39:18;;;;;;;;;;;;;;;5327:19:3::1;5336:9;5327:8;:19::i;:::-;5319:48;;;::::0;;-1:-1:-1;;;5319:48:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;5319:48:3;;;;;;;;;;;;;::::1;;5377:60;5396:8;5406:9;5417:7;5426;5435:1;5377:18;:60::i;11817:838::-:0;11963:8;1224:25:20;1240:8;1224:15;:25::i;:::-;-1:-1:-1;;;;;1210:39:20;:10;-1:-1:-1;;;;;1210:39:20;;1202:78;;;;;-1:-1:-1;;;1202:78:20;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1202:78:20;;;;;;;;;;;;;;;12077:30:3::1;12097:9;12077:19;:30::i;:::-;12069:66;;;::::0;;-1:-1:-1;;;12069:66:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;12069:66:3;;;;;;;;;;;;;::::1;;12242:9:::0;12224:15:::1;12287:49;12309:8:::0;12242:9;12328:7;12287:21:::1;:49::i;:::-;12261:75;;12374:51;12386:10;12398:9;12409:15;12374:11;:51::i;:::-;12463:185;12502:8;12524:7;12545:9;12568:41;12582:9;12593:15;12568:13;:41::i;:::-;12463:185;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::1;1290:1:20;;11817:838:3::0;;;;:::o;7140:401:31:-;7281:15;7312:16;7349:11;7339:22;;;;;;7331:31;;7312:50;;-1:-1:-1;;;;;;;;7430:15:31;;;;;;;;;;;;;-1:-1:-1;;;7430:15:31;;;7447:9;7458:8;7413:54;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7413:54:31;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7413:54:31;;;;;;;;;;;;;;;;-1:-1:-1;7413:54:31;;;;;;;-1:-1:-1;7413:54:31;;;;;;;;;;;;;;;7403:65;;;;;7395:101;;;;7394:140;;;;;;-1:-1:-1;;;;;7140:401:31:o;1724:80:15:-;1773:31;1724:80;:::o;3151:331:4:-;3372:6;-1:-1:-1;;;;;3398:25:4;;3418:4;3398:25;:76;;3472:1;3398:76;;;-1:-1:-1;;;3398:76:4;3390:85;3151:331;-1:-1:-1;;;;;;;;;3151:331:4:o;12661:1174:3:-;12841:8;1224:25:20;1240:8;1224:15;:25::i;:::-;-1:-1:-1;;;;;1210:39:20;:10;-1:-1:-1;;;;;1210:39:20;;1202:78;;;;;-1:-1:-1;;;1202:78:20;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1202:78:20;;;;;;;;;;;;;;;12955:33:3::1;12978:9;12955:22;:33::i;:::-;12947:64;;;::::0;;-1:-1:-1;;;12947:64:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;12947:64:3;;;;;;;;;;;;;::::1;;13100:15;13118:47;13146:9;13157:7;13118:27;:47::i;:::-;13100:65;;13175:23;13201:49;13223:8;13233:7;13242;13201:21;:49::i;:::-;13175:75:::0;-1:-1:-1;13265:19:3;;13261:152:::1;;13331:71;13354:10;13366:9;13377:7;13386:15;13331:22;:71::i;:::-;13449:19;13458:9;13449:8;:19::i;:::-;13445:131;;;13489:76;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;::::1;::::0;;;;;;;::::1;13445:131;13590:238;13640:8;13662:7;13683:9;13706:7;13727;13748:41;13762:9;13773:15;13748:13;:41::i;:::-;13590:238;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::1;1290:1:20;;12661:1174:3::0;;;;;:::o;2376:90:25:-;;;;;;;;;;;;;;;;;;;:::o;5129:140:33:-;5224:38;5238:9;5249;;5260:1;3881:1242;3068:24;3081:10;3068:12;:24::i;:::-;3060:54;;;;;-1:-1:-1;;;3060:54:33;;;;;;;;;;;;-1:-1:-1;;;3060:54:33;;;;;;;;;;;;;;;4108:28:::1;4126:9;4108:17;:28::i;:::-;4107:29;4099:66;;;::::0;;-1:-1:-1;;;4099:66:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4099:66:33;;;;;;;;;;;;;::::1;;-1:-1:-1::0;;;;;4183:9:33::1;:21;4175:52;;;::::0;;-1:-1:-1;;;4175:52:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4175:52:33;;;;;;;;;;;;;::::1;;4255:1;4245:7;:11;4237:39;;;::::0;;-1:-1:-1;;;4237:39:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4237:39:33;;;;;;;;;;;;;::::1;;-1:-1:-1::0;;;4294:7:33::1;:29;4286:57;;;::::0;;-1:-1:-1;;;4286:57:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4286:57:33;;;;;;;;;;;;;::::1;;4456:18;-1:-1:-1::0;;;;;4512:9:33::1;;4523:7;4495:36;;;;;;;;;;;::::0;;;::::1;::::0;;;-1:-1:-1;;4495:36:33::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;;4485:47;;;::::1;::::0;4477:67;;;::::1;::::0;-1:-1:-1;;;4562:23:33;;::::1;4554:54;;;::::0;;-1:-1:-1;;;4554:54:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4554:54:33;;;;;;;;;;;;;::::1;;4619:26;4635:9;;4619:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;4619:15:33::1;::::0;-1:-1:-1;;;4619:26:33:i:1;:::-;4699:33;4722:9;;4699:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;4699:22:33::1;::::0;-1:-1:-1;;;4699:33:33:i:1;:::-;4695:108;;;4756:7;4767:1;4756:12;4748:44;;;::::0;;-1:-1:-1;;;4748:44:33;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4748:44:33;;;;;;;;;;;;;::::1;;4864:30;::::0;;;:19:::1;:30;::::0;;;;;;;:37;;-1:-1:-1;;4864:37:33::1;4897:4;4864:37;::::0;;4911:20:::1;:31:::0;;;;;:43:::1;::::0;4945:9;;4911:43:::1;:::i;:::-;;4996:7;4964:18;:29;4983:9;4964:29;;;;;;;;;;;:39;;;;5067:49;5086:9;5097;;5108:7;5067:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;5067:49:33::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;5067:49:33;;-1:-1:-1;;;;;;5067:49:33::1;3124:1;3881:1242:::0;;;;:::o;7276:936:36:-;7415:17;7435:25;7451:8;7435:15;:25::i;:::-;7478:30;;;;:19;:30;;;;;;7415:45;;-1:-1:-1;7478:30:36;;7470:61;;;;;-1:-1:-1;;;7470:61:36;;;;;;;;;;;;-1:-1:-1;;;7470:61:36;;;;;;;;;;;;;;;7549:30;7569:9;7549:19;:30::i;:::-;7541:66;;;;;-1:-1:-1;;;7541:66:36;;;;;;;;;;;;-1:-1:-1;;;7541:66:36;;;;;;;;;;;;;;;7617:15;7635:48;7660:9;7671:11;;7635:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7635:24:36;;-1:-1:-1;;;7635:48:36:i;:::-;7741:1;7701:28;;;:18;:28;;;;;;;;:37;;;;;;;;;7617:66;;-1:-1:-1;7693:83:36;;;;;-1:-1:-1;;;7693:83:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;7786:23;7812:28;;;:18;:28;;;;;;;;:37;;;;;;;;;;7859:41;;;7937:67;7953:9;7812:37;7981:9;7992:11;;7937:15;:67::i;:::-;8019:186;8059:8;8081:9;8104:41;8118:9;8129:15;8104:13;:41::i;:::-;8019:186;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7276:936;;;;;;;:::o;1144:358:32:-;1221:15;1253:38;;;:19;:38;;;;;;;;1248:248;;-1:-1:-1;1368:1:32;1248:248;;;-1:-1:-1;1448:37:32;;;;:18;:37;;;;;;;1144:358::o;2292:62:15:-;2352:2;2292:62;:::o;1584:56::-;1637:2;1584:56;:::o;4365:265:36:-;4477:7;4585:28;;;:18;:28;;;;;;;;:37;;;;;;;;;4528:7;;4552:71;;4528:7;;4552:13;:71::i;:::-;4545:78;4365:265;-1:-1:-1;;;;4365:265:36:o;2276:126:35:-;2328:13;2353:42;;;;;;;;;;;;;;;;;;;2276:126;:::o;1964:297:4:-;2156:6;-1:-1:-1;;;;;2182:25:4;;2202:4;2182:25;:71;;2251:1;2182:71;;;-1:-1:-1;;;2182:71:4;2174:80;1964:297;-1:-1:-1;;;;;;;1964:297:4:o;2485:326:31:-;2656:30;;;;:19;:30;;;;;;2556:22;;2656:30;;2648:68;;;;;-1:-1:-1;;;2648:68:31;;;;;;;;;;;;-1:-1:-1;;;2648:68:31;;;;;;;;;;;;;;;2773:31;;;;:20;:31;;;;;;;;;2761:43;;;;;;-1:-1:-1;;2761:43:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2773:31;;2761:43;;2773:31;2761:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2485:326;;;:::o;13841:351:3:-;14015:8;1224:25:20;1240:8;1224:15;:25::i;:::-;-1:-1:-1;;;;;1210:39:20;:10;-1:-1:-1;;;;;1210:39:20;;1202:78;;;;;-1:-1:-1;;;1202:78:20;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1202:78:20;;;;;;;;;;;;;;;14121:64:3::1;14147:8;14157:9;14168:7;14177;14121:25;:64::i;2997:158:31:-:0;3065:4;-1:-1:-1;;;3088:44:31;3122:9;3088:33;:44::i;:::-;-1:-1:-1;;;;;;3088:60:31;;;2997:158;-1:-1:-1;;2997:158:31:o;1508:323:32:-;1636:23;1675:15;1693:29;1704:17;1693:10;:29::i;:::-;1675:47;;1749:7;1740:6;:16;;;;;;:21;1732:48;;;;;-1:-1:-1;;;1732:48:32;;;;;;;;;;;;-1:-1:-1;;;1732:48:32;;;;;;;;;;;;;;;1817:7;1808:6;:16;;;;;;;1508:323;-1:-1:-1;;;;1508:323:32:o;2423:205:7:-;2498:4;2514:32;2549:19;:17;:19::i;:::-;-1:-1:-1;;;;;2585:36:7;;;;:22;:36;;;;;;;;-1:-1:-1;;2585:36:7;;;;;;;2423:205::o;4002:284:31:-;4082:4;4098:20;4121:44;4155:9;4121:33;:44::i;:::-;4098:67;-1:-1:-1;;;;;;;4194:40:31;;-1:-1:-1;;;4194:40:31;;:85;;-1:-1:-1;;;;;;;4238:41:31;;-1:-1:-1;;;4238:41:31;4175:104;;;4002:284;;;:::o;3665:331::-;3745:4;3761:20;3784:44;3818:9;3784:33;:44::i;:::-;3761:67;-1:-1:-1;;;;;;;3857:29:31;;-1:-1:-1;;;3857:29:31;;:76;;-1:-1:-1;;;;;;;3902:31:31;;-1:-1:-1;;;3902:31:31;3857:76;:132;;;-1:-1:-1;;;;;;;3949:40:31;;-1:-1:-1;;;3949:40:31;3838:151;;;3665:331;;;:::o;5792:877:3:-;5952:7;6066:25;;;:15;:25;;;;;;;;:34;;;;;;;;:43;;;;;;;;;6119:31;;6168;;;;6160:60;;;;;-1:-1:-1;;;6160:60:3;;;;;;;;;;;;-1:-1:-1;;;6160:60:3;;;;;;;;;;;;;;;6230:25;;;;:15;:25;;;;;;;;:34;;;;;;;;:43;;;;;;;;:58;;;6410:29;6246:8;6410:19;:29::i;:::-;:86;;;;-1:-1:-1;6443:30:3;;;;:20;:30;;;;;;;;:39;;;;;;;;:48;;;;;;;;;:53;;6410:86;6393:194;;;6528:30;;;;:20;:30;;;;;;;;:39;;;;;;;;:48;;;;;;;;6521:55;6650:12;5792:877;-1:-1:-1;;;;;5792:877:3:o;1131:1261:34:-;1223:14;1240:41;1254:9;1265:15;1240:13;:41::i;:::-;1223:58;;1295:18;1303:9;1295:7;:18::i;:::-;1291:1095;;;1333:20;1329:33;;1355:7;;;1329:33;1375:20;1398:33;1421:9;1398:22;:33::i;:::-;1375:56;;1445:12;1467;1445:35;;1494:29;1526:5;-1:-1:-1;;;;;1526:15:34;;1550:4;1526:30;;;;;;;;;;;;;-1:-1:-1;;;;;1526:30:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1526:30:34;1594:164;;;1679:10;1594:164;;;;1715:4;1594:164;;;;;;;;;;;;;;;;;;;;;;;;;;;;1526:30;1594:164;;;;-1:-1:-1;;;;;1594:164:34;-1:-1:-1;;;1594:164:34;;;1526:30;;-1:-1:-1;1772:44:34;-1:-1:-1;;;;;1772:34:34;;1594:164;1772:34;:44::i;:::-;1830:28;1861:5;-1:-1:-1;;;;;1861:15:34;;1885:4;1861:30;;;;;;;;;;;;;-1:-1:-1;;;;;1861:30:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1861:30:34;;-1:-1:-1;1913:45:34;;;;1905:66;;;;;-1:-1:-1;;;1905:66:34;;;;;;;;;;;;-1:-1:-1;;;1905:66:34;;;;;;;;;;;;;;;2133:6;2109:21;:30;2085:20;:54;2060:141;;;;;-1:-1:-1;;;2060:141:34;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2060:141:34;;;;;;;;;;;;;;;1291:1095;;;;;;;;2222:18;2230:9;2222:7;:18::i;:::-;2218:168;;;2277:6;2264:9;:19;2256:56;;;;;-1:-1:-1;;;2256:56:34;;;;;;;;;;;;-1:-1:-1;;;2256:56:34;;;;;;;;;;;;;;;2218:168;;;2343:32;;;-1:-1:-1;;;2343:32:34;;;;;;;;;;;;-1:-1:-1;;;2343:32:34;;;;;;;;;;;;;;1131:1261;;;:::o;790:348:32:-;929:14;959:15;977:29;988:17;977:10;:29::i;:::-;959:47;;1043:7;1025:15;:25;1016:34;;1088:15;1077:7;1068:6;:16;;;;;;:35;1060:71;;;;;-1:-1:-1;;;1060:71:32;;;;;;;;;;;;-1:-1:-1;;;1060:71:32;;;;;;;;;;;;;;;790:348;;;;;:::o;3782:498:7:-;3911:32;3946:19;:17;:19::i;:::-;3997:21;;;;;;-1:-1:-1;;;;;;3997:21:7;3983:10;:35;3975:71;;;;;-1:-1:-1;;;3975:71:7;;;;;;;;;;;;-1:-1:-1;;;3975:71:7;;;;;;;;;;;;;;;4094:21;;;;4082:34;;-1:-1:-1;;;;;4094:21:7;4082:11;:34::i;:::-;4126:21;;;:36;;-1:-1:-1;;;;;;4126:36:7;;;4239:34;;;4262:10;4239:34;;;;;;;;;;;;;3782:498;:::o;901:231:28:-;1032:7;1062:63;;;;;;;;;;;;;;-1:-1:-1;;;1062:63:28;;;1106:8;1116:7;1095:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1062:13;:63::i;4292:259:31:-;4375:4;4391:20;4414:44;4448:9;4414:33;:44::i;:::-;4391:67;-1:-1:-1;;;;;;;4475:32:31;;-1:-1:-1;;;4475:32:31;;:69;;-1:-1:-1;;;;;;;4511:33:31;;-1:-1:-1;;;4511:33:31;4468:76;;;4292:259;;;:::o;3327:162::-;3396:4;-1:-1:-1;;;3419:44:31;3453:9;3419:33;:44::i;2495:487:34:-;2653:33;2676:9;2653:22;:33::i;:::-;2645:65;;;;;-1:-1:-1;;;2645:65:34;;;;;;;;;;;;-1:-1:-1;;;2645:65:34;;;;;;;;;;;;;;;2725:19;2734:9;2725:8;:19::i;:::-;2721:255;;;2768:15;2787:1;2768:20;2760:52;;;;;-1:-1:-1;;;2760:52:34;;;;;;;;;;;;-1:-1:-1;;;2760:52:34;;;;;;;;;;;;;;;2826:33;2840:9;2851:7;2826:13;:33::i;2721:255::-;2880:19;;2876:100;;2915:50;2929:9;2940:7;2949:15;2915:13;:50::i;1849:198:14:-;1924:14;1959:19;1969:8;1959:9;:19::i;:::-;1950:28;-1:-1:-1;;;;;;1996:22:14;;1988:52;;;;;-1:-1:-1;;;1988:52:14;;;;;;;;;;;;-1:-1:-1;;;1988:52:14;;;;;;;;;;;;;;4712:1430:34;-1:-1:-1;;;;;4925:25:34;;4917:55;;;;;-1:-1:-1;;;4917:55:34;;;;;;;;;;;;-1:-1:-1;;;4917:55:34;;;;;;;;;;;;;;;4982:14;4999:41;5013:9;5024:15;4999:13;:41::i;:::-;4982:58;;5054:18;5062:9;5054:7;:18::i;:::-;5050:1086;;;5092:20;5088:33;;5114:7;;;5088:33;5134:20;5157:33;5180:9;5157:22;:33::i;:::-;5134:56;;5204:12;5226;5204:35;;5253:29;5285:5;-1:-1:-1;;;;;5285:15:34;;5309:4;5285:30;;;;;;;;;;;;;-1:-1:-1;;;;;5285:30:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5285:30:34;5353:128;;;-1:-1:-1;;;;;5353:128:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5285:30;5353:128;;;;-1:-1:-1;;;;;5353:128:34;-1:-1:-1;;;5353:128:34;;;5285:30;;-1:-1:-1;5495:44:34;;:34;;5353:128;5495:34;:44::i;:::-;5553:28;5584:5;-1:-1:-1;;;;;5584:15:34;;5608:4;5584:30;;;;;;;;;;;;;-1:-1:-1;;;;;5584:30:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5584:30:34;;-1:-1:-1;5636:45:34;;;;5628:67;;;;;-1:-1:-1;;;5628:67:34;;;;;;;;;;;;-1:-1:-1;;;5628:67:34;;;;;;;;;;;;;;;5857:6;5833:21;:30;5809:20;:54;5784:141;;;;;-1:-1:-1;;;5784:141:34;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;5784:141:34;;;;;;;;;;;;;;;5050:1086;;;;;;;;5946:18;5954:9;5946:7;:18::i;:::-;5942:194;;;5984:20;5980:33;;6006:7;;;5980:33;6026:36;-1:-1:-1;;;;;6026:28:34;;6055:6;6026:28;:36::i;:::-;5942:194;;3495:164:31;3565:4;-1:-1:-1;;;3588:44:31;3622:9;3588:33;:44::i;6248:538:34:-;6434:33;6457:9;6434:22;:33::i;:::-;6426:65;;;;;-1:-1:-1;;;6426:65:34;;;;;;;;;;;;-1:-1:-1;;;6426:65:34;;;;;;;;;;;;;;;6505:19;6514:9;6505:8;:19::i;:::-;6501:279;;;6548:15;6567:1;6548:20;6540:52;;;;;-1:-1:-1;;;6540:52:34;;;;;;;;;;;;-1:-1:-1;;;6540:52:34;;;;;;;;;;;;;;;6606:45;6621:9;6632;6643:7;6606:14;:45::i;6501:279::-;6672:19;;6668:112;;6707:62;6722:9;6733;6744:7;6753:15;6707:14;:62::i;2702:209:7:-;1031:23:19;1043:10;1031:11;:23::i;:::-;1023:51;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;;;2765:32:7::1;2800:19;:17;:19::i;:::-;2829:21;::::0;::::1;:36:::0;;-1:-1:-1;;;;;;2829:36:7::1;::::0;;2880:24:::1;::::0;2765:54;;-1:-1:-1;2880:24:7::1;::::0;2861:3:::1;::::0;2880:24:::1;1084:1:19;2702:209:7:o:0;2917:303::-;1031:23:19;1043:10;1031:11;:23::i;:::-;1023:51;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;;;3002:32:7::1;3037:19;:17;:19::i;:::-;3002:54;;3075:24;3087:11;3075;:24::i;:::-;3074:25;3066:54;;;::::0;;-1:-1:-1;;;3066:54:7;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;3066:54:7;;;;;;;;;;;;;::::1;;3130:21;::::0;::::1;:35:::0;;-1:-1:-1;;;;;3130:35:7;::::1;-1:-1:-1::0;;;;;;3130:35:7;;::::1;::::0;::::1;::::0;;;3180:33:::1;::::0;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;1084:1:19;2917:303:7::0;:::o;4337:402::-;1031:23:19;1043:10;1031:11;:23::i;:::-;1023:51;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;-1:-1:-1;;;1023:51:19;;;;;;;;;;;;;;;4432:10:7::1;-1:-1:-1::0;;;;;4432:32:7;::::1;;;4424:65;;;::::0;;-1:-1:-1;;;4424:65:7;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4424:65:7;;;;;;;;;;;;;::::1;;4499:32;4534:19;:17;:19::i;:::-;4499:54;;4571:31;4583:18;4571:11;:31::i;:::-;4563:56;;;::::0;;-1:-1:-1;;;4563:56:7;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;4563:56:7;;;;;;;;;;;;;::::1;;-1:-1:-1::0;;;;;4629:42:7;::::1;4674:5;4629:42:::0;;;::::1;::::0;;;;;;;;:50;;-1:-1:-1;;4629:50:7::1;::::0;;4694:38;;;;;;;::::1;::::0;;;;;;;;::::1;1084:1:19;4337:402:7::0;:::o;10933:878:3:-;11063:7;11149:30;;;:20;:30;;;;;;;;:39;;;;;;;;:48;;;;;;;;;11215:16;11207:49;;;;;-1:-1:-1;;;11207:49:3;;;;;;;;;;;;-1:-1:-1;;;11207:49:3;;;;;;;;;;;;;;;1106:6:15;11285:34:3;;;;11336:32;;;11329:40;;;;11406:8;11387:15;:27;;11379:54;;;;;-1:-1:-1;;;11379:54:3;;;;;;;;;;;;-1:-1:-1;;;11379:54:3;;;;;;;;;;;;;;;-1:-1:-1;;;11492:23:3;11518:25;;;:15;:25;;;;;;;;:34;;;;;;;;:43;;;;;;;;;;11571:50;;;;11638:30;;;:20;:30;;;;;:39;;;;;;;;;:48;;;;;;;;;;11631:55;11518:43;10933:878::o;5468:949:31:-;5550:20;5573:44;5607:9;5573:33;:44::i;:::-;5550:67;;5696:31;5713:13;5696:16;:31::i;:::-;5688:66;;;;;-1:-1:-1;;;5688:66:31;;;;;;;;;;;;-1:-1:-1;;;5688:66:31;;;;;;;;;;;;;;;-1:-1:-1;;;;;;5769:29:31;;-1:-1:-1;;;5769:29:31;5765:646;;;5908:9;:16;5928:1;5908:21;5900:54;;;;;-1:-1:-1;;;5900:54:31;;;;;;;;;;;;-1:-1:-1;;;5900:54:31;;;;;;;;;;;;;;;5765:646;;;6199:9;:16;6219:4;6199:24;6191:57;;;;;-1:-1:-1;;;6191:57:31;;;;;;;;;;;;-1:-1:-1;;;6191:57:31;;;;;;;;;;;;;;;6262:20;6285:46;6321:9;6285:35;:46::i;:::-;6262:69;;6353:25;:12;-1:-1:-1;;;;;6353:23:31;;:25::i;:::-;6345:55;;;;;-1:-1:-1;;;6345:55:31;;;;;;;;;;;;-1:-1:-1;;;6345:55:31;;;;;;;;;;;;;;6423:272;6511:4;6527:20;6550:44;6584:9;6550:33;:44::i;:::-;6527:67;-1:-1:-1;;;;;;;6611:32:31;;-1:-1:-1;;;6611:32:31;;:77;;-1:-1:-1;;;;;;;6647:41:31;;-1:-1:-1;;;6647:41:31;6604:84;;;6423:272;;;:::o;8914:805:34:-;-1:-1:-1;;;;;9159:25:34;;9151:55;;;;;-1:-1:-1;;;9151:55:34;;;;;;;;;;;;-1:-1:-1;;;9151:55:34;;;;;;;;;;;;;;;9224:30;9244:9;9224:19;:30::i;:::-;9216:66;;;;;-1:-1:-1;;;9216:66:34;;;;;;;;;;;;-1:-1:-1;;;9216:66:34;;;;;;;;;;;;;;;9318:1;9300:15;:19;9292:51;;;;;-1:-1:-1;;;9292:51:34;;;;;;;;;;;;-1:-1:-1;;;9292:51:34;;;;;;;;;;;;;;;9353:14;9370:41;9384:9;9395:15;9370:13;:41::i;:::-;9353:58;;9421:20;9444:33;9467:9;9444:22;:33::i;:::-;9421:56;;9487:225;9626:9;9653:6;9677:11;;9535:167;;;;;;-1:-1:-1;;;;;9535:167:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9535:167:34;;;;;;;;;;;;;;;;;;-1:-1:-1;9535:167:34;;;;;-1:-1:-1;;;;;;;;9535:167:34;;;;;;-1:-1:-1;;;;;9487:34:34;;;-1:-1:-1;9535:167:34;-1:-1:-1;9487:34:34;;-1:-1:-1;;;;9487:225:34:i;:::-;8914:805;;;;;;;:::o;2817:174:31:-;2901:6;2926:58;2960:23;2973:9;2960:12;:23::i;:::-;2926:33;:58::i;2562:155:25:-;2623:28;2670:14;2685:24;;;;;;;;;;;;;;;;;2670:40;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2670:40:25;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2670:40:25;;;;;;;;;;;;;;;;-1:-1:-1;2670:40:25;;;;;;;;;;;2562:155;-1:-1:-1;;;2562:155:25:o;2053:142:14:-;2132:4;2169:19;2179:8;2169:9;:19::i;:::-;-1:-1:-1;;;;;2155:33:14;:10;-1:-1:-1;;;;;2155:33:14;;2148:40;;2053:142;;;:::o;3161:160:31:-;3229:4;-1:-1:-1;;;3252:44:31;3286:9;3252:33;:44::i;5286:176::-;5369:7;5395:60;5431:23;5444:9;5431:12;:23::i;:::-;5395:35;:60::i;1380:452:2:-;1483:24;1494:12;1483:10;:24::i;:::-;1475:54;;;;;-1:-1:-1;;;1475:54:2;;;;;;;;;;;;-1:-1:-1;;;1475:54:2;;;;;;;;;;;;;;;1584:12;1598:23;1625:12;-1:-1:-1;;;;;1625:17:2;1643:8;1625:27;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1625:27:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1583:69;;;;1670:7;1686:10;1662:36;;;;;-1:-1:-1;;;1662:36:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1713:17:2;;:21;1709:117;;1769:10;1758:30;;;;;;;;;;;;;;;-1:-1:-1;1758:30:2;1750:65;;;;;-1:-1:-1;;;1750:65:2;;;;;;;;;;;;-1:-1:-1;;;1750:65:2;;;;;;;;;;;;;;3539:237:7;3608:24;3620:11;3608;:24::i;:::-;3607:25;3599:54;;;;;-1:-1:-1;;;3599:54:7;;;;;;;;;;;;-1:-1:-1;;;3599:54:7;;;;;;;;;;;;;;;3663:32;3698:19;:17;:19::i;:::-;-1:-1:-1;;;;;3727:35:7;;;:22;:35;;;;;;;;-1:-1:-1;3727:35:7;;;:42;;-1:-1:-1;;3727:42:7;3765:4;3727:42;;;3539:237::o;855:250:1:-;988:18;1062:10;1074:22;1045:52;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1045:52:1;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1045:52:1;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1045:52:1;;;;;;;;;;;;;-1:-1:-1;;1045:52:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1035:63;;;;;;1022:76;;855:250;;;;:::o;2988:449:34:-;3073:19;3082:9;3073:8;:19::i;:::-;3065:48;;;;;-1:-1:-1;;;3065:48:34;;;;;;;;;;;;-1:-1:-1;;;3065:48:34;;;;;;;;;;;;;;;3123:20;3146:33;3169:9;3146:22;:33::i;:::-;3238:182;;;3340:10;3238:182;;;;3376:4;3238:182;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3238:182:34;-1:-1:-1;;;3238:182:34;;;3123:56;;-1:-1:-1;3190:240:34;;-1:-1:-1;;;;;3190:34:34;;;;:240::i;3443:1195::-;3583:20;3593:9;3583;:20::i;:::-;3575:50;;;;;-1:-1:-1;;;3575:50:34;;;;;;;;;;;;-1:-1:-1;;;3575:50:34;;;;;;;;;;;;;;;3639:20;3635:33;;3661:7;;3635:33;3678:14;3695:41;3709:9;3720:15;3695:13;:41::i;:::-;3678:58;;3746:20;3769:33;3792:9;3769:22;:33::i;:::-;3893:39;;;-1:-1:-1;;;3893:39:34;;3917:4;3893:39;;;;;;;;;;;;3746:56;;-1:-1:-1;3746:56:34;;3812:14;;-1:-1:-1;;;;;3893:15:34;;;;;:39;;;;;;;;;;;;;;;:15;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3861:71;;3986:278;4074:31;;;4123:10;4159:4;4182:7;4207:6;4231:9;;;;;;;;;;;;4034:220;;;;;;-1:-1:-1;;;;;4034:220:34;;;;;;-1:-1:-1;;;;;4034:220:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4034:220:34;;;-1:-1:-1;;4034:220:34;;;;;;;;;;;;;;-1:-1:-1;;;;;4034:220:34;-1:-1:-1;;;;;;4034:220:34;;;;;;;;;;-1:-1:-1;;;;;;;3986:34:34;;;4034:220;-1:-1:-1;;3986:34:34;:278;-1:-1:-1;;;3986:278:34:i;:::-;4275:28;4306:5;-1:-1:-1;;;;;4306:15:34;;4330:4;4337:7;4306:39;;;;;;;;;;;;;-1:-1:-1;;;;;4306:39:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4306:39:34;;-1:-1:-1;4363:45:34;;;;4355:66;;;;;-1:-1:-1;;;4355:66:34;;;;;;;;;;;;-1:-1:-1;;;4355:66:34;;;;;;;;;;;;;;;4571:6;4547:21;:30;4523:20;:54;4502:129;;;;;-1:-1:-1;;;4502:129:34;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;4502:129:34;;;;;;;;;;;;;;;3443:1195;;;;;;;;:::o;953:218:2:-;1054:33;;1036:12;;-1:-1:-1;;;;;1054:14:2;;;1076:6;;1036:12;1054:33;1036:12;1054:33;1076:6;1054:14;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1035:52;;;1133:7;1125:39;;;;;-1:-1:-1;;;1125:39:2;;;;;;;;;;;;-1:-1:-1;;;1125:39:2;;;;;;;;;;;;;;6858:618:34;-1:-1:-1;;;;;7048:25:34;;7040:55;;;;;-1:-1:-1;;;7040:55:34;;;;;;;;;;;;-1:-1:-1;;;7040:55:34;;;;;;;;;;;;;;;7113:19;7122:9;7113:8;:19::i;:::-;7105:48;;;;;-1:-1:-1;;;7105:48:34;;;;;;;;;;;;-1:-1:-1;;;7105:48:34;;;;;;;;;;;;;;;7163:20;7186:33;7209:9;7186:22;:33::i;:::-;7278:181;;;7388:4;7278:181;;;;-1:-1:-1;;;;;7278:181:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7278:181:34;-1:-1:-1;;;7278:181:34;;;7163:56;;-1:-1:-1;7230:239:34;;:34;;;;;:239::i;7565:1343::-;-1:-1:-1;;;;;7788:25:34;;7780:55;;;;;-1:-1:-1;;;7780:55:34;;;;;;;;;;;;-1:-1:-1;;;7780:55:34;;;;;;;;;;;;;;;7853:20;7863:9;7853;:20::i;:::-;7845:50;;;;;-1:-1:-1;;;7845:50:34;;;;;;;;;;;;-1:-1:-1;;;7845:50:34;;;;;;;;;;;;;;;7909:20;7905:33;;7931:7;;7905:33;7948:14;7965:41;7979:9;7990:15;7965:13;:41::i;:::-;7948:58;;8016:20;8039:33;8062:9;8039:22;:33::i;:::-;8163:39;;;-1:-1:-1;;;8163:39:34;;8187:4;8163:39;;;;;;;;;;;;8016:56;;-1:-1:-1;8016:56:34;;8082:14;;-1:-1:-1;;;;;8163:15:34;;;;;:39;;;;;;;;;;;;;;;:15;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8131:71;;8256:277;8344:31;;;8401:4;8424:9;8451:7;8476:6;8500:9;;;;;;;;;;;;8304:219;;;;;;-1:-1:-1;;;;;8304:219:34;;;;;;-1:-1:-1;;;;;8304:219:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8256:277;8544:28;8575:5;-1:-1:-1;;;;;8575:15:34;;8599:4;8606:7;8575:39;;;;;;;;;;;;;-1:-1:-1;;;;;8575:39:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8575:39:34;;-1:-1:-1;8632:45:34;;;;8624:67;;;;;-1:-1:-1;;;8624:67:34;;;;;;;;;;;;-1:-1:-1;;;8624:67:34;;;;;;;;;;;;;;;8841:6;8817:21;:30;8793:20;:54;8772:129;;;;;-1:-1:-1;;;8772:129:34;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;8772:129:34;;;;;;;;;;;;;;;7565:1343;;;;;;;;;:::o;2127:352:31:-;2432:15;2417:31;2411:38;-1:-1:-1;;;;;;2306:157:31;;2280:193::o;4557:398::-;4627:4;-1:-1:-1;;;;;;4662:29:31;;-1:-1:-1;;;4662:29:31;;:76;;-1:-1:-1;;;;;;;4707:31:31;;-1:-1:-1;;;4707:31:31;4662:76;:124;;;-1:-1:-1;;;;;;;4754:32:31;;-1:-1:-1;;;4754:32:31;4662:124;:180;;;-1:-1:-1;;;;;;;4802:40:31;;-1:-1:-1;;;4802:40:31;4662:180;:237;;;-1:-1:-1;;;;;;;4858:41:31;;-1:-1:-1;;;4858:41:31;4662:237;:286;;;-1:-1:-1;;;;;;;;4915:33:31;-1:-1:-1;;;4915:33:31;;4557:398::o;4961:319::-;1666:31;5212:22;5206:29;;4961:319::o;757:190:2:-;886:20;932:8;;;757:190::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;

Swarm Source

ipfs://dceb72817044db7cba290582a0d8c7b21878ca86d2edb87a60b1165772a90f36

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.