// File: Common.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

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

    function performEthTransfer(address recipient, uint256 amount) internal {
        // solium-disable-next-line security/no-call-value
        (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);
        // solium-disable-previous-line security/no-low-level-calls
        require(success, string(returndata));

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

    /*
      Similar to safeTokenContractCall, but always ignores the return value.

      Assumes some other method is used to detect the failures
      (e.g. balance is checked before and after the call).
    */
    function uncheckedTokenContractCall(address tokenAddress, bytes memory callData) internal {
        // NOLINTNEXTLINE: low-level-calls.
        (bool success, bytes memory returndata) = tokenAddress.call(callData);
        // solium-disable-previous-line security/no-low-level-calls
        require(success, string(returndata));
    }

}

/*
  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: GovernanceStorage.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

/*
  Holds the governance slots for ALL entities, including proxy and the main contract.
*/
contract GovernanceStorage {

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

    // A map from a Governor tag to its own GovernanceInfoStruct.
    mapping (string => GovernanceInfoStruct) internal governanceInfo;
}

// File: Identity.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

contract 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: IDispatcher.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

/*
  Interface for generic dispatcher to use,
  which the concrete dispatcher must implement.

  I contains the functions that are specific to the concrete dispatcher instance.

  The interface is implemented as contract, because interface implies all methods external.
*/
contract IDispatcher {

    function getSubContract(bytes4 selector) internal view returns (address);

    function setSubContractAddress(uint256 index, address subContract) internal;

    function getNumSubcontracts() internal pure returns (uint256);

    function validateSubContractIndex(uint256 index, address subContract) internal pure;

    /*
      Ensures initializer can be called. Reverts otherwise.
    */
    function initializationSentinel() internal view;
}

// File: IFactRegistry.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

/*
  The Fact Registry design pattern is a way to separate cryptographic verification from the
  business logic of the contract flow.

  A fact registry holds a hash table of verified "facts" which are represented by a hash of claims
  that the registry hash check and found valid. This table may be queried by accessing the
  isValid() function of the registry with a given hash.

  In addition, each fact registry exposes a registry specific function for submitting new claims
  together with their proofs. The information submitted varies from one registry to the other
  depending of the type of fact requiring verification.

  For further reading on the Fact Registry design pattern see this
  `StarkWare blog post <https://medium.com/starkware/the-fact-registry-a64aafb598b6>`_.
*/
contract IFactRegistry {
    /*
      Returns true if the given fact was previously registered in the contract.
    */
    function isValid(bytes32 fact)
        external view
        returns(bool);
}

// File: MainDispatcher.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

import "SubContractor.sol";
import "IDispatcher.sol";
import "Common.sol";
import "StorageSlots.sol";


contract MainDispatcher is IDispatcher, StorageSlots {

    using Addresses for address;

    function() external payable {
        address subContractAddress = getSubContract(msg.sig);
        require(subContractAddress != address(0x0), "NO_CONTRACT_FOR_FUNCTION");

        // solium-disable-next-line security/no-inline-assembly
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize)

            // Call the implementation.
            // out and outsize are 0 for now, as we don"t know the out size yet.
            let result := delegatecall(gas, subContractAddress, 0, calldatasize, 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize)

            switch result
                // delegatecall returns 0 on error.
                case 0 {
                    revert(0, returndatasize)
                }
                default {
                    return(0, returndatasize)
                }
        }
    }

    /*
      1. Extract subcontracts.
      2. Verify correct sub-contract initializer size.
      3. Extract sub-contract initializer data.
      4. Call sub-contract initializer.

      The init data bytes passed to initialize are structed as following:
      I. N slots (uin256 size) addresses of the deployed sub-contracts.
      II. An address of an external initialization contract (optional, or ZERO_ADDRESS).
      III. (Up to) N bytes sections of the sub-contracts initializers.

      If already initialized (i.e. upgrade) we expect the init data to be consistent with this.
      and if a different size of init data is expected when upgrading, the initializerSize should
      reflect this.

      If an external initializer contract is not used, ZERO_ADDRESS is passed in its slot.
      If the external initializer contract is used, all the remaining init data is passed to it,
      and internal initialization will not occur.

      External Initialization Contract
      --------------------------------
      External Initialization Contract (EIC) is a hook for custom initialization.
      Typically in an upgrade flow, the expected initialization contains only the addresses of
      the sub-contracts. Normal initialization of the sub-contracts is such that is not needed
      in an upgrade, and actually may be very dangerous, as changing of state on a working system
      may corrupt it.

      In the event that some state initialization is required, the EIC is a hook that allows this.
      It may be deployed and called specifically for this purpose.

      The address of the EIC must be provided (if at all) when a new implementation is added to
      a Proxy contract (as part of the initialization vector).
      Hence, it is considered part of the code open to reviewers prior to a time-locked upgrade.

      When a custom initialization is performed using an EIC,
      the main dispatcher initialize extracts and stores the sub-contracts addresses, and then
      yields to the EIC, skipping the rest of its initialization code.


      Flow of MainDispatcher initialize
      ---------------------------------
      1. Extraction and assignment of subcontracts addresses
         Main dispatcher expects a valid and consistent set of addresses in the passed data.
         It validates that, extracts the addresses from the data, and validates that the addresses
         are of the expected type and order. Then those addresses are stored.

      2. Extraction of EIC address
         The address of the EIC is extracted from the data.
         External Initializer Contract is optional. ZERO_ADDRESS indicates it is not used.

      3a. EIC is used
          Dispatcher calls the EIC initialize function with the remaining data.
          Note - In this option 3b is not performed.

      3b. EIC is not used
          If there is additional initialization data then:
          I. Sentitenl function is called to permit subcontracts initialization.
          II. Dispatcher loops through the subcontracts and for each one it extracts the
              initializing data and passes it to the subcontract's initialize function.

    */
    // NOLINTNEXTLINE: external-function.
    function initialize(bytes memory data) public {
        // Number of sub-contracts.
        uint256 nSubContracts = getNumSubcontracts();

        // We support currently 4 bits per contract, i.e. 16, reserving 00 leads to 15.
        require(nSubContracts <= 15, "TOO_MANY_SUB_CONTRACTS");

        // Init data MUST include addresses for all sub-contracts.
        require(data.length >= 32 * (nSubContracts + 1), "SUB_CONTRACTS_NOT_PROVIDED");

        // Ensure implementation is a valid contract.
        require(implementation().isContract(), "INVALID_IMPLEMENTATION");

        // Size of passed data, excluding sub-contract addresses.
        uint256 additionalDataSize = data.length - 32 * (nSubContracts + 1);

        // Sum of subcontract initializers. Aggregated for verification near the end.
        uint256 totalInitSizes = 0;

        // Offset (within data) of sub-contract initializer vector.
        // Just past the sub-contract addresses.
        uint256 initDataContractsOffset = 32 * (nSubContracts + 1);

        // 1. Extract & update contract addresses.
        for (uint256 nContract = 1; nContract <= nSubContracts; nContract++) {
            address contractAddress;

            // Extract sub-contract address.
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                contractAddress := mload(add(data, mul(32, nContract)))
            }

            validateSubContractIndex(nContract, contractAddress);

            // Contracts are indexed from 1 and 0 is not in use here.
            setSubContractAddress(nContract, contractAddress);
        }

        // Check if we have an external initializer contract.
        address externalInitializerAddr;

        // 2. Extract sub-contract address, again. It's cheaper than reading from storage.
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            externalInitializerAddr := mload(add(data, mul(32, add(nSubContracts, 1))))
        }

        // 3(a). Yield to EIC initialization.
        if (externalInitializerAddr != address(0x0)) {
            callExternalInitializer(data, externalInitializerAddr, additionalDataSize);
            return;
        }

        // 3(b). Subcontracts initialization.
        // I. If no init data passed besides sub-contracts, return.
        if (additionalDataSize == 0) {
            return;
        }

        // Just to be on the safe side.
        assert(externalInitializerAddr == address(0x0));

        // II. Gate further initialization.
        initializationSentinel();

        // III. Loops through the subcontracts, extracts their data and calls their initializer.
        for (uint256 nContract = 1; nContract <= nSubContracts; nContract++) {
            address contractAddress;

            // Extract sub-contract address, again. It's cheaper than reading from storage.
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                contractAddress := mload(add(data, mul(32, nContract)))
            }
            // The initializerSize returns the expected size, with respect also to the state status.
            // i.e. different size if it's a first init (clean state) or upgrade init (alive state).
            // NOLINTNEXTLINE: calls-loop.

            // The initializerSize is called via delegatecall, so that it can relate to the state,
            // and not only to the new contract code. (e.g. return 0 if state-intialized else 192).
            // solium-disable-next-line security/no-low-level-calls
            // NOLINTNEXTLINE: reentrancy-events low-level-calls calls-loop.
            (bool success, bytes memory returndata) = contractAddress.delegatecall(
                abi.encodeWithSelector(SubContractor(contractAddress).initializerSize.selector));
            require(success, string(returndata));
            uint256 initSize = abi.decode(returndata, (uint256));
            require(initSize <= additionalDataSize, "INVALID_INITIALIZER_SIZE");
            require(totalInitSizes + initSize <= additionalDataSize, "INVALID_INITIALIZER_SIZE");

            if (initSize == 0) {
                continue;
            }

            // Extract sub-contract init vector.
            bytes memory subContractInitData = new bytes(initSize);
            for (uint256 trgOffset = 32; trgOffset <= initSize; trgOffset += 32) {
                // solium-disable-next-line security/no-inline-assembly
                assembly {
                    mstore(
                        add(subContractInitData, trgOffset),
                        mload(add(add(data, trgOffset), initDataContractsOffset))
                    )
                }
            }

            // Call sub-contract initializer.
            // solium-disable-next-line security/no-low-level-calls
            // NOLINTNEXTLINE: low-level-calls.
            (success, returndata) = contractAddress.delegatecall(
                abi.encodeWithSelector(this.initialize.selector, subContractInitData)
            );
            require(success, string(returndata));
            totalInitSizes += initSize;
            initDataContractsOffset += initSize;
        }
        require(
            additionalDataSize == totalInitSizes,
            "MISMATCHING_INIT_DATA_SIZE");
    }

    function callExternalInitializer(
        bytes memory data,
        address externalInitializerAddr,
        uint256 dataSize)
        private {
        require(externalInitializerAddr.isContract(), "NOT_A_CONTRACT");
        require(dataSize <= data.length, "INVALID_DATA_SIZE");
        bytes memory extInitData = new bytes(dataSize);

        // Prepare memcpy pointers.
        uint256 srcDataOffset = 32 + data.length - dataSize;
        uint256 srcData;
        uint256 trgData;

        // solium-disable-next-line security/no-inline-assembly
        assembly {
            srcData := add(data, srcDataOffset)
            trgData := add(extInitData, 32)
        }

        // Copy initializer data to be passed to the EIC.
        for (uint256 seek = 0; seek < dataSize; seek += 32) {
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                mstore(
                    add(trgData, seek),
                    mload(add(srcData, seek))
                )
            }
        }

        // solium-disable-next-line security/no-low-level-calls
        // NOLINTNEXTLINE: low-level-calls.
        (bool success, bytes memory returndata) = externalInitializerAddr.delegatecall(
            abi.encodeWithSelector(this.initialize.selector, extInitData)
        );
        require(success, string(returndata));
        require(returndata.length == 0, string(returndata));
    }
}

// File: MainStorage.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

import "IFactRegistry.sol";
import "ProxyStorage.sol";
import "Common.sol";
/*
  Holds ALL the main contract state (storage) variables.
*/
contract MainStorage is ProxyStorage {

    IFactRegistry escapeVerifier_;

    // 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.

    // Full withdrawal requests: stark key => vaultId => requestTime.
    // stark key => vaultId => requestTime.
    mapping (uint256 => mapping (uint256 => uint256)) fullWithdrawalRequests;

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

    // Vaults Tree Root & Height.
    uint256 vaultRoot;                              // NOLINT: constable-states uninitialized-state.
    uint256 vaultTreeHeight;                        // 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;

    // True if and only if the address is allowed to register users.
    mapping (address => bool) userAdmins;

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

    // 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.

    // Onchain-data version configured for the system.
    // TODO(zuphit,01/01/2021): wrap this with an attribute class.
    uint256 onchainDataVersion;                     // NOLINT: constable-states uninitialized-state.
}

// File: ProxyStorage.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

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 {

    // Stores the hash of the initialization vector of the added implementation.
    // Upon upgradeTo the implementation, the initialization vector is verified
    // to be identical to the one submitted when adding the implementation.
    mapping (address => bytes32) internal initializationHash;

    // The time after which we can switch to the implementation.
    mapping (address => 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: StarkExchange.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

import "MainStorage.sol";
import "MainDispatcher.sol";

contract StarkExchange is MainStorage, MainDispatcher {
    string public constant VERSION = "2.5.0";

    uint256 constant SUBCONTRACT_BITS = 4;

    // Salt for a 7 bit unique spread of all relevant selectors. Pre-calculated.
    // ---------- The following code was auto-generated. PLEASE DO NOT EDIT. ----------
    uint256 constant MAGIC_SALT = 45733;
    uint256 constant IDX_MAP_0 = 0x201220230201001000221220210222000000020303010211122120200003002;
    uint256 constant IDX_MAP_1 = 0x2100003002200010003000000300100220220203000020000101022100011100;
    // ---------- End of auto-generated code. ----------

    function validateSubContractIndex(uint256 index, address subContract) internal pure{
        string memory id = SubContractor(subContract).identify();
        bytes32 hashed_expected_id = keccak256(abi.encodePacked(expectedIdByIndex(index)));
        require(
            hashed_expected_id == keccak256(abi.encodePacked(id)),
            "MISPLACED_INDEX_OR_BAD_CONTRACT_ID");
    }

    function expectedIdByIndex(uint256 index)
        private pure returns (string memory id) {
        if (index == 1){
            id = "StarkWare_AllVerifiers_2020_1";
        } else if (index == 2){
            id = "StarkWare_TokensAndRamping_2020_1";
        } else if (index == 3){
            id = "StarkWare_StarkExState_2020_1";
        } else {
            revert("UNEXPECTED_INDEX");
        }
    }

    function getNumSubcontracts() internal pure returns (uint256) {
        return 3;
    }

    function getSubContract(bytes4 selector)
        internal view returns (address) {
        uint256 location = 0x7F & uint256(keccak256(abi.encodePacked(selector, MAGIC_SALT)));
        uint256 subContractIdx;
        uint256 offset = SUBCONTRACT_BITS * location % 256;
        if (location < 64) {
            subContractIdx = (IDX_MAP_0 >> offset) & 0xF;
        } else {
            subContractIdx = (IDX_MAP_1 >> offset) & 0xF;
        }
        return subContracts[subContractIdx];
    }

    function setSubContractAddress(uint256 index, address subContractAddress) internal {
        subContracts[index] = subContractAddress;
    }

    function initializationSentinel()
        internal view {
        string memory REVERT_MSG = "INITIALIZATION_BLOCKED";
        // This initializer sets roots etc. It must not be applied twice.
        // I.e. it can run only when the state is still empty.
        require(vaultRoot == 0, REVERT_MSG);
        require(vaultTreeHeight == 0, REVERT_MSG);
        require(orderRoot == 0, REVERT_MSG);
        require(orderTreeHeight == 0, REVERT_MSG);
    }
}

// File: StorageSlots.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

/**
  StorageSlots holds the arbitrary storage slots used throughout the Proxy pattern.
  Storage address slots are a mechanism to define an arbitrary location, that will not be
  overlapped by the logical contracts.
*/
contract StorageSlots {
    /*
      Returns the address of the current implementation.
    */
    // NOLINTNEXTLINE external-function.
    function implementation() public view returns(address _implementation) {
        bytes32 slot = IMPLEMENTATION_SLOT;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            _implementation := sload(slot)
        }
    }

    // Storage slot with the address of the current implementation.
    // The address of the slot is keccak256("StarkWare2019.implemntation-slot").
    // We need to keep this variable stored outside of the commonly used space,
    // so that it's not overrun by the logical implementation (the proxied contract).
    bytes32 internal constant IMPLEMENTATION_SLOT =
    0x177667240aeeea7e35eabe3a35e18306f336219e1386f7710a6bf8783f761b24;

    // This storage slot stores the finalization flag.
    // Once the value stored in this slot is set to non-zero
    // the proxy blocks implementation upgrades.
    // The current implementation is then referred to as Finalized.
    // Web3.solidityKeccak(['string'], ["StarkWare2019.finalization-flag-slot"]).
    bytes32 internal constant FINALIZED_STATE_SLOT =
    0x7d433c6f837e8f93009937c466c82efbb5ba621fae36886d0cac433c5d0aa7d2;

    // Storage slot to hold the upgrade delay (time-lock).
    // The intention of this slot is to allow modification using an EIC.
    // Web3.solidityKeccak(['string'], ['StarkWare.Upgradibility.Delay.Slot']).
    bytes32 public constant UPGRADE_DELAY_SLOT =
    0xc21dbb3089fcb2c4f4c6a67854ab4db2b0f233ea4b21b21f912d52d18fc5db1f;
}

// File: SubContractor.sol



/*
  Copyright 2019,2020 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.
*/
pragma solidity ^0.5.2;

import "Identity.sol";

contract SubContractor is Identity {

    function initialize(bytes calldata data)
        external;

    function initializerSize()
        external view
        returns(uint256);

}