Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ZkSync
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.0; import "./ReentrancyGuard.sol"; import "./SafeMath.sol"; import "./SafeMathUInt128.sol"; import "./SafeCast.sol"; import "./Utils.sol"; import "./Storage.sol"; import "./Config.sol"; import "./Events.sol"; import "./Bytes.sol"; import "./Operations.sol"; import "./UpgradeableMaster.sol"; /// @title zkSync main contract /// @author Matter Labs contract ZkSync is UpgradeableMaster, Storage, Config, Events, ReentrancyGuard { using SafeMath for uint256; using SafeMathUInt128 for uint128; bytes32 public constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // Upgrade functional /// @notice Notice period before activation preparation status of upgrade mode function getNoticePeriod() external returns (uint) { return UPGRADE_NOTICE_PERIOD; } /// @notice Notification that upgrade notice period started function upgradeNoticePeriodStarted() external { } /// @notice Notification that upgrade preparation status is activated function upgradePreparationStarted() external { upgradePreparationActive = true; upgradePreparationActivationTime = now; } /// @notice Notification that upgrade canceled function upgradeCanceled() external { upgradePreparationActive = false; upgradePreparationActivationTime = 0; } /// @notice Notification that upgrade finishes function upgradeFinishes() external { upgradePreparationActive = false; upgradePreparationActivationTime = 0; } /// @notice Checks that contract is ready for upgrade /// @return bool flag indicating that contract is ready for upgrade function isReadyForUpgrade() external returns (bool) { return !exodusMode; } /// @notice Franklin contract initialization. Can be external because Proxy contract intercepts illegal calls of this function. /// @param initializationParameters Encoded representation of initialization parameters: /// _governanceAddress The address of Governance contract /// _verifierAddress The address of Verifier contract /// _ // FIXME: remove _genesisAccAddress /// _genesisRoot Genesis blocks (first block) root function initialize(bytes calldata initializationParameters) external { initializeReentrancyGuard(); ( address _governanceAddress, address _verifierAddress, bytes32 _genesisRoot ) = abi.decode(initializationParameters, (address, address, bytes32)); verifier = Verifier(_verifierAddress); governance = Governance(_governanceAddress); blocks[0].stateRoot = _genesisRoot; } /// @notice zkSync contract upgrade. Can be external because Proxy contract intercepts illegal calls of this function. /// @param upgradeParameters Encoded representation of upgrade parameters function upgrade(bytes calldata upgradeParameters) external {} /// @notice Sends tokens /// @dev NOTE: will revert if transfer call fails or rollup balance difference (before and after transfer) is bigger than _maxAmount /// @param _token Token address /// @param _to Address of recipient /// @param _amount Amount of tokens to transfer /// @param _maxAmount Maximum possible amount of tokens to transfer to this account function withdrawERC20Guarded(IERC20 _token, address _to, uint128 _amount, uint128 _maxAmount) external returns (uint128 withdrawnAmount) { require(msg.sender == address(this), "wtg10"); // wtg10 - can be called only from this contract as one "external" call (to revert all this function state changes if it is needed) uint256 balance_before = _token.balanceOf(address(this)); require(Utils.sendERC20(_token, _to, _amount), "wtg11"); // wtg11 - ERC20 transfer fails uint256 balance_after = _token.balanceOf(address(this)); uint256 balance_diff = balance_before.sub(balance_after); require(balance_diff <= _maxAmount, "wtg12"); // wtg12 - rollup balance difference (before and after transfer) is bigger than _maxAmount return SafeCast.toUint128(balance_diff); } /// @notice executes pending withdrawals /// @param _n The number of withdrawals to complete starting from oldest function completeWithdrawals(uint32 _n) external nonReentrant { // TODO: when switched to multi validators model we need to add incentive mechanism to call complete. uint32 toProcess = Utils.minU32(_n, numberOfPendingWithdrawals); uint32 startIndex = firstPendingWithdrawalIndex; numberOfPendingWithdrawals -= toProcess; firstPendingWithdrawalIndex += toProcess; for (uint32 i = startIndex; i < startIndex + toProcess; ++i) { uint16 tokenId = pendingWithdrawals[i].tokenId; address to = pendingWithdrawals[i].to; // send fails are ignored hence there is always a direct way to withdraw. delete pendingWithdrawals[i]; bytes22 packedBalanceKey = packAddressAndTokenId(to, tokenId); uint128 amount = balancesToWithdraw[packedBalanceKey].balanceToWithdraw; // amount is zero means funds has been withdrawn with withdrawETH or withdrawERC20 if (amount != 0) { balancesToWithdraw[packedBalanceKey].balanceToWithdraw -= amount; bool sent = false; if (tokenId == 0) { address payable toPayable = address(uint160(to)); sent = Utils.sendETHNoRevert(toPayable, amount); } else { address tokenAddr = governance.tokenAddresses(tokenId); // we can just check that call not reverts because it wants to withdraw all amount (sent, ) = address(this).call.gas(ERC20_WITHDRAWAL_GAS_LIMIT)( abi.encodeWithSignature("withdrawERC20Guarded(address,address,uint128,uint128)", tokenAddr, to, amount, amount) ); } if (!sent) { balancesToWithdraw[packedBalanceKey].balanceToWithdraw += amount; } } } if (toProcess > 0) { emit PendingWithdrawalsComplete(startIndex, startIndex + toProcess); } } /// @notice Accrues users balances from deposit priority requests in Exodus mode /// @dev WARNING: Only for Exodus mode /// @dev Canceling may take several separate transactions to be completed /// @param _n number of requests to process function cancelOutstandingDepositsForExodusMode(uint64 _n) external nonReentrant { require(exodusMode, "coe01"); // exodus mode not active uint64 toProcess = Utils.minU64(totalOpenPriorityRequests, _n); require(toProcess > 0, "coe02"); // no deposits to process for (uint64 id = firstPriorityRequestId; id < firstPriorityRequestId + toProcess; id++) { if (priorityRequests[id].opType == Operations.OpType.Deposit) { Operations.Deposit memory op = Operations.readDepositPubdata(priorityRequests[id].pubData); bytes22 packedBalanceKey = packAddressAndTokenId(op.owner, op.tokenId); balancesToWithdraw[packedBalanceKey].balanceToWithdraw += op.amount; } delete priorityRequests[id]; } firstPriorityRequestId += toProcess; totalOpenPriorityRequests -= toProcess; } /// @notice Deposit ETH to Layer 2 - transfer ether from user into contract, validate it, register deposit /// @param _franklinAddr The receiver Layer 2 address function depositETH(address _franklinAddr) external payable nonReentrant { requireActive(); registerDeposit(0, SafeCast.toUint128(msg.value), _franklinAddr); } /// @notice Withdraw ETH to Layer 1 - register withdrawal and transfer ether to sender /// @param _amount Ether amount to withdraw function withdrawETH(uint128 _amount) external nonReentrant { registerWithdrawal(0, _amount, msg.sender); (bool success, ) = msg.sender.call.value(_amount)(""); require(success, "fwe11"); // ETH withdraw failed } /// @notice Deposit ERC20 token to Layer 2 - transfer ERC20 tokens from user into contract, validate it, register deposit /// @param _token Token address /// @param _amount Token amount /// @param _franklinAddr Receiver Layer 2 address function depositERC20(IERC20 _token, uint104 _amount, address _franklinAddr) external nonReentrant { requireActive(); // Get token id by its address uint16 tokenId = governance.validateTokenAddress(address(_token)); uint256 balance_before = _token.balanceOf(address(this)); require(Utils.transferFromERC20(_token, msg.sender, address(this), SafeCast.toUint128(_amount)), "fd012"); // token transfer failed deposit uint256 balance_after = _token.balanceOf(address(this)); uint128 deposit_amount = SafeCast.toUint128(balance_after.sub(balance_before)); registerDeposit(tokenId, deposit_amount, _franklinAddr); } /// @notice Withdraw ERC20 token to Layer 1 - register withdrawal and transfer ERC20 to sender /// @param _token Token address /// @param _amount amount to withdraw function withdrawERC20(IERC20 _token, uint128 _amount) external nonReentrant { uint16 tokenId = governance.validateTokenAddress(address(_token)); bytes22 packedBalanceKey = packAddressAndTokenId(msg.sender, tokenId); uint128 balance = balancesToWithdraw[packedBalanceKey].balanceToWithdraw; uint128 withdrawnAmount = this.withdrawERC20Guarded(_token, msg.sender, _amount, balance); registerWithdrawal(tokenId, withdrawnAmount, msg.sender); } /// @notice Register full exit request - pack pubdata, add priority request /// @param _accountId Numerical id of the account /// @param _token Token address, 0 address for ether function fullExit (uint32 _accountId, address _token) external nonReentrant { requireActive(); require(_accountId <= MAX_ACCOUNT_ID, "fee11"); uint16 tokenId; if (_token == address(0)) { tokenId = 0; } else { tokenId = governance.validateTokenAddress(_token); } // Priority Queue request Operations.FullExit memory op = Operations.FullExit({ accountId: _accountId, owner: msg.sender, tokenId: tokenId, amount: 0 // unknown at this point }); bytes memory pubData = Operations.writeFullExitPubdata(op); addPriorityRequest(Operations.OpType.FullExit, pubData); // User must fill storage slot of balancesToWithdraw(msg.sender, tokenId) with nonzero value // In this case operator should just overwrite this slot during confirming withdrawal bytes22 packedBalanceKey = packAddressAndTokenId(msg.sender, tokenId); balancesToWithdraw[packedBalanceKey].gasReserveValue = 0xff; } /// @notice Commit block - collect onchain operations, create its commitment, emit BlockCommit event /// @param _blockNumber Block number /// @param _feeAccount Account to collect fees /// @param _newBlockInfo New state of the block. (first element is the account tree root hash, rest of the array is reserved for the future) /// @param _publicData Operations pubdata /// @param _ethWitness Data passed to ethereum outside pubdata of the circuit. /// @param _ethWitnessSizes Amount of eth witness bytes for the corresponding operation. function commitBlock( uint32 _blockNumber, uint32 _feeAccount, bytes32[] calldata _newBlockInfo, bytes calldata _publicData, bytes calldata _ethWitness, uint32[] calldata _ethWitnessSizes ) external nonReentrant { requireActive(); require(_blockNumber == totalBlocksCommitted + 1, "fck11"); // only commit next block governance.requireActiveValidator(msg.sender); require(_newBlockInfo.length == 1, "fck13"); // This version of the contract expects only account tree root hash bytes memory publicData = _publicData; // Unpack onchain operations and store them. // Get priority operations number for this block. uint64 prevTotalCommittedPriorityRequests = totalCommittedPriorityRequests; bytes32 withdrawalsDataHash = collectOnchainOps(_blockNumber, publicData, _ethWitness, _ethWitnessSizes); uint64 nPriorityRequestProcessed = totalCommittedPriorityRequests - prevTotalCommittedPriorityRequests; createCommittedBlock(_blockNumber, _feeAccount, _newBlockInfo[0], publicData, withdrawalsDataHash, nPriorityRequestProcessed); totalBlocksCommitted++; emit BlockCommit(_blockNumber); } /// @notice Block verification. /// @notice Verify proof -> process onchain withdrawals (accrue balances from withdrawals) -> remove priority requests /// @param _blockNumber Block number /// @param _proof Block proof /// @param _withdrawalsData Block withdrawals data function verifyBlock(uint32 _blockNumber, uint256[] calldata _proof, bytes calldata _withdrawalsData) external nonReentrant { requireActive(); require(_blockNumber == totalBlocksVerified + 1, "fvk11"); // only verify next block governance.requireActiveValidator(msg.sender); require(verifier.verifyBlockProof(_proof, blocks[_blockNumber].commitment, blocks[_blockNumber].chunks), "fvk13"); // proof verification failed processOnchainWithdrawals(_withdrawalsData, blocks[_blockNumber].withdrawalsDataHash); deleteRequests( blocks[_blockNumber].priorityOperations ); totalBlocksVerified += 1; emit BlockVerification(_blockNumber); } /// @notice Reverts unverified blocks /// @param _maxBlocksToRevert the maximum number blocks that will be reverted (use if can't revert all blocks because of gas limit). function revertBlocks(uint32 _maxBlocksToRevert) external nonReentrant { require(isBlockCommitmentExpired(), "rbs11"); // trying to revert non-expired blocks. governance.requireActiveValidator(msg.sender); uint32 blocksCommited = totalBlocksCommitted; uint32 blocksToRevert = Utils.minU32(_maxBlocksToRevert, blocksCommited - totalBlocksVerified); uint64 revertedPriorityRequests = 0; for (uint32 i = totalBlocksCommitted - blocksToRevert + 1; i <= blocksCommited; i++) { Block memory revertedBlock = blocks[i]; require(revertedBlock.committedAtBlock > 0, "frk11"); // block not found revertedPriorityRequests += revertedBlock.priorityOperations; delete blocks[i]; } blocksCommited -= blocksToRevert; totalBlocksCommitted -= blocksToRevert; totalCommittedPriorityRequests -= revertedPriorityRequests; emit BlocksRevert(totalBlocksVerified, blocksCommited); } /// @notice Checks if Exodus mode must be entered. If true - enters exodus mode and emits ExodusMode event. /// @dev Exodus mode must be entered in case of current ethereum block number is higher than the oldest /// @dev of existed priority requests expiration block number. /// @return bool flag that is true if the Exodus mode must be entered. function triggerExodusIfNeeded() external returns (bool) { bool trigger = block.number >= priorityRequests[firstPriorityRequestId].expirationBlock && priorityRequests[firstPriorityRequestId].expirationBlock != 0; if (trigger) { if (!exodusMode) { exodusMode = true; emit ExodusMode(); } return true; } else { return false; } } /// @notice Withdraws token from Franklin to root chain in case of exodus mode. User must provide proof that he owns funds /// @param _accountId Id of the account in the tree /// @param _proof Proof /// @param _tokenId Verified token id /// @param _amount Amount for owner (must be total amount, not part of it) function exit(uint32 _accountId, uint16 _tokenId, uint128 _amount, uint256[] calldata _proof) external nonReentrant { bytes22 packedBalanceKey = packAddressAndTokenId(msg.sender, _tokenId); require(exodusMode, "fet11"); // must be in exodus mode require(!exited[_accountId][_tokenId], "fet12"); // already exited require(verifier.verifyExitProof(blocks[totalBlocksVerified].stateRoot, _accountId, msg.sender, _tokenId, _amount, _proof), "fet13"); // verification failed uint128 balance = balancesToWithdraw[packedBalanceKey].balanceToWithdraw; balancesToWithdraw[packedBalanceKey].balanceToWithdraw = balance.add(_amount); exited[_accountId][_tokenId] = true; } function setAuthPubkeyHash(bytes calldata _pubkey_hash, uint32 _nonce) external nonReentrant { require(_pubkey_hash.length == PUBKEY_HASH_BYTES, "ahf10"); // PubKeyHash should be 20 bytes. require(authFacts[msg.sender][_nonce] == bytes32(0), "ahf11"); // auth fact for nonce should be empty authFacts[msg.sender][_nonce] = keccak256(_pubkey_hash); emit FactAuth(msg.sender, _nonce, _pubkey_hash); } /// @notice Register deposit request - pack pubdata, add priority request and emit OnchainDeposit event /// @param _tokenId Token by id /// @param _amount Token amount /// @param _owner Receiver function registerDeposit( uint16 _tokenId, uint128 _amount, address _owner ) internal { // Priority Queue request Operations.Deposit memory op = Operations.Deposit({ accountId: 0, // unknown at this point owner: _owner, tokenId: _tokenId, amount: _amount }); bytes memory pubData = Operations.writeDepositPubdata(op); addPriorityRequest(Operations.OpType.Deposit, pubData); emit OnchainDeposit( msg.sender, _tokenId, _amount, _owner ); } /// @notice Register withdrawal - update user balance and emit OnchainWithdrawal event /// @param _token - token by id /// @param _amount - token amount /// @param _to - address to withdraw to function registerWithdrawal(uint16 _token, uint128 _amount, address payable _to) internal { bytes22 packedBalanceKey = packAddressAndTokenId(_to, _token); uint128 balance = balancesToWithdraw[packedBalanceKey].balanceToWithdraw; balancesToWithdraw[packedBalanceKey].balanceToWithdraw = balance.sub(_amount); emit OnchainWithdrawal( _to, _token, _amount ); } /// @notice Store committed block structure to the storage. /// @param _nCommittedPriorityRequests - number of priority requests in block function createCommittedBlock( uint32 _blockNumber, uint32 _feeAccount, bytes32 _newRoot, bytes memory _publicData, bytes32 _withdrawalDataHash, uint64 _nCommittedPriorityRequests ) internal { require(_publicData.length % CHUNK_BYTES == 0, "cbb10"); // Public data size is not multiple of CHUNK_BYTES uint32 blockChunks = uint32(_publicData.length / CHUNK_BYTES); require(verifier.isBlockSizeSupported(blockChunks), "ccb11"); // Create block commitment for verification proof bytes32 commitment = createBlockCommitment( _blockNumber, _feeAccount, blocks[_blockNumber - 1].stateRoot, _newRoot, _publicData ); blocks[_blockNumber] = Block( uint32(block.number), // committed at _nCommittedPriorityRequests, // number of priority onchain ops in block blockChunks, _withdrawalDataHash, // hash of onchain withdrawals data (will be used during checking block withdrawal data in verifyBlock function) commitment, // blocks' commitment _newRoot // new root ); } function emitDepositCommitEvent(uint32 _blockNumber, Operations.Deposit memory depositData) internal { emit DepositCommit(_blockNumber, depositData.accountId, depositData.owner, depositData.tokenId, depositData.amount); } function emitFullExitCommitEvent(uint32 _blockNumber, Operations.FullExit memory fullExitData) internal { emit FullExitCommit(_blockNumber, fullExitData.accountId, fullExitData.owner, fullExitData.tokenId, fullExitData.amount); } /// @notice Gets operations packed in bytes array. Unpacks it and stores onchain operations. /// @param _blockNumber Franklin block number /// @param _publicData Operations packed in bytes array /// @param _ethWitness Eth witness that was posted with commit /// @param _ethWitnessSizes Amount of eth witness bytes for the corresponding operation. /// Priority operations must be committed in the same order as they are in the priority queue. function collectOnchainOps(uint32 _blockNumber, bytes memory _publicData, bytes memory _ethWitness, uint32[] memory _ethWitnessSizes) internal returns (bytes32 withdrawalsDataHash) { require(_publicData.length % CHUNK_BYTES == 0, "fcs11"); // pubdata length must be a multiple of CHUNK_BYTES uint64 currentPriorityRequestId = firstPriorityRequestId + totalCommittedPriorityRequests; uint256 pubDataPtr = 0; uint256 pubDataStartPtr = 0; uint256 pubDataEndPtr = 0; assembly { pubDataStartPtr := add(_publicData, 0x20) } pubDataPtr = pubDataStartPtr; pubDataEndPtr = pubDataStartPtr + _publicData.length; uint64 ethWitnessOffset = 0; uint16 processedOperationsRequiringEthWitness = 0; withdrawalsDataHash = EMPTY_STRING_KECCAK; while (pubDataPtr < pubDataEndPtr) { Operations.OpType opType; // read operation type from public data (the first byte per each operation) assembly { opType := shr(0xf8, mload(pubDataPtr)) } // cheap operations processing if (opType == Operations.OpType.Transfer) { pubDataPtr += TRANSFER_BYTES; } else if (opType == Operations.OpType.Noop) { pubDataPtr += NOOP_BYTES; } else if (opType == Operations.OpType.TransferToNew) { pubDataPtr += TRANSFER_TO_NEW_BYTES; } else { // other operations processing // calculation of public data offset uint256 pubdataOffset = pubDataPtr - pubDataStartPtr; if (opType == Operations.OpType.Deposit) { bytes memory pubData = Bytes.slice(_publicData, pubdataOffset + 1, DEPOSIT_BYTES - 1); Operations.Deposit memory depositData = Operations.readDepositPubdata(pubData); emitDepositCommitEvent(_blockNumber, depositData); OnchainOperation memory onchainOp = OnchainOperation( Operations.OpType.Deposit, pubData ); commitNextPriorityOperation(onchainOp, currentPriorityRequestId); currentPriorityRequestId++; pubDataPtr += DEPOSIT_BYTES; } else if (opType == Operations.OpType.PartialExit) { Operations.PartialExit memory data = Operations.readPartialExitPubdata(_publicData, pubdataOffset + 1); bool addToPendingWithdrawalsQueue = true; withdrawalsDataHash = keccak256(abi.encode(withdrawalsDataHash, addToPendingWithdrawalsQueue, data.owner, data.tokenId, data.amount)); pubDataPtr += PARTIAL_EXIT_BYTES; } else if (opType == Operations.OpType.FullExit) { bytes memory pubData = Bytes.slice(_publicData, pubdataOffset + 1, FULL_EXIT_BYTES - 1); Operations.FullExit memory fullExitData = Operations.readFullExitPubdata(pubData); emitFullExitCommitEvent(_blockNumber, fullExitData); bool addToPendingWithdrawalsQueue = false; withdrawalsDataHash = keccak256(abi.encode(withdrawalsDataHash, addToPendingWithdrawalsQueue, fullExitData.owner, fullExitData.tokenId, fullExitData.amount)); OnchainOperation memory onchainOp = OnchainOperation( Operations.OpType.FullExit, pubData ); commitNextPriorityOperation(onchainOp, currentPriorityRequestId); currentPriorityRequestId++; pubDataPtr += FULL_EXIT_BYTES; } else if (opType == Operations.OpType.ChangePubKey) { require(processedOperationsRequiringEthWitness < _ethWitnessSizes.length, "fcs13"); // eth witness data malformed Operations.ChangePubKey memory op = Operations.readChangePubKeyPubdata(_publicData, pubdataOffset + 1); if (_ethWitnessSizes[processedOperationsRequiringEthWitness] != 0) { bytes memory currentEthWitness = Bytes.slice(_ethWitness, ethWitnessOffset, _ethWitnessSizes[processedOperationsRequiringEthWitness]); bool valid = verifyChangePubkeySignature(currentEthWitness, op.pubKeyHash, op.nonce, op.owner, op.accountId); require(valid, "fpp15"); // failed to verify change pubkey hash signature } else { bool valid = authFacts[op.owner][op.nonce] == keccak256(abi.encodePacked(op.pubKeyHash)); require(valid, "fpp16"); // new pub key hash is not authenticated properly } ethWitnessOffset += _ethWitnessSizes[processedOperationsRequiringEthWitness]; processedOperationsRequiringEthWitness++; pubDataPtr += CHANGE_PUBKEY_BYTES; } else { revert("fpp14"); // unsupported op } } } require(pubDataPtr == pubDataEndPtr, "fcs12"); // last chunk exceeds pubdata require(ethWitnessOffset == _ethWitness.length, "fcs14"); // _ethWitness was not used completely require(processedOperationsRequiringEthWitness == _ethWitnessSizes.length, "fcs15"); // _ethWitnessSizes was not used completely require(currentPriorityRequestId <= firstPriorityRequestId + totalOpenPriorityRequests, "fcs16"); // fcs16 - excess priority requests in pubdata totalCommittedPriorityRequests = currentPriorityRequestId - firstPriorityRequestId; } /// @notice Checks that signature is valid for pubkey change message /// @param _signature Signature /// @param _newPkHash New pubkey hash /// @param _nonce Nonce used for message /// @param _ethAddress Account's ethereum address /// @param _accountId Id of zkSync account function verifyChangePubkeySignature(bytes memory _signature, bytes20 _newPkHash, uint32 _nonce, address _ethAddress, uint32 _accountId) internal pure returns (bool) { bytes memory signedMessage = abi.encodePacked( "\x19Ethereum Signed Message:\n152", "Register zkSync pubkey:\n\n", Bytes.bytesToHexASCIIBytes(abi.encodePacked(_newPkHash)), "\n", "nonce: 0x", Bytes.bytesToHexASCIIBytes(Bytes.toBytesFromUInt32(_nonce)), "\n", "account id: 0x", Bytes.bytesToHexASCIIBytes(Bytes.toBytesFromUInt32(_accountId)), "\n\n", "Only sign this message for a trusted client!" ); address recoveredAddress = Utils.recoverAddressFromEthSignature(_signature, signedMessage); return recoveredAddress == _ethAddress; } /// @notice Creates block commitment from its data /// @param _blockNumber Block number /// @param _feeAccount Account to collect fees /// @param _oldRoot Old tree root /// @param _newRoot New tree root /// @param _publicData Operations pubdata /// @return block commitment function createBlockCommitment( uint32 _blockNumber, uint32 _feeAccount, bytes32 _oldRoot, bytes32 _newRoot, bytes memory _publicData ) internal view returns (bytes32 commitment) { bytes32 hash = sha256( abi.encodePacked(uint256(_blockNumber), uint256(_feeAccount)) ); hash = sha256(abi.encodePacked(hash, uint256(_oldRoot))); hash = sha256(abi.encodePacked(hash, uint256(_newRoot))); /// The code below is equivalent to `commitment = sha256(abi.encodePacked(hash, _publicData))` /// We use inline assembly instead of this concise and readable code in order to avoid copying of `_publicData` (which saves ~90 gas per transfer operation). /// Specifically, we perform the following trick: /// First, replace the first 32 bytes of `_publicData` (where normally its length is stored) with the value of `hash`. /// Then, we call `sha256` precompile passing the `_publicData` pointer and the length of the concatenated byte buffer. /// Finally, we put the `_publicData.length` back to its original location (to the first word of `_publicData`). assembly { let hashResult := mload(0x40) let pubDataLen := mload(_publicData) mstore(_publicData, hash) // staticcall to the sha256 precompile at address 0x2 let success := staticcall( gas, 0x2, _publicData, add(pubDataLen, 0x20), hashResult, 0x20 ) mstore(_publicData, pubDataLen) // Use "invalid" to make gas estimation work switch success case 0 { invalid() } commitment := mload(hashResult) } } /// @notice Checks that operation is same as operation in priority queue /// @param _onchainOp The operation /// @param _priorityRequestId Operation's id in priority queue function commitNextPriorityOperation(OnchainOperation memory _onchainOp, uint64 _priorityRequestId) internal view { Operations.OpType priorReqType = priorityRequests[_priorityRequestId].opType; bytes memory priorReqPubdata = priorityRequests[_priorityRequestId].pubData; require(priorReqType == _onchainOp.opType, "nvp12"); // incorrect priority op type if (_onchainOp.opType == Operations.OpType.Deposit) { require(Operations.depositPubdataMatch(priorReqPubdata, _onchainOp.pubData), "vnp13"); } else if (_onchainOp.opType == Operations.OpType.FullExit) { require(Operations.fullExitPubdataMatch(priorReqPubdata, _onchainOp.pubData), "vnp14"); } else { revert("vnp15"); // invalid or non-priority operation } } /// @notice Processes onchain withdrawals. Full exit withdrawals will not be added to pending withdrawals queue /// @dev NOTICE: must process only withdrawals which hash matches with expectedWithdrawalsDataHash. /// @param withdrawalsData Withdrawals data /// @param expectedWithdrawalsDataHash Expected withdrawals data hash function processOnchainWithdrawals(bytes memory withdrawalsData, bytes32 expectedWithdrawalsDataHash) internal { require(withdrawalsData.length % ONCHAIN_WITHDRAWAL_BYTES == 0, "pow11"); // pow11 - withdrawalData length is not multiple of ONCHAIN_WITHDRAWAL_BYTES bytes32 withdrawalsDataHash = EMPTY_STRING_KECCAK; uint offset = 0; uint32 localNumberOfPendingWithdrawals = numberOfPendingWithdrawals; while (offset < withdrawalsData.length) { (bool addToPendingWithdrawalsQueue, address _to, uint16 _tokenId, uint128 _amount) = Operations.readWithdrawalData(withdrawalsData, offset); bytes22 packedBalanceKey = packAddressAndTokenId(_to, _tokenId); uint128 balance = balancesToWithdraw[packedBalanceKey].balanceToWithdraw; // after this all writes to this slot will cost 5k gas balancesToWithdraw[packedBalanceKey] = BalanceToWithdraw({ balanceToWithdraw: balance.add(_amount), gasReserveValue: 0xff }); if (addToPendingWithdrawalsQueue) { pendingWithdrawals[firstPendingWithdrawalIndex + localNumberOfPendingWithdrawals] = PendingWithdrawal(_to, _tokenId); localNumberOfPendingWithdrawals++; } withdrawalsDataHash = keccak256(abi.encode(withdrawalsDataHash, addToPendingWithdrawalsQueue, _to, _tokenId, _amount)); offset += ONCHAIN_WITHDRAWAL_BYTES; } require(withdrawalsDataHash == expectedWithdrawalsDataHash, "pow12"); // pow12 - withdrawals data hash not matches with expected value if (numberOfPendingWithdrawals != localNumberOfPendingWithdrawals) { emit PendingWithdrawalsAdd(firstPendingWithdrawalIndex + numberOfPendingWithdrawals, firstPendingWithdrawalIndex + localNumberOfPendingWithdrawals); } numberOfPendingWithdrawals = localNumberOfPendingWithdrawals; } /// @notice Checks whether oldest unverified block has expired /// @return bool flag that indicates whether oldest unverified block has expired function isBlockCommitmentExpired() internal view returns (bool) { return ( totalBlocksCommitted > totalBlocksVerified && blocks[totalBlocksVerified + 1].committedAtBlock > 0 && block.number > blocks[totalBlocksVerified + 1].committedAtBlock + EXPECT_VERIFICATION_IN ); } /// @notice Checks that current state not is exodus mode function requireActive() internal view { require(!exodusMode, "fre11"); // exodus mode activated } // Priority queue /// @notice Saves priority request in storage /// @dev Calculates expiration block for request, store this request and emit NewPriorityRequest event /// @param _opType Rollup operation type /// @param _pubData Operation pubdata function addPriorityRequest( Operations.OpType _opType, bytes memory _pubData ) internal { // Expiration block is: current block number + priority expiration delta uint256 expirationBlock = block.number + PRIORITY_EXPIRATION; uint64 nextPriorityRequestId = firstPriorityRequestId + totalOpenPriorityRequests; priorityRequests[nextPriorityRequestId] = PriorityOperation({ opType: _opType, pubData: _pubData, expirationBlock: expirationBlock }); emit NewPriorityRequest( msg.sender, nextPriorityRequestId, _opType, _pubData, expirationBlock ); totalOpenPriorityRequests++; } /// @notice Deletes processed priority requests /// @param _number The number of requests function deleteRequests(uint64 _number) internal { require(_number <= totalOpenPriorityRequests, "pcs21"); // number is higher than total priority requests number uint64 numberOfRequestsToClear = Utils.minU64(_number, MAX_PRIORITY_REQUESTS_TO_DELETE_IN_VERIFY); uint64 startIndex = firstPriorityRequestId; for (uint64 i = startIndex; i < startIndex + numberOfRequestsToClear; i++) { delete priorityRequests[i]; } totalOpenPriorityRequests -= _number; firstPriorityRequestId += _number; totalCommittedPriorityRequests -= _number; } }
pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. * * _Since v2.5.0:_ this module is now much more gas efficient, given net gas * metering changes introduced in the Istanbul hardfork. */ contract ReentrancyGuard { /// Address of lock flag variable. /// Flag is placed at random memory location to not interfere with Storage contract. uint constant private LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4; // keccak256("ReentrancyGuard") - 1; function initializeReentrancyGuard () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. assembly { sstore(LOCK_FLAG_ADDRESS, 1) } } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { bool notEntered; assembly { notEntered := sload(LOCK_FLAG_ADDRESS) } // On the first call to nonReentrant, _notEntered will be true require(notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail assembly { sstore(LOCK_FLAG_ADDRESS, 0) } _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) assembly { sstore(LOCK_FLAG_ADDRESS, 1) } } }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMathUInt128 { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint128 a, uint128 b) internal pure returns (uint128) { uint128 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint128 a, uint128 b) internal pure returns (uint128) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint128 a, uint128 b, string memory errorMessage) internal pure returns (uint128) { require(b <= a, errorMessage); uint128 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint128 a, uint128 b) internal pure returns (uint128) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint128 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint128 a, uint128 b) internal pure returns (uint128) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint128 a, uint128 b, string memory errorMessage) internal pure returns (uint128) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint128 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint128 a, uint128 b) internal pure returns (uint128) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint128 a, uint128 b, string memory errorMessage) internal pure returns (uint128) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's uintXX casting operators with added overflow * checks. * * Downcasting from uint256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} to extend it to smaller types, by performing * all math on `uint256` and then downcasting. * * _Available since v2.5.0._ */ library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } }
pragma solidity ^0.5.0; import "./IERC20.sol"; import "./Bytes.sol"; library Utils { /// @notice Returns lesser of two values function minU32(uint32 a, uint32 b) internal pure returns (uint32) { return a < b ? a : b; } /// @notice Returns lesser of two values function minU64(uint64 a, uint64 b) internal pure returns (uint64) { return a < b ? a : b; } /// @notice Sends tokens /// @dev NOTE: this function handles tokens that have transfer function not strictly compatible with ERC20 standard /// @dev NOTE: call `transfer` to this token may return (bool) or nothing /// @param _token Token address /// @param _to Address of recipient /// @param _amount Amount of tokens to transfer /// @return bool flag indicating that transfer is successful function sendERC20(IERC20 _token, address _to, uint256 _amount) internal returns (bool) { (bool callSuccess, bytes memory callReturnValueEncoded) = address(_token).call( abi.encodeWithSignature("transfer(address,uint256)", _to, _amount) ); // `transfer` method may return (bool) or nothing. bool returnedSuccess = callReturnValueEncoded.length == 0 || abi.decode(callReturnValueEncoded, (bool)); return callSuccess && returnedSuccess; } /// @notice Transfers token from one address to another /// @dev NOTE: this function handles tokens that have transfer function not strictly compatible with ERC20 standard /// @dev NOTE: call `transferFrom` to this token may return (bool) or nothing /// @param _token Token address /// @param _from Address of sender /// @param _to Address of recipient /// @param _amount Amount of tokens to transfer /// @return bool flag indicating that transfer is successful function transferFromERC20(IERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) { (bool callSuccess, bytes memory callReturnValueEncoded) = address(_token).call( abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _amount) ); // `transferFrom` method may return (bool) or nothing. bool returnedSuccess = callReturnValueEncoded.length == 0 || abi.decode(callReturnValueEncoded, (bool)); return callSuccess && returnedSuccess; } /// @notice Sends ETH /// @param _to Address of recipient /// @param _amount Amount of tokens to transfer /// @return bool flag indicating that transfer is successful function sendETHNoRevert(address payable _to, uint256 _amount) internal returns (bool) { // TODO: Use constant from Config uint256 ETH_WITHDRAWAL_GAS_LIMIT = 10000; (bool callSuccess, ) = _to.call.gas(ETH_WITHDRAWAL_GAS_LIMIT).value(_amount)(""); return callSuccess; } /// @notice Recovers signer's address from ethereum signature for given message /// @param _signature 65 bytes concatenated. R (32) + S (32) + V (1) /// @param _message signed message. /// @return address of the signer function recoverAddressFromEthSignature(bytes memory _signature, bytes memory _message) internal pure returns (address) { require(_signature.length == 65, "ves10"); // incorrect signature length bytes32 signR; bytes32 signS; uint offset = 0; (offset, signR) = Bytes.readBytes32(_signature, offset); (offset, signS) = Bytes.readBytes32(_signature, offset); uint8 signV = uint8(_signature[offset]); return ecrecover(keccak256(_message), signV, signR, signS); } }
pragma solidity ^0.5.0; import "./IERC20.sol"; import "./Governance.sol"; import "./Verifier.sol"; import "./Operations.sol"; /// @title zkSync storage contract /// @author Matter Labs contract Storage { /// @notice Flag indicates that upgrade preparation status is active /// @dev Will store false in case of not active upgrade mode bool public upgradePreparationActive; /// @notice Upgrade preparation activation timestamp (as seconds since unix epoch) /// @dev Will be equal to zero in case of not active upgrade mode uint public upgradePreparationActivationTime; /// @notice Verifier contract. Used to verify block proof and exit proof Verifier internal verifier; /// @notice Governance contract. Contains the governor (the owner) of whole system, validators list, possible tokens list Governance internal governance; struct BalanceToWithdraw { uint128 balanceToWithdraw; uint8 gasReserveValue; // gives user opportunity to fill storage slot with nonzero value } /// @notice Root-chain balances (per owner and token id, see packAddressAndTokenId) to withdraw mapping(bytes22 => BalanceToWithdraw) public balancesToWithdraw; /// @notice verified withdrawal pending to be executed. struct PendingWithdrawal { address to; uint16 tokenId; } /// @notice Verified but not executed withdrawals for addresses stored in here (key is pendingWithdrawal's index in pending withdrawals queue) mapping(uint32 => PendingWithdrawal) public pendingWithdrawals; uint32 public firstPendingWithdrawalIndex; uint32 public numberOfPendingWithdrawals; /// @notice Total number of verified blocks i.e. blocks[totalBlocksVerified] points at the latest verified block (block 0 is genesis) uint32 public totalBlocksVerified; /// @notice Total number of committed blocks i.e. blocks[totalBlocksCommitted] points at the latest committed block uint32 public totalBlocksCommitted; /// @notice Rollup block data (once per block) /// @member validator Block producer /// @member committedAtBlock ETH block number at which this block was committed /// @member cumulativeOnchainOperations Total number of operations in this and all previous blocks /// @member priorityOperations Total number of priority operations for this block /// @member commitment Hash of the block circuit commitment /// @member stateRoot New tree root hash /// /// Consider memory alignment when changing field order: https://solidity.readthedocs.io/en/v0.4.21/miscellaneous.html struct Block { uint32 committedAtBlock; uint64 priorityOperations; uint32 chunks; bytes32 withdrawalsDataHash; /// can be restricted to 16 bytes to reduce number of required storage slots bytes32 commitment; bytes32 stateRoot; } /// @notice Blocks by Franklin block id mapping(uint32 => Block) public blocks; /// @notice Onchain operations - operations processed inside rollup blocks /// @member opType Onchain operation type /// @member amount Amount used in the operation /// @member pubData Operation pubdata struct OnchainOperation { Operations.OpType opType; bytes pubData; } /// @notice Flag indicates that a user has exited certain token balance (per account id and tokenId) mapping(uint32 => mapping(uint16 => bool)) public exited; /// @notice Flag indicates that exodus (mass exit) mode is triggered /// @notice Once it was raised, it can not be cleared again, and all users must exit bool public exodusMode; /// @notice User authenticated fact hashes for some nonce. mapping(address => mapping(uint32 => bytes32)) public authFacts; /// @notice Priority Operation container /// @member opType Priority operation type /// @member pubData Priority operation public data /// @member expirationBlock Expiration block number (ETH block) for this request (must be satisfied before) struct PriorityOperation { Operations.OpType opType; bytes pubData; uint256 expirationBlock; } /// @notice Priority Requests mapping (request id - operation) /// @dev Contains op type, pubdata and expiration block of unsatisfied requests. /// @dev Numbers are in order of requests receiving mapping(uint64 => PriorityOperation) public priorityRequests; /// @notice First open priority request id uint64 public firstPriorityRequestId; /// @notice Total number of requests uint64 public totalOpenPriorityRequests; /// @notice Total number of committed requests. /// @dev Used in checks: if the request matches the operation on Rollup contract and if provided number of requests is not too big uint64 public totalCommittedPriorityRequests; /// @notice Packs address and token id into single word to use as a key in balances mapping function packAddressAndTokenId(address _address, uint16 _tokenId) internal pure returns (bytes22) { return bytes22((uint176(_address) | (uint176(_tokenId) << 160))); } /// @notice Gets value from balancesToWithdraw function getBalanceToWithdraw(address _address, uint16 _tokenId) public view returns (uint128) { return balancesToWithdraw[packAddressAndTokenId(_address, _tokenId)].balanceToWithdraw; } }
pragma solidity ^0.5.0; /// @title zkSync configuration constants /// @author Matter Labs contract Config { /// @notice ERC20 token withdrawal gas limit, used only for complete withdrawals uint256 constant ERC20_WITHDRAWAL_GAS_LIMIT = 250000; /// @notice ETH token withdrawal gas limit, used only for complete withdrawals uint256 constant ETH_WITHDRAWAL_GAS_LIMIT = 10000; /// @notice Bytes in one chunk uint8 constant CHUNK_BYTES = 9; /// @notice zkSync address length uint8 constant ADDRESS_BYTES = 20; uint8 constant PUBKEY_HASH_BYTES = 20; /// @notice Public key bytes length uint8 constant PUBKEY_BYTES = 32; /// @notice Ethereum signature r/s bytes length uint8 constant ETH_SIGN_RS_BYTES = 32; /// @notice Success flag bytes length uint8 constant SUCCESS_FLAG_BYTES = 1; /// @notice Max amount of tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0) uint16 constant MAX_AMOUNT_OF_REGISTERED_TOKENS = 128 - 1; /// @notice Max account id that could be registered in the network uint32 constant MAX_ACCOUNT_ID = (2 ** 24) - 1; /// @notice Expected average period of block creation uint256 constant BLOCK_PERIOD = 15 seconds; /// @notice ETH blocks verification expectation /// Blocks can be reverted if they are not verified for at least EXPECT_VERIFICATION_IN. /// If set to 0 validator can revert blocks at any time. uint256 constant EXPECT_VERIFICATION_IN = 0 hours / BLOCK_PERIOD; uint256 constant NOOP_BYTES = 1 * CHUNK_BYTES; uint256 constant DEPOSIT_BYTES = 6 * CHUNK_BYTES; uint256 constant TRANSFER_TO_NEW_BYTES = 6 * CHUNK_BYTES; uint256 constant PARTIAL_EXIT_BYTES = 6 * CHUNK_BYTES; uint256 constant TRANSFER_BYTES = 2 * CHUNK_BYTES; /// @notice Full exit operation length uint256 constant FULL_EXIT_BYTES = 6 * CHUNK_BYTES; /// @notice OnchainWithdrawal data length uint256 constant ONCHAIN_WITHDRAWAL_BYTES = 1 + 20 + 2 + 16; // (uint8 addToPendingWithdrawalsQueue, address _to, uint16 _tokenId, uint128 _amount) /// @notice ChangePubKey operation length uint256 constant CHANGE_PUBKEY_BYTES = 6 * CHUNK_BYTES; /// @notice Expiration delta for priority request to be satisfied (in seconds) /// NOTE: Priority expiration should be > (EXPECT_VERIFICATION_IN * BLOCK_PERIOD), otherwise incorrect block with priority op could not be reverted. uint256 constant PRIORITY_EXPIRATION_PERIOD = 3 days; /// @notice Expiration delta for priority request to be satisfied (in ETH blocks) uint256 constant PRIORITY_EXPIRATION = PRIORITY_EXPIRATION_PERIOD / BLOCK_PERIOD; /// @notice Maximum number of priority request to clear during verifying the block /// @dev Cause deleting storage slots cost 5k gas per each slot it's unprofitable to clear too many slots /// @dev Value based on the assumption of ~750k gas cost of verifying and 5 used storage slots per PriorityOperation structure uint64 constant MAX_PRIORITY_REQUESTS_TO_DELETE_IN_VERIFY = 6; /// @notice Reserved time for users to send full exit priority operation in case of an upgrade (in seconds) uint constant MASS_FULL_EXIT_PERIOD = 3 days; /// @notice Reserved time for users to withdraw funds from full exit priority operation in case of an upgrade (in seconds) uint constant TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT = 2 days; /// @notice Notice period before activation preparation status of upgrade mode (in seconds) // NOTE: we must reserve for users enough time to send full exit operation, wait maximum time for processing this operation and withdraw funds from it. uint constant UPGRADE_NOTICE_PERIOD = MASS_FULL_EXIT_PERIOD + PRIORITY_EXPIRATION_PERIOD + TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT; }
pragma solidity ^0.5.0; import "./Upgradeable.sol"; import "./Operations.sol"; /// @title zkSync events /// @author Matter Labs interface Events { /// @notice Event emitted when a block is committed event BlockCommit(uint32 indexed blockNumber); /// @notice Event emitted when a block is verified event BlockVerification(uint32 indexed blockNumber); /// @notice Event emitted when user send a transaction to withdraw her funds from onchain balance event OnchainWithdrawal( address indexed owner, uint16 indexed tokenId, uint128 amount ); /// @notice Event emitted when user send a transaction to deposit her funds event OnchainDeposit( address indexed sender, uint16 indexed tokenId, uint128 amount, address indexed owner ); /// @notice Event emitted when user sends a authentication fact (e.g. pub-key hash) event FactAuth( address indexed sender, uint32 nonce, bytes fact ); /// @notice Event emitted when blocks are reverted event BlocksRevert( uint32 totalBlocksVerified, uint32 totalBlocksCommitted ); /// @notice Exodus mode entered event event ExodusMode(); /// @notice New priority request event. Emitted when a request is placed into mapping event NewPriorityRequest( address sender, uint64 serialId, Operations.OpType opType, bytes pubData, uint256 expirationBlock ); /// @notice Deposit committed event. event DepositCommit( uint32 indexed zkSyncBlockId, uint32 indexed accountId, address owner, uint16 indexed tokenId, uint128 amount ); /// @notice Full exit committed event. event FullExitCommit( uint32 indexed zkSyncBlockId, uint32 indexed accountId, address owner, uint16 indexed tokenId, uint128 amount ); /// @notice Pending withdrawals index range that were added in the verifyBlock operation. /// NOTE: processed indexes in the queue map are [queueStartIndex, queueEndIndex) event PendingWithdrawalsAdd( uint32 queueStartIndex, uint32 queueEndIndex ); /// @notice Pending withdrawals index range that were executed in the completeWithdrawals operation. /// NOTE: processed indexes in the queue map are [queueStartIndex, queueEndIndex) event PendingWithdrawalsComplete( uint32 queueStartIndex, uint32 queueEndIndex ); } /// @title Upgrade events /// @author Matter Labs interface UpgradeEvents { /// @notice Event emitted when new upgradeable contract is added to upgrade gatekeeper's list of managed contracts event NewUpgradable( uint indexed versionId, address indexed upgradeable ); /// @notice Upgrade mode enter event event NoticePeriodStart( uint indexed versionId, address[] newTargets, uint noticePeriod // notice period (in seconds) ); /// @notice Upgrade mode cancel event event UpgradeCancel( uint indexed versionId ); /// @notice Upgrade mode preparation status event event PreparationStart( uint indexed versionId ); /// @notice Upgrade mode complete event event UpgradeComplete( uint indexed versionId, address[] newTargets ); }
pragma solidity ^0.5.0; // Functions named bytesToX, except bytesToBytes20, where X is some type of size N < 32 (size of one word) // implements the following algorithm: // f(bytes memory input, uint offset) -> X out // where byte representation of out is N bytes from input at the given offset // 1) We compute memory location of the word W such that last N bytes of W is input[offset..offset+N] // W_address = input + 32 (skip stored length of bytes) + offset - (32 - N) == input + offset + N // 2) We load W from memory into out, last N bytes of W are placed into out library Bytes { function toBytesFromUInt16(uint16 self) internal pure returns (bytes memory _bts) { return toBytesFromUIntTruncated(uint(self), 2); } function toBytesFromUInt24(uint24 self) internal pure returns (bytes memory _bts) { return toBytesFromUIntTruncated(uint(self), 3); } function toBytesFromUInt32(uint32 self) internal pure returns (bytes memory _bts) { return toBytesFromUIntTruncated(uint(self), 4); } function toBytesFromUInt128(uint128 self) internal pure returns (bytes memory _bts) { return toBytesFromUIntTruncated(uint(self), 16); } // Copies 'len' lower bytes from 'self' into a new 'bytes memory'. // Returns the newly created 'bytes memory'. The returned bytes will be of length 'len'. function toBytesFromUIntTruncated(uint self, uint8 byteLength) private pure returns (bytes memory bts) { require(byteLength <= 32, "bt211"); bts = new bytes(byteLength); // Even though the bytes will allocate a full word, we don't want // any potential garbage bytes in there. uint data = self << ((32 - byteLength) * 8); assembly { mstore(add(bts, /*BYTES_HEADER_SIZE*/32), data) } } // Copies 'self' into a new 'bytes memory'. // Returns the newly created 'bytes memory'. The returned bytes will be of length '20'. function toBytesFromAddress(address self) internal pure returns (bytes memory bts) { bts = toBytesFromUIntTruncated(uint(self), 20); } // See comment at the top of this file for explanation of how this function works. // NOTE: theoretically possible overflow of (_start + 20) function bytesToAddress(bytes memory self, uint256 _start) internal pure returns (address addr) { uint256 offset = _start + 20; require(self.length >= offset, "bta11"); assembly { addr := mload(add(self, offset)) } } // Reasoning about why this function works is similar to that of other similar functions, except NOTE below. // NOTE: that bytes1..32 is stored in the beginning of the word unlike other primitive types // NOTE: theoretically possible overflow of (_start + 20) function bytesToBytes20(bytes memory self, uint256 _start) internal pure returns (bytes20 r) { require(self.length >= (_start + 20), "btb20"); assembly { r := mload(add(add(self, 0x20), _start)) } } // See comment at the top of this file for explanation of how this function works. // NOTE: theoretically possible overflow of (_start + 0x2) function bytesToUInt16(bytes memory _bytes, uint256 _start) internal pure returns (uint16 r) { uint256 offset = _start + 0x2; require(_bytes.length >= offset, "btu02"); assembly { r := mload(add(_bytes, offset)) } } // See comment at the top of this file for explanation of how this function works. // NOTE: theoretically possible overflow of (_start + 0x3) function bytesToUInt24(bytes memory _bytes, uint256 _start) internal pure returns (uint24 r) { uint256 offset = _start + 0x3; require(_bytes.length >= offset, "btu03"); assembly { r := mload(add(_bytes, offset)) } } // NOTE: theoretically possible overflow of (_start + 0x4) function bytesToUInt32(bytes memory _bytes, uint256 _start) internal pure returns (uint32 r) { uint256 offset = _start + 0x4; require(_bytes.length >= offset, "btu04"); assembly { r := mload(add(_bytes, offset)) } } // NOTE: theoretically possible overflow of (_start + 0x10) function bytesToUInt128(bytes memory _bytes, uint256 _start) internal pure returns (uint128 r) { uint256 offset = _start + 0x10; require(_bytes.length >= offset, "btu16"); assembly { r := mload(add(_bytes, offset)) } } // See comment at the top of this file for explanation of how this function works. // NOTE: theoretically possible overflow of (_start + 0x14) function bytesToUInt160(bytes memory _bytes, uint256 _start) internal pure returns (uint160 r) { uint256 offset = _start + 0x14; require(_bytes.length >= offset, "btu20"); assembly { r := mload(add(_bytes, offset)) } } // NOTE: theoretically possible overflow of (_start + 0x20) function bytesToBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32 r) { uint256 offset = _start + 0x20; require(_bytes.length >= offset, "btb32"); assembly { r := mload(add(_bytes, offset)) } } // Original source code: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol#L228 // Get slice from bytes arrays // Returns the newly created 'bytes memory' // NOTE: theoretically possible overflow of (_start + _length) function slice( bytes memory _bytes, uint _start, uint _length ) internal pure returns (bytes memory) { require(_bytes.length >= (_start + _length), "bse11"); // bytes length is less then start byte + length bytes bytes memory tempBytes = new bytes(_length); if (_length != 0) { // TODO: Review this thoroughly. assembly { let slice_curr := add(tempBytes, 0x20) let slice_end := add(slice_curr, _length) for { let array_current := add(_bytes, add(_start, 0x20)) } lt(slice_curr, slice_end) { slice_curr := add(slice_curr, 0x20) array_current := add(array_current, 0x20) } { mstore(slice_curr, mload(array_current)) } } } return tempBytes; } /// Reads byte stream /// @return new_offset - offset + amount of bytes read /// @return data - actually read data // NOTE: theoretically possible overflow of (_offset + _length) function read(bytes memory _data, uint _offset, uint _length) internal pure returns (uint new_offset, bytes memory data) { data = slice(_data, _offset, _length); new_offset = _offset + _length; } // NOTE: theoretically possible overflow of (_offset + 1) function readBool(bytes memory _data, uint _offset) internal pure returns (uint new_offset, bool r) { new_offset = _offset + 1; r = uint8(_data[_offset]) != 0; } // NOTE: theoretically possible overflow of (_offset + 1) function readUint8(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint8 r) { new_offset = _offset + 1; r = uint8(_data[_offset]); } // NOTE: theoretically possible overflow of (_offset + 2) function readUInt16(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint16 r) { new_offset = _offset + 2; r = bytesToUInt16(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 3) function readUInt24(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint24 r) { new_offset = _offset + 3; r = bytesToUInt24(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 4) function readUInt32(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint32 r) { new_offset = _offset + 4; r = bytesToUInt32(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 16) function readUInt128(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint128 r) { new_offset = _offset + 16; r = bytesToUInt128(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 20) function readUInt160(bytes memory _data, uint _offset) internal pure returns (uint new_offset, uint160 r) { new_offset = _offset + 20; r = bytesToUInt160(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 20) function readAddress(bytes memory _data, uint _offset) internal pure returns (uint new_offset, address r) { new_offset = _offset + 20; r = bytesToAddress(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 20) function readBytes20(bytes memory _data, uint _offset) internal pure returns (uint new_offset, bytes20 r) { new_offset = _offset + 20; r = bytesToBytes20(_data, _offset); } // NOTE: theoretically possible overflow of (_offset + 32) function readBytes32(bytes memory _data, uint _offset) internal pure returns (uint new_offset, bytes32 r) { new_offset = _offset + 32; r = bytesToBytes32(_data, _offset); } // Helper function for hex conversion. function halfByteToHex(byte _byte) internal pure returns (byte _hexByte) { require(uint8(_byte) < 0x10, "hbh11"); // half byte's value is out of 0..15 range. // "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated. return byte (uint8 (0x66656463626139383736353433323130 >> (uint8 (_byte) * 8))); } // Convert bytes to ASCII hex representation function bytesToHexASCIIBytes(bytes memory _input) internal pure returns (bytes memory _output) { bytes memory outStringBytes = new bytes(_input.length * 2); // code in `assembly` construction is equivalent of the next code: // for (uint i = 0; i < _input.length; ++i) { // outStringBytes[i*2] = halfByteToHex(_input[i] >> 4); // outStringBytes[i*2+1] = halfByteToHex(_input[i] & 0x0f); // } assembly { let input_curr := add(_input, 0x20) let input_end := add(input_curr, mload(_input)) for { let out_curr := add(outStringBytes, 0x20) } lt(input_curr, input_end) { input_curr := add(input_curr, 0x01) out_curr := add(out_curr, 0x02) } { let curr_input_byte := shr(0xf8, mload(input_curr)) // here outStringByte from each half of input byte calculates by the next: // // "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated. // outStringByte = byte (uint8 (0x66656463626139383736353433323130 >> (uint8 (_byteHalf) * 8))) mstore(out_curr, shl(0xf8, shr(mul(shr(0x04, curr_input_byte), 0x08), 0x66656463626139383736353433323130))) mstore(add(out_curr, 0x01), shl(0xf8, shr(mul(and(0x0f, curr_input_byte), 0x08), 0x66656463626139383736353433323130))) } } return outStringBytes; } /// Trim bytes into single word function trim(bytes memory _data, uint _new_length) internal pure returns (uint r) { require(_new_length <= 0x20, "trm10"); // new_length is longer than word require(_data.length >= _new_length, "trm11"); // data is to short uint a; assembly { a := mload(add(_data, 0x20)) // load bytes into uint256 } return a >> ((0x20 - _new_length) * 8); } }
pragma solidity ^0.5.0; import "./Bytes.sol"; /// @title zkSync operations tools library Operations { // Circuit ops and their pubdata (chunks * bytes) /// @notice zkSync circuit operation type enum OpType { Noop, Deposit, TransferToNew, PartialExit, _CloseAccount, // used for correct op id offset Transfer, FullExit, ChangePubKey } // Byte lengths uint8 constant TOKEN_BYTES = 2; uint8 constant PUBKEY_BYTES = 32; uint8 constant NONCE_BYTES = 4; uint8 constant PUBKEY_HASH_BYTES = 20; uint8 constant ADDRESS_BYTES = 20; /// @notice Packed fee bytes lengths uint8 constant FEE_BYTES = 2; /// @notice zkSync account id bytes lengths uint8 constant ACCOUNT_ID_BYTES = 4; uint8 constant AMOUNT_BYTES = 16; /// @notice Signature (for example full exit signature) bytes length uint8 constant SIGNATURE_BYTES = 64; // Deposit pubdata struct Deposit { uint32 accountId; uint16 tokenId; uint128 amount; address owner; } uint public constant PACKED_DEPOSIT_PUBDATA_BYTES = ACCOUNT_ID_BYTES + TOKEN_BYTES + AMOUNT_BYTES + ADDRESS_BYTES; /// Deserialize deposit pubdata function readDepositPubdata(bytes memory _data) internal pure returns (Deposit memory parsed) { // NOTE: there is no check that variable sizes are same as constants (i.e. TOKEN_BYTES), fix if possible. uint offset = 0; (offset, parsed.accountId) = Bytes.readUInt32(_data, offset); // accountId (offset, parsed.tokenId) = Bytes.readUInt16(_data, offset); // tokenId (offset, parsed.amount) = Bytes.readUInt128(_data, offset); // amount (offset, parsed.owner) = Bytes.readAddress(_data, offset); // owner require(offset == PACKED_DEPOSIT_PUBDATA_BYTES, "rdp10"); // reading invalid deposit pubdata size } /// Serialize deposit pubdata function writeDepositPubdata(Deposit memory op) internal pure returns (bytes memory buf) { buf = abi.encodePacked( bytes4(0), // accountId (ignored) (update when ACCOUNT_ID_BYTES is changed) op.tokenId, // tokenId op.amount, // amount op.owner // owner ); } /// @notice Check that deposit pubdata from request and block matches function depositPubdataMatch(bytes memory _lhs, bytes memory _rhs) internal pure returns (bool) { // We must ignore `accountId` because it is present in block pubdata but not in priority queue bytes memory lhs_trimmed = Bytes.slice(_lhs, ACCOUNT_ID_BYTES, PACKED_DEPOSIT_PUBDATA_BYTES - ACCOUNT_ID_BYTES); bytes memory rhs_trimmed = Bytes.slice(_rhs, ACCOUNT_ID_BYTES, PACKED_DEPOSIT_PUBDATA_BYTES - ACCOUNT_ID_BYTES); return keccak256(lhs_trimmed) == keccak256(rhs_trimmed); } // FullExit pubdata struct FullExit { uint32 accountId; address owner; uint16 tokenId; uint128 amount; } uint public constant PACKED_FULL_EXIT_PUBDATA_BYTES = ACCOUNT_ID_BYTES + ADDRESS_BYTES + TOKEN_BYTES + AMOUNT_BYTES; function readFullExitPubdata(bytes memory _data) internal pure returns (FullExit memory parsed) { // NOTE: there is no check that variable sizes are same as constants (i.e. TOKEN_BYTES), fix if possible. uint offset = 0; (offset, parsed.accountId) = Bytes.readUInt32(_data, offset); // accountId (offset, parsed.owner) = Bytes.readAddress(_data, offset); // owner (offset, parsed.tokenId) = Bytes.readUInt16(_data, offset); // tokenId (offset, parsed.amount) = Bytes.readUInt128(_data, offset); // amount require(offset == PACKED_FULL_EXIT_PUBDATA_BYTES, "rfp10"); // reading invalid full exit pubdata size } function writeFullExitPubdata(FullExit memory op) internal pure returns (bytes memory buf) { buf = abi.encodePacked( op.accountId, // accountId op.owner, // owner op.tokenId, // tokenId op.amount // amount ); } /// @notice Check that full exit pubdata from request and block matches function fullExitPubdataMatch(bytes memory _lhs, bytes memory _rhs) internal pure returns (bool) { // `amount` is ignored because it is present in block pubdata but not in priority queue uint lhs = Bytes.trim(_lhs, PACKED_FULL_EXIT_PUBDATA_BYTES - AMOUNT_BYTES); uint rhs = Bytes.trim(_rhs, PACKED_FULL_EXIT_PUBDATA_BYTES - AMOUNT_BYTES); return lhs == rhs; } // PartialExit pubdata struct PartialExit { //uint32 accountId; -- present in pubdata, ignored at serialization uint16 tokenId; uint128 amount; //uint16 fee; -- present in pubdata, ignored at serialization address owner; } function readPartialExitPubdata(bytes memory _data, uint _offset) internal pure returns (PartialExit memory parsed) { // NOTE: there is no check that variable sizes are same as constants (i.e. TOKEN_BYTES), fix if possible. uint offset = _offset + ACCOUNT_ID_BYTES; // accountId (ignored) (offset, parsed.tokenId) = Bytes.readUInt16(_data, offset); // tokenId (offset, parsed.amount) = Bytes.readUInt128(_data, offset); // amount offset += FEE_BYTES; // fee (ignored) (offset, parsed.owner) = Bytes.readAddress(_data, offset); // owner } function writePartialExitPubdata(PartialExit memory op) internal pure returns (bytes memory buf) { buf = abi.encodePacked( bytes4(0), // accountId (ignored) (update when ACCOUNT_ID_BYTES is changed) op.tokenId, // tokenId op.amount, // amount bytes2(0), // fee (ignored) (update when FEE_BYTES is changed) op.owner // owner ); } // ChangePubKey struct ChangePubKey { uint32 accountId; bytes20 pubKeyHash; address owner; uint32 nonce; } function readChangePubKeyPubdata(bytes memory _data, uint _offset) internal pure returns (ChangePubKey memory parsed) { uint offset = _offset; (offset, parsed.accountId) = Bytes.readUInt32(_data, offset); // accountId (offset, parsed.pubKeyHash) = Bytes.readBytes20(_data, offset); // pubKeyHash (offset, parsed.owner) = Bytes.readAddress(_data, offset); // owner (offset, parsed.nonce) = Bytes.readUInt32(_data, offset); // nonce } // Withdrawal data process function readWithdrawalData(bytes memory _data, uint _offset) internal pure returns (bool _addToPendingWithdrawalsQueue, address _to, uint16 _tokenId, uint128 _amount) { uint offset = _offset; (offset, _addToPendingWithdrawalsQueue) = Bytes.readBool(_data, offset); (offset, _to) = Bytes.readAddress(_data, offset); (offset, _tokenId) = Bytes.readUInt16(_data, offset); (offset, _amount) = Bytes.readUInt128(_data, offset); } }
pragma solidity ^0.5.0; /// @title Interface of the upgradeable master contract (defines notice period duration and allows finish upgrade during preparation of it) /// @author Matter Labs interface UpgradeableMaster { /// @notice Notice period before activation preparation status of upgrade mode function getNoticePeriod() external returns (uint); /// @notice Notifies contract that notice period started function upgradeNoticePeriodStarted() external; /// @notice Notifies contract that upgrade preparation status is activated function upgradePreparationStarted() external; /// @notice Notifies contract that upgrade canceled function upgradeCanceled() external; /// @notice Notifies contract that upgrade finishes function upgradeFinishes() external; /// @notice Checks that contract is ready for upgrade /// @return bool flag indicating that contract is ready for upgrade function isReadyForUpgrade() external returns (bool); }
pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
pragma solidity ^0.5.0; import "./Config.sol"; /// @title Governance Contract /// @author Matter Labs contract Governance is Config { /// @notice Token added to Franklin net event NewToken( address indexed token, uint16 indexed tokenId ); /// @notice Governor changed event NewGovernor( address newGovernor ); /// @notice Validator's status changed event ValidatorStatusUpdate( address indexed validatorAddress, bool isActive ); /// @notice Address which will exercise governance over the network i.e. add tokens, change validator set, conduct upgrades address public networkGovernor; /// @notice Total number of ERC20 tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0) uint16 public totalTokens; /// @notice List of registered tokens by tokenId mapping(uint16 => address) public tokenAddresses; /// @notice List of registered tokens by address mapping(address => uint16) public tokenIds; /// @notice List of permitted validators mapping(address => bool) public validators; constructor() public {} /// @notice Governance contract initialization. Can be external because Proxy contract intercepts illegal calls of this function. /// @param initializationParameters Encoded representation of initialization parameters: /// _networkGovernor The address of network governor function initialize(bytes calldata initializationParameters) external { address _networkGovernor = abi.decode(initializationParameters, (address)); networkGovernor = _networkGovernor; } /// @notice Governance contract upgrade. Can be external because Proxy contract intercepts illegal calls of this function. /// @param upgradeParameters Encoded representation of upgrade parameters function upgrade(bytes calldata upgradeParameters) external {} /// @notice Change current governor /// @param _newGovernor Address of the new governor function changeGovernor(address _newGovernor) external { requireGovernor(msg.sender); if (networkGovernor != _newGovernor) { networkGovernor = _newGovernor; emit NewGovernor(_newGovernor); } } /// @notice Add token to the list of networks tokens /// @param _token Token address function addToken(address _token) external { requireGovernor(msg.sender); require(tokenIds[_token] == 0, "gan11"); // token exists require(totalTokens < MAX_AMOUNT_OF_REGISTERED_TOKENS, "gan12"); // no free identifiers for tokens totalTokens++; uint16 newTokenId = totalTokens; // it is not `totalTokens - 1` because tokenId = 0 is reserved for eth tokenAddresses[newTokenId] = _token; tokenIds[_token] = newTokenId; emit NewToken(_token, newTokenId); } /// @notice Change validator status (active or not active) /// @param _validator Validator address /// @param _active Active flag function setValidator(address _validator, bool _active) external { requireGovernor(msg.sender); if (validators[_validator] != _active) { validators[_validator] = _active; emit ValidatorStatusUpdate(_validator, _active); } } /// @notice Check if specified address is is governor /// @param _address Address to check function requireGovernor(address _address) public view { require(_address == networkGovernor, "grr11"); // only by governor } /// @notice Checks if validator is active /// @param _address Validator address function requireActiveValidator(address _address) external view { require(validators[_address], "grr21"); // validator is not active } /// @notice Validate token id (must be less than or equal to total tokens amount) /// @param _tokenId Token id /// @return bool flag that indicates if token id is less than or equal to total tokens amount function isValidTokenId(uint16 _tokenId) external view returns (bool) { return _tokenId <= totalTokens; } /// @notice Validate token address /// @param _tokenAddr Token address /// @return tokens id function validateTokenAddress(address _tokenAddr) external view returns (uint16) { uint16 tokenId = tokenIds[_tokenAddr]; require(tokenId != 0, "gvs11"); // 0 is not a valid token return tokenId; } }
pragma solidity ^0.5.0; import "./KeysWithPlonkVerifier.sol"; // Hardcoded constants to avoid accessing store contract Verifier is KeysWithPlonkVerifier { bool constant DUMMY_VERIFIER = false; function initialize(bytes calldata) external { } /// @notice Verifier contract upgrade. Can be external because Proxy contract intercepts illegal calls of this function. /// @param upgradeParameters Encoded representation of upgrade parameters function upgrade(bytes calldata upgradeParameters) external {} function isBlockSizeSupported(uint32 _size) public pure returns (bool) { if (DUMMY_VERIFIER) { return true; } else { return isBlockSizeSupportedInternal(_size); } } function verifyBlockProof( uint256[] calldata _proof, bytes32 _commitment, uint32 _chunks ) external view returns (bool) { if (DUMMY_VERIFIER) { uint oldGasValue = gasleft(); uint tmp; while (gasleft() + 470000 > oldGasValue) { tmp += 1; } return true; } uint256[] memory inputs = new uint256[](1); uint256 mask = (~uint256(0)) >> 3; inputs[0] = uint256(_commitment) & mask; Proof memory proof = deserialize_proof(inputs, _proof); VerificationKey memory vk = getVkBlock(_chunks); require(vk.num_inputs == inputs.length); return verify(proof, vk); } function verifyExitProof( bytes32 _rootHash, uint32 _accountId, address _owner, uint16 _tokenId, uint128 _amount, uint256[] calldata _proof ) external view returns (bool) { bytes32 commitment = sha256(abi.encodePacked(_rootHash, _accountId, _owner, _tokenId, _amount)); uint256[] memory inputs = new uint256[](1); uint256 mask = (~uint256(0)) >> 3; inputs[0] = uint256(commitment) & mask; Proof memory proof = deserialize_proof(inputs, _proof); VerificationKey memory vk = getVkExit(); require(vk.num_inputs == inputs.length); return verify(proof, vk); } }
pragma solidity ^0.5.0; /// @title Interface of the upgradeable contract /// @author Matter Labs interface Upgradeable { /// @notice Upgrades target of upgradeable contract /// @param newTarget New target /// @param newTargetInitializationParameters New target initialization parameters function upgradeTarget(address newTarget, bytes calldata newTargetInitializationParameters) external; }
pragma solidity >=0.5.0 <0.7.0; import "./PlonkCore.sol"; // Hardcoded constants to avoid accessing store contract KeysWithPlonkVerifier is VerifierWithDeserialize { function isBlockSizeSupportedInternal(uint32 _size) internal pure returns (bool) { if (_size == uint32(6)) { return true; } else if (_size == uint32(30)) { return true; } else if (_size == uint32(74)) { return true; } else if (_size == uint32(150)) { return true; } else if (_size == uint32(334)) { return true; } else if (_size == uint32(678)) { return true; } else { return false; } } function getVkBlock(uint32 _chunks) internal pure returns (VerificationKey memory vk) { if (_chunks == uint32(6)) { return getVkBlock6(); } else if (_chunks == uint32(30)) { return getVkBlock30(); } else if (_chunks == uint32(74)) { return getVkBlock74(); } else if (_chunks == uint32(150)) { return getVkBlock150(); } else if (_chunks == uint32(334)) { return getVkBlock334(); } else if (_chunks == uint32(678)) { return getVkBlock678(); } } function getVkBlock6() internal pure returns(VerificationKey memory vk) { vk.domain_size = 2097152; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x032750f8f3c2493d0828c7285d0258e1bdcaa463f4442a52747b5c96639659bb); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x0af568a35305efe9043e30a66e5dbf46219e16a04c7681e0291759114257a9a4, 0x2f35e4f3c521dcd57b7f7cc1548df2a4877eda3d6bf6e47830b7b4c5c78247fa ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x15facf3c62fdc8eb795512905e6756fbdab12f583e92f847fe04ebed1de2b0d9, 0x145ba3f0cd63989a960af1652ace370d8ebae9ccf8462780216625d812100623 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x16d73cc25f2f549e265a5cc871d5350a340e53bfab24118d30d6dd3276b9edf5, 0x1eaf73c1e29c3c3a1702e2375bbee02458c04ae316a603c9509ac9f041bdf67e ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x1f652d9f3fb289cfaff303e35b53e4a1915f2a4f631115e572cfb7dd7e72c9a8, 0x165827a3b413c30dd0e22f10b58e7e64774325e5a213821b953b20d26374b1b1 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x0bb9329eaae8b9979ccf377d312778494b03642e3a1f629f1c4a78dcc759b348, 0x213616224ae180ef4c0010301e037e281689f84d5a9121191957eff36770d526 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x0b478d136e36e67ef049746e8b452afa88c13547cdc341eef713fa7e42f6dcd6, 0x24ef9c90e617fcf3adf998dff4c3238f8fe564ba2da8d15ac3c673d0b16d9bd6 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x09a2c2eeb91944b93013a95e6a63a780e881f101249375d9732ba74c6e54186b, 0x2599f0b0d736bfb3f66cdff99c9f5557f7b82a1fa4029d0d5770d1d194019533 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x199f1e85e793132f1ce19e86967efb1ed606e68b7af0478532fa182163fefa6e, 0x21698d34ed8a715d0086ecab6c1b7fcf4d9a1d7995db29d517031084f2764f95 ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x2389c84e9eaf7f61ad69dd4d19299530c4027f083c6976b5e7cc7f3b7cb57b55, 0x18ee0d9df2d37dda5e85a5764088e89ee8ce32eb7ff45173f0fd102c522d41e1 ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x0f922b9348896b282f12aff0610e39dfa1b6066aaeb5a04f0a5a29d2bb0096c8, 0x1e24a9abbf50778a8d2fd51b37a8eae7836cde2c559740d6ec322c8584274442 ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x2abf5027b8f2a88015873d2b3f97ae97da5f771e800acf89098c5d2228086cf1, 0x1e245aa8ee95af522f204a3e62b82cc62361cf604efac1dd27d49252d1d360c4 ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkBlock30() internal pure returns(VerificationKey memory vk) { vk.domain_size = 4194304; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x18c95f1ae6514e11a1b30fd7923947c5ffcec5347f16e91b4dd654168326bede); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x0dabeb092c842c9877aab11b2242490061cef35c2631e3c383f1ce13c386aaf3, 0x0d34932557f52b84c523dc2474e79eb343f84718d7f20e519a85d10bdb4611eb ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x1c0ea096536ef84a9ee46457b44d4bf9f4b147e9cfd9157f9291d50e59de2512, 0x0b84d8085ef5989f16bc03822d3c3232c2d5df22a0d0a3ac80e6338094909b3b ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x2f6dd701052fc5e95812f5c0da0bf96d5120d7dd5a60bfcc7705aeb212593949, 0x1275cd37c2e0b36830d7a0a3000668064b28c3ff4071614d5992e7a9720fe5a8 ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x1466533cc8c309aca62e5571d170e056b570358ba73bdf921d914a96deef85b1, 0x2f1d1375359dcd5c881b144b64698f15e8227d3f4cb9507f463eecb14173942d ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x0d23903b411253d6e1ea85334f072b75da815db364e96b600003f3f95e3af56c, 0x1130d37d579a1c54aab11ac4e7b7e3fb12e2632682c41f40042cf5e0de646e32 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x130a475c0d12c09535079832afded260636cea2d3acf638b3645f6f18b1defd8, 0x0bf9f1bc4fe3d87628e43c5f87634164bb4a7baedeb578e8b036e72bc5da9038 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x153b616b629aa926262a08d03f3626b2623b1a2aad95dba19d80878fe4d2701a, 0x0ce4c47b8656ea235b974df7b7ec7e3cb62a952704ebcb084ecf521da22c1549 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x0ec6a763e129c400eeaa8bf1d66498ff92286d1bed142f92c932f5ef8cf8c5e3, 0x23a13322172b50c6f624e9c7c924260e2894f84ab928dbb718d0c391b0d43abf ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x246a73716676323f05a5d6137eb98c7f6c8d6ca5f9b63c397271ce820175599e, 0x08ac8dc778bb4998b6d8440fb25463d7810986439aae3f3ddc6e24b0e8a8da2f ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x1174638606b9dc726499db27c34f317db4bd0475678827972fa0da4fab6da1f7, 0x17ceb003ecee92a35fa0ab0989de9d6aafedd821c6d89a0dcded8b096f5b45cb ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x1e7f3863aacbcbb3a43318c621b0abcae89a145bc950dd161fb793fb425ae8cb, 0x2980f2f25fd142c92a55560529f7080e7d55ed8c3cfbb1cd421186c3c3f799e7 ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkBlock74() internal pure returns(VerificationKey memory vk) { vk.domain_size = 8388608; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x1283ba6f4b7b1a76ba2008fe823128bea4adb9269cbfd7c41c223be65bc60863); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x1021fcff6a718826f54ecb1ed30b237b453a8d16a68c5d473ddd1a98ce4d3ffe, 0x1ff632b0f6b06f344c7790260938e21fefeda3c4428e4f3ffce28301de847934 ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x04d1cc2c538b6bc75450f955d21550a948cb38b8aec7c9775795a96aabdb412e, 0x159a35771ccd356ab60f186c9efc8767df370c28e2231ec98e6a674bc95f7612 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x23eeccd095551b0357be6eea8bd9ecabd4a446cb7993c545c7193a2d5bb8657f, 0x00827f6f318c00d7dd2e4a7f3bd94810af906e62eb6844bd110e17ee1ec16f8d ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x1d3bdf4f220278fc7fc8be20ced77647dc38be36f8d9b84e61ddf46e1d593d14, 0x2396a7d5704823939ead4a2bfc6510a7f6470e2a1f447072c9534d62372873f3 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x040be274be43c2d83ae606ec3636fec5c4e7d8c99becf7d33b52adbd0d724b8a, 0x0dec58400efeed3381f71ad1e83582c139a8b728fa9e25ca61e92ef46a09e025 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x0adf559b5270e352f9ab28f549922da636aef8bdba57d67f85434dc56e78c744, 0x2e70f0eda4beb23c457fb274b0aa553b82a94f07c6015ee589481cfa2b3496b1 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x2a8d0d37052e369ff5f5f03b3263deae82cbb555557050c6332488ec2be812ae, 0x2fa789399c26b85d1cf48961bbc44dca2eaf75016720f9e2ba78c1133fadf0bb ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x238b4d00fa2d36e7ab351a32f91a2125622a5bb0ae9af7fdbd9b60cf000e6e91, 0x08ff4499abe98d10e1b6b2fc77fa32333dd5f41cf726cdc71503e0eb8595f4de ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x0cd7e807d8ed7749d99f27e58c871f6feb2036ed6cfcc5a411dc38c7fd307be6, 0x292f00dd8d21c1ce8124bd9f82ab249dbbdb6f45c3696481ae38ee77b22f849b ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x2809b958f09357f3a419ce2245cc5b38e8faecc1ec767d5c868349e588fe5d44, 0x2624d43f0e037f39b0a6fb9f5ae4499849d54c54c0dc3ac8f9c292ac8551e6bc ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x276a858b024e5d82607fac4ee82e97719b25fae9853e2c394236ebc15bdc07ed, 0x11de57c72d139056394203bcac52a132a9d2a012edba72949518e3b986694a8e ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkBlock150() internal pure returns(VerificationKey memory vk) { vk.domain_size = 16777216; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x1951441010b2b95a6e47a6075066a50a036f5ba978c050f2821df86636c0facb); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x2b980886069d87943728e229dd4c9e983a0ce1a319b5ab964fced0bc02e2cf96, 0x176f6a4a15b95fa93edb949de5510ee84c50040e05c5ee1e2b928ec013d2c0da ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x251f54507ddd45d703e5a81b666217e0c3e9231fdbfd382188dafc03268931ce, 0x27d916677565037db4532f2846e10f42cd20499ec54989c42a996c86429786c0 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x00e1d3e897a5f0fea282b120762ed656204c7b05c6716f92047c88991a6776f9, 0x1c83d49caa16f271c2f7250bbc4bba028d4dfd65ed880bc294005253ea7c846a ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x29692360bdfa1c1fde3828cf2b903f6ec3853a1073368db46ab444edf5989cc4, 0x1fb7acc4736be1008144d100c5d447cc55d36c988e6ca974afb2d6039ad19c71 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x2324d61f18207e8135bd2f290e4acd36fc9a977411da6c7e404702d120a4aa4a, 0x12f7ce81186f570986229da30c136c85473d552fe1c214a7eb3b2d305b7b2ae5 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x1d1d3df125d46c06153985ada847816cdcafbf7c8f72d99ae779680bed23e935, 0x1685aa96e1c7d4be8e4993d2b50e8ea76fca9166c223749492f31ebf22915853 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x234111b09c5d38dd313eb1ef80a12cbbdc20bc6066310cd5109f93a4545852da, 0x02441d140d85197884cc9cce20f80670cd94daf51153e61d99381ad85f9d3421 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x02f194881a81ef07ab23dd4552157fb3b83a67df10ffd6916c6ac9f8f5a088ba, 0x0cfb413a65eb6880ffb16277e56b6e1f2474bbb5e2de0a71f06a94118f54bdab ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x1292198bff3ce83fc2410250e998a49ae2d15080555ab268e2714e7cd7e68078, 0x206789f5461397abcaed25062e0881928a9ad05d02f031944dc3a3c3b0955eec ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x2204220f2bfff0ff22d77c9c66c3fdc00b431e92e930dc65ba3a6b91a3350a98, 0x0e46f948f7b703fd7c100575ed47db8d559b93fba62cefaa6f65458249b1e52c ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x2b627b695c64b566e4f4b8f0be454d1de004cce7fa19e6f7fdcb2de2397e67d6, 0x264b1bb8361351d44e34c89162185f489f8e823c649dbbd1f65a1d10e3e196af ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkBlock334() internal pure returns(VerificationKey memory vk) { vk.domain_size = 33554432; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x0d94d63997367c97a8ed16c17adaae39262b9af83acb9e003f94c217303dd160); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x29d9574cd4b98e563db05a14d1ecf9dd7b8e3cd5d901e140d04181c9f53db97e, 0x2ee352008474de4960ca513838e407cd27cbd5c5a8cffd67f67d8a49d4861279 ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x1b1dffc6fde1dd941557412626ddebedd2bcb6f9f8cc9c19bc1f1cca2f9635c7, 0x0f2a6292bb6dacecaa6cb3c71240504f417d8e45f8b345707486afb658fd9d4a ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x0210cb0963ab20ff896d704feb4aadf889ebfe3c3fe1555744ec562fc8bc24b6, 0x156b1a7294328baadcb080d01237d031acf66f63c2d91659d16e1b80cbf3a890 ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x1c3228a3e68fe3ade8c48d516595407359570842d2ab66127b77dc076488be5b, 0x2497ee062b253369cdf12f373e8bd7c9bde6942074b7fea52d1751e9b0de7a24 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x291088d66f3e2f19861c488ab28c619a8fb0ead716cbf1182be4c857a738e37b, 0x010eaf9bab2047a22c90b03c95a8d4f4f45ed0f3410777fc572ca249398017e5 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x18c2e15408ba31f91aec85db8edf934f6ad294b1ef641109f026090c7ce788af, 0x215a339e53528e9c9247987610f93f0854de562fd78ba34aebd8e0e82d5a45a2 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x14a4455b1da8964b29fe75d6b19283f00fd58d3db10afce417cca2a69cd993ae, 0x12d468900ccdc72f0f2e7f41b9a29329c46dd8ba3b0344bf453e2d172a26bc9c ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x04a3e03c4f3e964d756e69a0de2d331c8679cfbdce806849931efe547d493b4b, 0x20871a71fdb6f7e12839bc53ff8b0559d30db42e523d1754121b2ee8f967361b ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x1e8f25a49a753a938da78263003a4dc0e68492940abd9b6294da149c7c927216, 0x0bcd44d08ffc48a289e87b0604c7a16b5e119e3c47b293c3c6c29762a4a5d326 ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x2f3b23257c3437e10631f5dc5da61a622f17dd1516294e013fe484a3adf42462, 0x0b0a21cb5384dc0669f58d54671732385cf96065680255d46861f9a7456267f5 ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x01ec6c4541fb1b4342d219856f1805bf7b94de582b261b096ea2b11b62205633, 0x05a9b67927c90079c45907f9ba67105b47b15dcf480b3bf3514582dc18d357bf ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkBlock678() internal pure returns(VerificationKey memory vk) { vk.domain_size = 67108864; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x1dba8b5bdd64ef6ce29a9039aca3c0e524395c43b9227b96c75090cc6cc7ec97); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x10fac38e585fc150fa6f7470ff88f978bd906bd5454fd067381816c296f89870, 0x1b5424e03353a60155d057d5b0303c2b0d78410cd2f7b0abeb2928b76f808816 ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x0ff633c9b1ed5af3bd5882da5354dfcccd698066d4050ff0c7fd20aa9cd01218, 0x2ab1ee7db81f3e504032e3e36e297c38d15e55171a49cee01ff42d1c954d63a5 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x03aafad8e4a648f6339fc48f229b8672c64dd64e7866263fa8c4e0e716961dea, 0x03bc02bc248d3d3aa917b9eec4a335dc7b1c21ae694c6166911b7246fc95a539 ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x303d788f44e34b61d5671389e8e4a7bfa4f13c02b8c2d345d0eba623e5a6f17f, 0x00a6d7d77556ccff73f1ce9fd0ddce9eb8940731dbdca250fad108ffbccb744d ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x03cacd9bc51ff522d6cc654b17483cf5f044a15eec12f1837fcb9d7f717d5a67, 0x0de3f25d9a6865cd7cc72e529edd802a0cee06d1b45830a294bd6a2240d4bdd0 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x02c54c3ac215172724f0b8138e212e793b28af7ae06b5b53c2f56b52cf32fff6, 0x25093d56e5e5dfad1b1c75b94250fcb4fc430ba214bba40989855d142dcf29b2 ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x222cfccd491605b4b9e15a18b8b0d841c8c5104ed3f96a97d546b0b33cdc67db, 0x0f4ea5620594b707d6d37c4292df6889bd835574abec790b97fd0af88b1d1edd ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x230f568480422793e27ba60859477b363d50ae18c48ace23d6cfcf04abe29dd6, 0x1c6c663735ff13ab1332598f552fc3d01410b18cfa9c6a7bb88df553c79a38b0 ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x0955c07d90bf6d48aa1aec00c060f9aec57f10fa76285684a16cd023192af01c, 0x290ff005de85504f475b596b72bcf1623b71b30534cd360576626d6737f1b763 ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x0cac2104abcde1bf215788c18be6a5c2d73da416f8c5b6e0a2a2222a24deb32f, 0x02dde54e719bc243cda9febc88187582a0983ff1a85d6f888bfe13e4567d9aa5 ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x27fce095aa4c68adbd01f5fd8e64864f6c1625cc577e13a2b80051947b2e8ff6, 0x2583c01600426f9b3873ffef651187c82c0e55a6e5de762355a458fc388f4585 ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkExit() internal pure returns(VerificationKey memory vk) { vk.domain_size = 262144; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x0f60c8fe0414cb9379b2d39267945f6bd60d06a05216231b26a9fcf88ddbfebe); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x117ebe939b7336d17b69b05d5530e30326af39da45a989b078bb3d607707bf3e, 0x18b16095a1c814fe2980170ff34490f1fd454e874caa87df2f739fb9c8d2e902 ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x05ac70a10fc569cc8358bfb708c184446966c6b6a3e0d7c25183ded97f9e7933, 0x0f6152282854e153588d45e784d216a423a624522a687741492ee0b807348e71 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x03cfa9d8f9b40e565435bee3c5b0e855c8612c5a89623557cc30f4588617d7bd, 0x2292bb95c2cc2da55833b403a387e250a9575e32e4ce7d6caa954f12e6ce592a ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x04d04f495c69127b6cc6ecbfd23f77f178e7f4e2d2de3eab3e583a4997744cd9, 0x09dcf5b3db29af5c5eef2759da26d3b6959cb8d80ada9f9b086f7cc39246ad2b ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x01ebab991522d407cfd4e8a1740b64617f0dfca50479bba2707c2ec4159039fc, 0x2c8bd00a44c6120bbf8e57877013f2b5ee36b53eef4ea3b6748fd03568005946 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x07a7124d1fece66bd5428fcce25c22a4a9d5ceaa1e632565d9a062c39f005b5e, 0x2044ae5306f0e114c48142b9b97001d94e3f2280db1b01a1e47ac1cf6bd5f99e ); // we only have access to value of the d(x) witness polynomial on the next // trace step, so we only need one element here and deal with it in other places // by having this in mind vk.next_step_selector_commitments[0] = PairingsBn254.new_g1( 0x1dd1549a639f052c4fbc95b7b7a40acf39928cad715580ba2b38baa116dacd9c, 0x0f8e712990da1ce5195faaf80185ef0d5e430fdec9045a20af758cc8ecdac2e5 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x0026b64066e39a22739be37fed73308ace0a5f38a0e2292dcc2309c818e8c89c, 0x285101acca358974c2c7c9a8a3936e08fbd86779b877b416d9480c91518cb35b ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x2159265ac6fcd4d0257673c3a85c17f4cf3ea13a3c9fb51e404037b13778d56f, 0x25bf73e568ba3406ace2137195bb2176d9de87a48ae42520281aaef2ac2ef937 ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x068f29af99fc8bbf8c00659d34b6d34e4757af6edc10fc7647476cbd0ea9be63, 0x2ef759b20cabf3da83d7f578d9e11ed60f7015440e77359db94475ddb303144d ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x22793db6e98b9e37a1c5d78fcec67a2d8c527d34c5e9c8c1ff15007d30a4c133, 0x1b683d60fd0750b3a45cdee5cbc4057204a02bd428e8071c92fe6694a40a5c1f ); vk.permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } }
pragma solidity >=0.5.0 <0.7.0; library PairingsBn254 { uint256 constant q_mod = 21888242871839275222246405745257275088696311157297823662689037894645226208583; uint256 constant r_mod = 21888242871839275222246405745257275088548364400416034343698204186575808495617; uint256 constant bn254_b_coeff = 3; struct G1Point { uint256 X; uint256 Y; } struct Fr { uint256 value; } function new_fr(uint256 fr) internal pure returns (Fr memory) { require(fr < r_mod); return Fr({value: fr}); } function copy(Fr memory self) internal pure returns (Fr memory n) { n.value = self.value; } function assign(Fr memory self, Fr memory other) internal pure { self.value = other.value; } function inverse(Fr memory fr) internal view returns (Fr memory) { require(fr.value != 0); return pow(fr, r_mod-2); } function add_assign(Fr memory self, Fr memory other) internal pure { self.value = addmod(self.value, other.value, r_mod); } function sub_assign(Fr memory self, Fr memory other) internal pure { self.value = addmod(self.value, r_mod - other.value, r_mod); } function mul_assign(Fr memory self, Fr memory other) internal pure { self.value = mulmod(self.value, other.value, r_mod); } function pow(Fr memory self, uint256 power) internal view returns (Fr memory) { uint256[6] memory input = [32, 32, 32, self.value, power, r_mod]; uint256[1] memory result; bool success; assembly { success := staticcall(gas(), 0x05, input, 0xc0, result, 0x20) } require(success); return Fr({value: result[0]}); } // Encoding of field elements is: X[0] * z + X[1] struct G2Point { uint[2] X; uint[2] Y; } function P1() internal pure returns (G1Point memory) { return G1Point(1, 2); } function new_g1(uint256 x, uint256 y) internal pure returns (G1Point memory) { return G1Point(x, y); } function new_g1_checked(uint256 x, uint256 y) internal pure returns (G1Point memory) { if (x == 0 && y == 0) { // point of infinity is (0,0) return G1Point(x, y); } // check encoding require(x < q_mod); require(y < q_mod); // check on curve uint256 lhs = mulmod(y, y, q_mod); // y^2 uint256 rhs = mulmod(x, x, q_mod); // x^2 rhs = mulmod(rhs, x, q_mod); // x^3 rhs = addmod(rhs, bn254_b_coeff, q_mod); // x^3 + b require(lhs == rhs); return G1Point(x, y); } function new_g2(uint256[2] memory x, uint256[2] memory y) internal pure returns (G2Point memory) { return G2Point(x, y); } function copy_g1(G1Point memory self) internal pure returns (G1Point memory result) { result.X = self.X; result.Y = self.Y; } function P2() internal pure returns (G2Point memory) { // for some reason ethereum expects to have c1*v + c0 form return G2Point( [0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed], [0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa] ); } function negate(G1Point memory self) internal pure { // The prime q in the base field F_q for G1 if (self.Y == 0) { require(self.X == 0); return; } self.Y = q_mod - self.Y; } function point_add(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { point_add_into_dest(p1, p2, r); return r; } function point_add_assign(G1Point memory p1, G1Point memory p2) internal view { point_add_into_dest(p1, p2, p1); } function point_add_into_dest(G1Point memory p1, G1Point memory p2, G1Point memory dest) internal view { if (p2.X == 0 && p2.Y == 0) { // we add zero, nothing happens dest.X = p1.X; dest.Y = p1.Y; return; } else if (p1.X == 0 && p1.Y == 0) { // we add into zero, and we add non-zero point dest.X = p2.X; dest.Y = p2.Y; return; } else { uint256[4] memory input; input[0] = p1.X; input[1] = p1.Y; input[2] = p2.X; input[3] = p2.Y; bool success = false; assembly { success := staticcall(gas(), 6, input, 0x80, dest, 0x40) } require(success); } } function point_sub_assign(G1Point memory p1, G1Point memory p2) internal view { point_sub_into_dest(p1, p2, p1); } function point_sub_into_dest(G1Point memory p1, G1Point memory p2, G1Point memory dest) internal view { if (p2.X == 0 && p2.Y == 0) { // we subtracted zero, nothing happens dest.X = p1.X; dest.Y = p1.Y; return; } else if (p1.X == 0 && p1.Y == 0) { // we subtract from zero, and we subtract non-zero point dest.X = p2.X; dest.Y = q_mod - p2.Y; return; } else { uint256[4] memory input; input[0] = p1.X; input[1] = p1.Y; input[2] = p2.X; input[3] = q_mod - p2.Y; bool success = false; assembly { success := staticcall(gas(), 6, input, 0x80, dest, 0x40) } require(success); } } function point_mul(G1Point memory p, Fr memory s) internal view returns (G1Point memory r) { point_mul_into_dest(p, s, r); return r; } function point_mul_assign(G1Point memory p, Fr memory s) internal view { point_mul_into_dest(p, s, p); } function point_mul_into_dest(G1Point memory p, Fr memory s, G1Point memory dest) internal view { uint[3] memory input; input[0] = p.X; input[1] = p.Y; input[2] = s.value; bool success; assembly { success := staticcall(gas(), 7, input, 0x60, dest, 0x40) } require(success); } function pairing(G1Point[] memory p1, G2Point[] memory p2) internal view returns (bool) { require(p1.length == p2.length); uint elements = p1.length; uint inputSize = elements * 6; uint[] memory input = new uint[](inputSize); for (uint i = 0; i < elements; i++) { input[i * 6 + 0] = p1[i].X; input[i * 6 + 1] = p1[i].Y; input[i * 6 + 2] = p2[i].X[0]; input[i * 6 + 3] = p2[i].X[1]; input[i * 6 + 4] = p2[i].Y[0]; input[i * 6 + 5] = p2[i].Y[1]; } uint[1] memory out; bool success; assembly { success := staticcall(gas(), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) } require(success); return out[0] != 0; } /// Convenience method for a pairing check for two pairs. function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2) internal view returns (bool) { G1Point[] memory p1 = new G1Point[](2); G2Point[] memory p2 = new G2Point[](2); p1[0] = a1; p1[1] = b1; p2[0] = a2; p2[1] = b2; return pairing(p1, p2); } } library TranscriptLibrary { // flip 0xe000000000000000000000000000000000000000000000000000000000000000; uint256 constant FR_MASK = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; uint32 constant DST_0 = 0; uint32 constant DST_1 = 1; uint32 constant DST_CHALLENGE = 2; struct Transcript { bytes32 state_0; bytes32 state_1; uint32 challenge_counter; } function new_transcript() internal pure returns (Transcript memory t) { t.state_0 = bytes32(0); t.state_1 = bytes32(0); t.challenge_counter = 0; } function update_with_u256(Transcript memory self, uint256 value) internal pure { bytes32 old_state_0 = self.state_0; self.state_0 = keccak256(abi.encodePacked(DST_0, old_state_0, self.state_1, value)); self.state_1 = keccak256(abi.encodePacked(DST_1, old_state_0, self.state_1, value)); } function update_with_fr(Transcript memory self, PairingsBn254.Fr memory value) internal pure { update_with_u256(self, value.value); } function update_with_g1(Transcript memory self, PairingsBn254.G1Point memory p) internal pure { update_with_u256(self, p.X); update_with_u256(self, p.Y); } function get_challenge(Transcript memory self) internal pure returns(PairingsBn254.Fr memory challenge) { bytes32 query = keccak256(abi.encodePacked(DST_CHALLENGE, self.state_0, self.state_1, self.challenge_counter)); self.challenge_counter += 1; challenge = PairingsBn254.Fr({value: uint256(query) & FR_MASK}); } } contract Plonk4VerifierWithAccessToDNext { using PairingsBn254 for PairingsBn254.G1Point; using PairingsBn254 for PairingsBn254.G2Point; using PairingsBn254 for PairingsBn254.Fr; using TranscriptLibrary for TranscriptLibrary.Transcript; uint256 constant STATE_WIDTH = 4; uint256 constant ACCESSIBLE_STATE_POLYS_ON_NEXT_STEP = 1; struct VerificationKey { uint256 domain_size; uint256 num_inputs; PairingsBn254.Fr omega; PairingsBn254.G1Point[STATE_WIDTH+2] selector_commitments; // STATE_WIDTH for witness + multiplication + constant PairingsBn254.G1Point[ACCESSIBLE_STATE_POLYS_ON_NEXT_STEP] next_step_selector_commitments; PairingsBn254.G1Point[STATE_WIDTH] permutation_commitments; PairingsBn254.Fr[STATE_WIDTH-1] permutation_non_residues; PairingsBn254.G2Point g2_x; } struct Proof { uint256[] input_values; PairingsBn254.G1Point[STATE_WIDTH] wire_commitments; PairingsBn254.G1Point grand_product_commitment; PairingsBn254.G1Point[STATE_WIDTH] quotient_poly_commitments; PairingsBn254.Fr[STATE_WIDTH] wire_values_at_z; PairingsBn254.Fr[ACCESSIBLE_STATE_POLYS_ON_NEXT_STEP] wire_values_at_z_omega; PairingsBn254.Fr grand_product_at_z_omega; PairingsBn254.Fr quotient_polynomial_at_z; PairingsBn254.Fr linearization_polynomial_at_z; PairingsBn254.Fr[STATE_WIDTH-1] permutation_polynomials_at_z; PairingsBn254.G1Point opening_at_z_proof; PairingsBn254.G1Point opening_at_z_omega_proof; } struct PartialVerifierState { PairingsBn254.Fr alpha; PairingsBn254.Fr beta; PairingsBn254.Fr gamma; PairingsBn254.Fr v; PairingsBn254.Fr u; PairingsBn254.Fr z; PairingsBn254.Fr[] cached_lagrange_evals; } function evaluate_lagrange_poly_out_of_domain( uint256 poly_num, uint256 domain_size, PairingsBn254.Fr memory omega, PairingsBn254.Fr memory at ) internal view returns (PairingsBn254.Fr memory res) { require(poly_num < domain_size); PairingsBn254.Fr memory one = PairingsBn254.new_fr(1); PairingsBn254.Fr memory omega_power = omega.pow(poly_num); res = at.pow(domain_size); res.sub_assign(one); require(res.value != 0); // Vanishing polynomial can not be zero at point `at` res.mul_assign(omega_power); PairingsBn254.Fr memory den = PairingsBn254.copy(at); den.sub_assign(omega_power); den.mul_assign(PairingsBn254.new_fr(domain_size)); den = den.inverse(); res.mul_assign(den); } function batch_evaluate_lagrange_poly_out_of_domain( uint256[] memory poly_nums, uint256 domain_size, PairingsBn254.Fr memory omega, PairingsBn254.Fr memory at ) internal view returns (PairingsBn254.Fr[] memory res) { PairingsBn254.Fr memory one = PairingsBn254.new_fr(1); PairingsBn254.Fr memory tmp_1 = PairingsBn254.new_fr(0); PairingsBn254.Fr memory tmp_2 = PairingsBn254.new_fr(domain_size); PairingsBn254.Fr memory vanishing_at_z = at.pow(domain_size); vanishing_at_z.sub_assign(one); // we can not have random point z be in domain require(vanishing_at_z.value != 0); PairingsBn254.Fr[] memory nums = new PairingsBn254.Fr[](poly_nums.length); PairingsBn254.Fr[] memory dens = new PairingsBn254.Fr[](poly_nums.length); // numerators in a form omega^i * (z^n - 1) // denoms in a form (z - omega^i) * N for (uint i = 0; i < poly_nums.length; i++) { tmp_1 = omega.pow(poly_nums[i]); // power of omega nums[i].assign(vanishing_at_z); nums[i].mul_assign(tmp_1); dens[i].assign(at); // (X - omega^i) * N dens[i].sub_assign(tmp_1); dens[i].mul_assign(tmp_2); // mul by domain size } PairingsBn254.Fr[] memory partial_products = new PairingsBn254.Fr[](poly_nums.length); partial_products[0].assign(PairingsBn254.new_fr(1)); for (uint i = 1; i < dens.length - 1; i++) { partial_products[i].assign(dens[i-1]); partial_products[i].mul_assign(dens[i]); } tmp_2.assign(partial_products[partial_products.length - 1]); tmp_2.mul_assign(dens[dens.length - 1]); tmp_2 = tmp_2.inverse(); // tmp_2 contains a^-1 * b^-1 (with! the last one) for (uint i = dens.length - 1; i < dens.length; i--) { dens[i].assign(tmp_2); // all inversed dens[i].mul_assign(partial_products[i]); // clear lowest terms tmp_2.mul_assign(dens[i]); } for (uint i = 0; i < nums.length; i++) { nums[i].mul_assign(dens[i]); } return nums; } function evaluate_vanishing( uint256 domain_size, PairingsBn254.Fr memory at ) internal view returns (PairingsBn254.Fr memory res) { res = at.pow(domain_size); res.sub_assign(PairingsBn254.new_fr(1)); } function verify_at_z( PartialVerifierState memory state, Proof memory proof, VerificationKey memory vk ) internal view returns (bool) { PairingsBn254.Fr memory lhs = evaluate_vanishing(vk.domain_size, state.z); require(lhs.value != 0); // we can not check a polynomial relationship if point `z` is in the domain lhs.mul_assign(proof.quotient_polynomial_at_z); PairingsBn254.Fr memory quotient_challenge = PairingsBn254.new_fr(1); PairingsBn254.Fr memory rhs = PairingsBn254.copy(proof.linearization_polynomial_at_z); // public inputs PairingsBn254.Fr memory tmp = PairingsBn254.new_fr(0); for (uint256 i = 0; i < proof.input_values.length; i++) { tmp.assign(state.cached_lagrange_evals[i]); tmp.mul_assign(PairingsBn254.new_fr(proof.input_values[i])); rhs.add_assign(tmp); } quotient_challenge.mul_assign(state.alpha); PairingsBn254.Fr memory z_part = PairingsBn254.copy(proof.grand_product_at_z_omega); for (uint256 i = 0; i < proof.permutation_polynomials_at_z.length; i++) { tmp.assign(proof.permutation_polynomials_at_z[i]); tmp.mul_assign(state.beta); tmp.add_assign(state.gamma); tmp.add_assign(proof.wire_values_at_z[i]); z_part.mul_assign(tmp); } tmp.assign(state.gamma); // we need a wire value of the last polynomial in enumeration tmp.add_assign(proof.wire_values_at_z[STATE_WIDTH - 1]); z_part.mul_assign(tmp); z_part.mul_assign(quotient_challenge); rhs.sub_assign(z_part); quotient_challenge.mul_assign(state.alpha); tmp.assign(state.cached_lagrange_evals[0]); tmp.mul_assign(quotient_challenge); rhs.sub_assign(tmp); return lhs.value == rhs.value; } function reconstruct_d( PartialVerifierState memory state, Proof memory proof, VerificationKey memory vk ) internal view returns (PairingsBn254.G1Point memory res) { // we compute what power of v is used as a delinearization factor in batch opening of // commitments. Let's label W(x) = 1 / (x - z) * // [ // t_0(x) + z^n * t_1(x) + z^2n * t_2(x) + z^3n * t_3(x) - t(z) // + v (r(x) - r(z)) // + v^{2..5} * (witness(x) - witness(z)) // + v^(6..8) * (permutation(x) - permutation(z)) // ] // W'(x) = 1 / (x - z*omega) * // [ // + v^9 (z(x) - z(z*omega)) <- we need this power // + v^10 * (d(x) - d(z*omega)) // ] // // we pay a little for a few arithmetic operations to not introduce another constant uint256 power_for_z_omega_opening = 1 + 1 + STATE_WIDTH + STATE_WIDTH - 1; res = PairingsBn254.copy_g1(vk.selector_commitments[STATE_WIDTH + 1]); PairingsBn254.G1Point memory tmp_g1 = PairingsBn254.P1(); PairingsBn254.Fr memory tmp_fr = PairingsBn254.new_fr(0); // addition gates for (uint256 i = 0; i < STATE_WIDTH; i++) { tmp_g1 = vk.selector_commitments[i].point_mul(proof.wire_values_at_z[i]); res.point_add_assign(tmp_g1); } // multiplication gate tmp_fr.assign(proof.wire_values_at_z[0]); tmp_fr.mul_assign(proof.wire_values_at_z[1]); tmp_g1 = vk.selector_commitments[STATE_WIDTH].point_mul(tmp_fr); res.point_add_assign(tmp_g1); // d_next tmp_g1 = vk.next_step_selector_commitments[0].point_mul(proof.wire_values_at_z_omega[0]); res.point_add_assign(tmp_g1); // z * non_res * beta + gamma + a PairingsBn254.Fr memory grand_product_part_at_z = PairingsBn254.copy(state.z); grand_product_part_at_z.mul_assign(state.beta); grand_product_part_at_z.add_assign(proof.wire_values_at_z[0]); grand_product_part_at_z.add_assign(state.gamma); for (uint256 i = 0; i < vk.permutation_non_residues.length; i++) { tmp_fr.assign(state.z); tmp_fr.mul_assign(vk.permutation_non_residues[i]); tmp_fr.mul_assign(state.beta); tmp_fr.add_assign(state.gamma); tmp_fr.add_assign(proof.wire_values_at_z[i+1]); grand_product_part_at_z.mul_assign(tmp_fr); } grand_product_part_at_z.mul_assign(state.alpha); tmp_fr.assign(state.cached_lagrange_evals[0]); tmp_fr.mul_assign(state.alpha); tmp_fr.mul_assign(state.alpha); grand_product_part_at_z.add_assign(tmp_fr); PairingsBn254.Fr memory grand_product_part_at_z_omega = state.v.pow(power_for_z_omega_opening); grand_product_part_at_z_omega.mul_assign(state.u); PairingsBn254.Fr memory last_permutation_part_at_z = PairingsBn254.new_fr(1); for (uint256 i = 0; i < proof.permutation_polynomials_at_z.length; i++) { tmp_fr.assign(state.beta); tmp_fr.mul_assign(proof.permutation_polynomials_at_z[i]); tmp_fr.add_assign(state.gamma); tmp_fr.add_assign(proof.wire_values_at_z[i]); last_permutation_part_at_z.mul_assign(tmp_fr); } last_permutation_part_at_z.mul_assign(state.beta); last_permutation_part_at_z.mul_assign(proof.grand_product_at_z_omega); last_permutation_part_at_z.mul_assign(state.alpha); // add to the linearization tmp_g1 = proof.grand_product_commitment.point_mul(grand_product_part_at_z); tmp_g1.point_sub_assign(vk.permutation_commitments[STATE_WIDTH - 1].point_mul(last_permutation_part_at_z)); res.point_add_assign(tmp_g1); res.point_mul_assign(state.v); res.point_add_assign(proof.grand_product_commitment.point_mul(grand_product_part_at_z_omega)); } function verify_commitments( PartialVerifierState memory state, Proof memory proof, VerificationKey memory vk ) internal view returns (bool) { PairingsBn254.G1Point memory d = reconstruct_d(state, proof, vk); PairingsBn254.Fr memory z_in_domain_size = state.z.pow(vk.domain_size); PairingsBn254.G1Point memory tmp_g1 = PairingsBn254.P1(); PairingsBn254.Fr memory aggregation_challenge = PairingsBn254.new_fr(1); PairingsBn254.G1Point memory commitment_aggregation = PairingsBn254.copy_g1(proof.quotient_poly_commitments[0]); PairingsBn254.Fr memory tmp_fr = PairingsBn254.new_fr(1); for (uint i = 1; i < proof.quotient_poly_commitments.length; i++) { tmp_fr.mul_assign(z_in_domain_size); tmp_g1 = proof.quotient_poly_commitments[i].point_mul(tmp_fr); commitment_aggregation.point_add_assign(tmp_g1); } aggregation_challenge.mul_assign(state.v); commitment_aggregation.point_add_assign(d); for (uint i = 0; i < proof.wire_commitments.length; i++) { aggregation_challenge.mul_assign(state.v); tmp_g1 = proof.wire_commitments[i].point_mul(aggregation_challenge); commitment_aggregation.point_add_assign(tmp_g1); } for (uint i = 0; i < vk.permutation_commitments.length - 1; i++) { aggregation_challenge.mul_assign(state.v); tmp_g1 = vk.permutation_commitments[i].point_mul(aggregation_challenge); commitment_aggregation.point_add_assign(tmp_g1); } aggregation_challenge.mul_assign(state.v); aggregation_challenge.mul_assign(state.v); tmp_fr.assign(aggregation_challenge); tmp_fr.mul_assign(state.u); tmp_g1 = proof.wire_commitments[STATE_WIDTH - 1].point_mul(tmp_fr); commitment_aggregation.point_add_assign(tmp_g1); // collect opening values aggregation_challenge = PairingsBn254.new_fr(1); PairingsBn254.Fr memory aggregated_value = PairingsBn254.copy(proof.quotient_polynomial_at_z); aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.linearization_polynomial_at_z); tmp_fr.mul_assign(aggregation_challenge); aggregated_value.add_assign(tmp_fr); for (uint i = 0; i < proof.wire_values_at_z.length; i++) { aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.wire_values_at_z[i]); tmp_fr.mul_assign(aggregation_challenge); aggregated_value.add_assign(tmp_fr); } for (uint i = 0; i < proof.permutation_polynomials_at_z.length; i++) { aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.permutation_polynomials_at_z[i]); tmp_fr.mul_assign(aggregation_challenge); aggregated_value.add_assign(tmp_fr); } aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.grand_product_at_z_omega); tmp_fr.mul_assign(aggregation_challenge); tmp_fr.mul_assign(state.u); aggregated_value.add_assign(tmp_fr); aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.wire_values_at_z_omega[0]); tmp_fr.mul_assign(aggregation_challenge); tmp_fr.mul_assign(state.u); aggregated_value.add_assign(tmp_fr); commitment_aggregation.point_sub_assign(PairingsBn254.P1().point_mul(aggregated_value)); PairingsBn254.G1Point memory pair_with_generator = commitment_aggregation; pair_with_generator.point_add_assign(proof.opening_at_z_proof.point_mul(state.z)); tmp_fr.assign(state.z); tmp_fr.mul_assign(vk.omega); tmp_fr.mul_assign(state.u); pair_with_generator.point_add_assign(proof.opening_at_z_omega_proof.point_mul(tmp_fr)); PairingsBn254.G1Point memory pair_with_x = proof.opening_at_z_omega_proof.point_mul(state.u); pair_with_x.point_add_assign(proof.opening_at_z_proof); pair_with_x.negate(); return PairingsBn254.pairingProd2(pair_with_generator, PairingsBn254.P2(), pair_with_x, vk.g2_x); } function verify_initial( PartialVerifierState memory state, Proof memory proof, VerificationKey memory vk ) internal view returns (bool) { require(proof.input_values.length == vk.num_inputs); require(vk.num_inputs >= 1); TranscriptLibrary.Transcript memory transcript = TranscriptLibrary.new_transcript(); for (uint256 i = 0; i < vk.num_inputs; i++) { transcript.update_with_u256(proof.input_values[i]); } for (uint256 i = 0; i < proof.wire_commitments.length; i++) { transcript.update_with_g1(proof.wire_commitments[i]); } state.beta = transcript.get_challenge(); state.gamma = transcript.get_challenge(); transcript.update_with_g1(proof.grand_product_commitment); state.alpha = transcript.get_challenge(); for (uint256 i = 0; i < proof.quotient_poly_commitments.length; i++) { transcript.update_with_g1(proof.quotient_poly_commitments[i]); } state.z = transcript.get_challenge(); uint256[] memory lagrange_poly_numbers = new uint256[](vk.num_inputs); for (uint256 i = 0; i < lagrange_poly_numbers.length; i++) { lagrange_poly_numbers[i] = i; } state.cached_lagrange_evals = batch_evaluate_lagrange_poly_out_of_domain( lagrange_poly_numbers, vk.domain_size, vk.omega, state.z ); bool valid = verify_at_z(state, proof, vk); if (valid == false) { return false; } for (uint256 i = 0; i < proof.wire_values_at_z.length; i++) { transcript.update_with_fr(proof.wire_values_at_z[i]); } for (uint256 i = 0; i < proof.wire_values_at_z_omega.length; i++) { transcript.update_with_fr(proof.wire_values_at_z_omega[i]); } for (uint256 i = 0; i < proof.permutation_polynomials_at_z.length; i++) { transcript.update_with_fr(proof.permutation_polynomials_at_z[i]); } transcript.update_with_fr(proof.quotient_polynomial_at_z); transcript.update_with_fr(proof.linearization_polynomial_at_z); state.v = transcript.get_challenge(); transcript.update_with_g1(proof.opening_at_z_proof); transcript.update_with_g1(proof.opening_at_z_omega_proof); state.u = transcript.get_challenge(); return true; } // This verifier is for a PLONK with a state width 4 // and main gate equation // q_a(X) * a(X) + // q_b(X) * b(X) + // q_c(X) * c(X) + // q_d(X) * d(X) + // q_m(X) * a(X) * b(X) + // q_constants(X)+ // q_d_next(X) * d(X*omega) // where q_{}(X) are selectors a, b, c, d - state (witness) polynomials // q_d_next(X) "peeks" into the next row of the trace, so it takes // the same d(X) polynomial, but shifted function verify(Proof memory proof, VerificationKey memory vk) internal view returns (bool) { PartialVerifierState memory state; bool valid = verify_initial(state, proof, vk); if (valid == false) { return false; } valid = verify_commitments(state, proof, vk); return valid; } } contract VerifierWithDeserialize is Plonk4VerifierWithAccessToDNext { uint256 constant SERIALIZED_PROOF_LENGTH = 33; function deserialize_proof( uint256[] memory public_inputs, uint256[] memory serialized_proof ) internal pure returns(Proof memory proof) { require(serialized_proof.length == SERIALIZED_PROOF_LENGTH); proof.input_values = new uint256[](public_inputs.length); for (uint256 i = 0; i < public_inputs.length; i++) { proof.input_values[i] = public_inputs[i]; } uint256 j = 0; for (uint256 i = 0; i < STATE_WIDTH; i++) { proof.wire_commitments[i] = PairingsBn254.new_g1_checked( serialized_proof[j], serialized_proof[j+1] ); j += 2; } proof.grand_product_commitment = PairingsBn254.new_g1_checked( serialized_proof[j], serialized_proof[j+1] ); j += 2; for (uint256 i = 0; i < STATE_WIDTH; i++) { proof.quotient_poly_commitments[i] = PairingsBn254.new_g1_checked( serialized_proof[j], serialized_proof[j+1] ); j += 2; } for (uint256 i = 0; i < STATE_WIDTH; i++) { proof.wire_values_at_z[i] = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; } for (uint256 i = 0; i < proof.wire_values_at_z_omega.length; i++) { proof.wire_values_at_z_omega[i] = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; } proof.grand_product_at_z_omega = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; proof.quotient_polynomial_at_z = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; proof.linearization_polynomial_at_z = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; for (uint256 i = 0; i < proof.permutation_polynomials_at_z.length; i++) { proof.permutation_polynomials_at_z[i] = PairingsBn254.new_fr( serialized_proof[j] ); j += 1; } proof.opening_at_z_proof = PairingsBn254.new_g1_checked( serialized_proof[j], serialized_proof[j+1] ); j += 2; proof.opening_at_z_omega_proof = PairingsBn254.new_g1_checked( serialized_proof[j], serialized_proof[j+1] ); } }
{ "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "optimizer": { "enabled": true, "runs": 200 } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"blockNumber","type":"uint32"}],"name":"BlockCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"blockNumber","type":"uint32"}],"name":"BlockVerification","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"totalBlocksVerified","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"totalBlocksCommitted","type":"uint32"}],"name":"BlocksRevert","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"zkSyncBlockId","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"accountId","type":"uint32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"DepositCommit","type":"event"},{"anonymous":false,"inputs":[],"name":"ExodusMode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint32","name":"nonce","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"fact","type":"bytes"}],"name":"FactAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"zkSyncBlockId","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"accountId","type":"uint32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"FullExitCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint64","name":"serialId","type":"uint64"},{"indexed":false,"internalType":"enum Operations.OpType","name":"opType","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"pubData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"expirationBlock","type":"uint256"}],"name":"NewPriorityRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OnchainDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"OnchainWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"queueStartIndex","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"queueEndIndex","type":"uint32"}],"name":"PendingWithdrawalsAdd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"queueStartIndex","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"queueEndIndex","type":"uint32"}],"name":"PendingWithdrawalsComplete","type":"event"},{"constant":true,"inputs":[],"name":"EMPTY_STRING_KECCAK","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"authFacts","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes22","name":"","type":"bytes22"}],"name":"balancesToWithdraw","outputs":[{"internalType":"uint128","name":"balanceToWithdraw","type":"uint128"},{"internalType":"uint8","name":"gasReserveValue","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"blocks","outputs":[{"internalType":"uint32","name":"committedAtBlock","type":"uint32"},{"internalType":"uint64","name":"priorityOperations","type":"uint64"},{"internalType":"uint32","name":"chunks","type":"uint32"},{"internalType":"bytes32","name":"withdrawalsDataHash","type":"bytes32"},{"internalType":"bytes32","name":"commitment","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint64","name":"_n","type":"uint64"}],"name":"cancelOutstandingDepositsForExodusMode","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_blockNumber","type":"uint32"},{"internalType":"uint32","name":"_feeAccount","type":"uint32"},{"internalType":"bytes32[]","name":"_newBlockInfo","type":"bytes32[]"},{"internalType":"bytes","name":"_publicData","type":"bytes"},{"internalType":"bytes","name":"_ethWitness","type":"bytes"},{"internalType":"uint32[]","name":"_ethWitnessSizes","type":"uint32[]"}],"name":"commitBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_n","type":"uint32"}],"name":"completeWithdrawals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint104","name":"_amount","type":"uint104"},{"internalType":"address","name":"_franklinAddr","type":"address"}],"name":"depositERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_franklinAddr","type":"address"}],"name":"depositETH","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_accountId","type":"uint32"},{"internalType":"uint16","name":"_tokenId","type":"uint16"},{"internalType":"uint128","name":"_amount","type":"uint128"},{"internalType":"uint256[]","name":"_proof","type":"uint256[]"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"exited","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"exodusMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"firstPendingWithdrawalIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"firstPriorityRequestId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_accountId","type":"uint32"},{"internalType":"address","name":"_token","type":"address"}],"name":"fullExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint16","name":"_tokenId","type":"uint16"}],"name":"getBalanceToWithdraw","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"getNoticePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"initializationParameters","type":"bytes"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"isReadyForUpgrade","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"numberOfPendingWithdrawals","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"pendingWithdrawals","outputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"tokenId","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"priorityRequests","outputs":[{"internalType":"enum Operations.OpType","name":"opType","type":"uint8"},{"internalType":"bytes","name":"pubData","type":"bytes"},{"internalType":"uint256","name":"expirationBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_maxBlocksToRevert","type":"uint32"}],"name":"revertBlocks","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_pubkey_hash","type":"bytes"},{"internalType":"uint32","name":"_nonce","type":"uint32"}],"name":"setAuthPubkeyHash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalBlocksCommitted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalBlocksVerified","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalCommittedPriorityRequests","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalOpenPriorityRequests","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"triggerExodusIfNeeded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"upgradeParameters","type":"bytes"}],"name":"upgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"upgradeCanceled","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"upgradeFinishes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"upgradeNoticePeriodStarted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"upgradePreparationActivationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"upgradePreparationActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"upgradePreparationStarted","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint32","name":"_blockNumber","type":"uint32"},{"internalType":"uint256[]","name":"_proof","type":"uint256[]"},{"internalType":"bytes","name":"_withdrawalsData","type":"bytes"}],"name":"verifyBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint128","name":"_amount","type":"uint128"}],"name":"withdrawERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint128","name":"_amount","type":"uint128"},{"internalType":"uint128","name":"_maxAmount","type":"uint128"}],"name":"withdrawERC20Guarded","outputs":[{"internalType":"uint128","name":"withdrawnAmount","type":"uint128"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint128","name":"_amount","type":"uint128"}],"name":"withdrawETH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506159d380620000216000396000f3fe6080604052600436106102385760003560e01c80636b27a0441161012e578063b269b9ae116100ab578063d6973fc61161006f578063d6973fc614610be8578063e17376b514610c89578063fa6b53c314610cdb578063faf4d8cb14610d18578063ffeec23714610d2d57610238565b8063b269b9ae146109d5578063c488a09c14610b49578063c57b22be14610b7c578063c94c5b7c14610b91578063cd24ee0814610bd357610238565b80638ae20dc9116100f25780638ae20dc9146109ff578063922e149214610a3e5780639a83400d14610a53578063a2f9f1ce14610ac3578063a6289e5a14610b1957610238565b80636b27a044146108e457806378b91e70146108f95780637d4907981461090e578063871b8ff1146109d55780638773334c146109ea57610238565b806334f6bb1c116101bc5780634e913cd9116101805780634e913cd914610626578063595a5ebc146107a75780635cd0783e1461082857806367708dae1461089f5780636a387fc9146108b457610238565b806334f6bb1c146104f75780633b154b73146105285780633c06e5141461053d5780633c6461a914610552578063439fab91146105ab57610238565b80632a3174f4116102035780632a3174f4146104215780632b8c062a146104365780632d24006c146104705780632d2da8061461049e5780632f804bd2146104c457610238565b8060e21461023d5780630231c02c1461027e57806321ae605414610356578063253946451461037d578063264c0912146103f8575b600080fd5b34801561024957600080fd5b5061027c6004803603604081101561026057600080fd5b50803563ffffffff1690602001356001600160a01b0316610d42565b005b34801561028a57600080fd5b5061027c600480360360608110156102a157600080fd5b63ffffffff8235169190810190604081016020820135600160201b8111156102c857600080fd5b8201836020820111156102da57600080fd5b803590602001918460208302840111600160201b831117156102fb57600080fd5b919390929091602081019035600160201b81111561031857600080fd5b82018360208201111561032a57600080fd5b803590602001918460018302840111600160201b8311171561034b57600080fd5b509092509050610f36565b34801561036257600080fd5b5061036b61127a565b60408051918252519081900360200190f35b34801561038957600080fd5b5061027c600480360360208110156103a057600080fd5b810190602081018135600160201b8111156103ba57600080fd5b8201836020820111156103cc57600080fd5b803590602001918460018302840111600160201b831117156103ed57600080fd5b50909250905061129e565b34801561040457600080fd5b5061040d6112a2565b604080519115158252519081900360200190f35b34801561042d57600080fd5b5061036b6112ab565b34801561044257600080fd5b5061040d6004803603604081101561045957600080fd5b50803563ffffffff16906020013561ffff166112b3565b34801561047c57600080fd5b506104856112d3565b6040805163ffffffff9092168252519081900360200190f35b61027c600480360360208110156104b457600080fd5b50356001600160a01b03166112e6565b3480156104d057600080fd5b5061027c600480360360208110156104e757600080fd5b50356001600160401b031661137a565b34801561050357600080fd5b5061050c6116a7565b604080516001600160401b039092168252519081900360200190f35b34801561053457600080fd5b5061027c6116bd565b34801561054957600080fd5b506104856116bf565b34801561055e57600080fd5b506105866004803603602081101561057557600080fd5b50356001600160501b0319166116d2565b604080516001600160801b03909316835260ff90911660208301528051918290030190f35b3480156105b757600080fd5b5061027c600480360360208110156105ce57600080fd5b810190602081018135600160201b8111156105e857600080fd5b8201836020820111156105fa57600080fd5b803590602001918460018302840111600160201b8311171561061b57600080fd5b5090925090506116f9565b34801561063257600080fd5b5061027c600480360360c081101561064957600080fd5b63ffffffff8235811692602081013590911691810190606081016040820135600160201b81111561067957600080fd5b82018360208201111561068b57600080fd5b803590602001918460208302840111600160201b831117156106ac57600080fd5b919390929091602081019035600160201b8111156106c957600080fd5b8201836020820111156106db57600080fd5b803590602001918460018302840111600160201b831117156106fc57600080fd5b919390929091602081019035600160201b81111561071957600080fd5b82018360208201111561072b57600080fd5b803590602001918460018302840111600160201b8311171561074c57600080fd5b919390929091602081019035600160201b81111561076957600080fd5b82018360208201111561077b57600080fd5b803590602001918460208302840111600160201b8311171561079c57600080fd5b509092509050611780565b3480156107b357600080fd5b5061027c600480360360408110156107ca57600080fd5b810190602081018135600160201b8111156107e457600080fd5b8201836020820111156107f657600080fd5b803590602001918460018302840111600160201b8311171561081757600080fd5b91935091503563ffffffff16611a88565b34801561083457600080fd5b506108586004803603602081101561084b57600080fd5b503563ffffffff16611c3f565b6040805163ffffffff97881681526001600160401b03909616602087015293909516848401526060840191909152608083015260a082019290925290519081900360c00190f35b3480156108ab57600080fd5b5061050c611c88565b3480156108c057600080fd5b5061027c600480360360208110156108d757600080fd5b503563ffffffff16611c97565b3480156108f057600080fd5b5061040d612077565b34801561090557600080fd5b5061027c612123565b34801561091a57600080fd5b506109416004803603602081101561093157600080fd5b50356001600160401b0316612138565b6040518084600781111561095157fe5b60ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015610998578181015183820152602001610980565b50505050905090810190601f1680156109c55780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b3480156109e157600080fd5b5061027c6121ec565b3480156109f657600080fd5b5061040d6121fb565b348015610a0b57600080fd5b5061036b60048036036040811015610a2257600080fd5b5080356001600160a01b0316906020013563ffffffff16612205565b348015610a4a57600080fd5b5061040d612222565b348015610a5f57600080fd5b50610aa760048036036080811015610a7657600080fd5b506001600160a01b0381358116916020810135909116906001600160801b036040820135811691606001351661222b565b604080516001600160801b039092168252519081900360200190f35b348015610acf57600080fd5b50610af360048036036020811015610ae657600080fd5b503563ffffffff16612415565b604080516001600160a01b03909316835261ffff90911660208301528051918290030190f35b348015610b2557600080fd5b5061027c60048036036020811015610b3c57600080fd5b503563ffffffff1661243d565b348015610b5557600080fd5b5061027c60048036036020811015610b6c57600080fd5b50356001600160801b031661275c565b348015610b8857600080fd5b5061050c612866565b348015610b9d57600080fd5b5061027c60048036036040811015610bb457600080fd5b5080356001600160a01b031690602001356001600160801b031661287c565b348015610bdf57600080fd5b50610485612a3e565b348015610bf457600080fd5b5061027c60048036036080811015610c0b57600080fd5b63ffffffff8235169161ffff602082013516916001600160801b036040830135169190810190608081016060820135600160201b811115610c4b57600080fd5b820183602082011115610c5d57600080fd5b803590602001918460208302840111600160201b83111715610c7e57600080fd5b509092509050612a4a565b348015610c9557600080fd5b5061027c60048036036060811015610cac57600080fd5b506001600160a01b0381358116916cffffffffffffffffffffffffff6020820135169160409091013516612d55565b348015610ce757600080fd5b50610aa760048036036040811015610cfe57600080fd5b5080356001600160a01b0316906020013561ffff16612fd6565b348015610d2457600080fd5b50610485613011565b348015610d3957600080fd5b5061036b613024565b60008051602061592c8339815191525480610d92576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255610dac61302a565b62ffffff63ffffffff84161115610df2576040805162461bcd60e51b8152602060048201526005602482015264666565313160d81b604482015290519081900360640190fd5b60006001600160a01b038316610e0a57506000610e86565b600354604080516375698bb160e11b81526001600160a01b0386811660048301529151919092169163ead31762916024808301926020929190829003018186803b158015610e5757600080fd5b505afa158015610e6b573d6000803e3d6000fd5b505050506040513d6020811015610e8157600080fd5b505190505b610e8e61579c565b60405180608001604052808663ffffffff168152602001336001600160a01b031681526020018361ffff16815260200160006001600160801b031681525090506060610ed98261306a565b9050610ee66006826130ff565b6000610ef233856132c2565b6001600160501b0319166000908152600460205260409020805460ff60801b191660ff60801b1790555050600160008051602061592c833981519152555050505050565b60008051602061592c8339815191525480610f86576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255610fa061302a565b600660089054906101000a900463ffffffff1660010163ffffffff168663ffffffff1614610ffd576040805162461bcd60e51b815260206004820152600560248201526466766b313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b50506002805463ffffffff808b166000908152600760209081526040918290209485015494549151633711baa560e21b815260248101869052600160601b90920490921660448201819052606060048301908152606483018c90526001600160a01b03909416965063dc46ea9495508b948b949093919290918291608401908790870280828437600081840152601f19601f8201169050808301925050509550505050505060206040518083038186803b15801561111957600080fd5b505afa15801561112d573d6000803e3d6000fd5b505050506040513d602081101561114357600080fd5b505161117e576040805162461bcd60e51b815260206004820152600560248201526466766b313360d81b604482015290519081900360640190fd5b6111d383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff8c1681526007602052604090206001015492506132df915050565b63ffffffff861660009081526007602052604090205461120290600160201b90046001600160401b03166135ee565b6006805463ffffffff600160401b80830482166001018216026bffffffff00000000000000001990921691909117909155604051908716907f0cdbd8bd7813095001c5fe7917bd69d834dc01db7c1dfcf52ca135bd2038441390600090a2600160008051602061592c83398151915255505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081565b5050565b60095460ff1681565b620a8c005b90565b600860209081526000928352604080842090915290825290205460ff1681565b600654600160401b900463ffffffff1681565b60008051602061592c8339815191525480611336576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525561135061302a565b611364600061135e3461372e565b84613772565b600160008051602061592c833981519152555050565b60008051602061592c83398151915254806113ca576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525560095460ff1661141b576040805162461bcd60e51b8152602060048201526005602482015264636f65303160d81b604482015290519081900360640190fd5b600c5460009061143b90600160401b90046001600160401b031684613829565b90506000816001600160401b031611611483576040805162461bcd60e51b815260206004820152600560248201526431b7b2981960d91b604482015290519081900360640190fd5b600c546001600160401b03165b600c546001600160401b039081168301811690821610156116475760016001600160401b0382166000908152600b602052604090205460ff1660078111156114d457fe5b1415611607576114e261579c565b6115ab600b6000846001600160401b03166001600160401b031681526020019081526020016000206001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115a15780601f10611576576101008083540402835291602001916115a1565b820191906000526020600020905b81548152906001019060200180831161158457829003601f168201915b5050505050613853565b905060006115c1826060015183602001516132c2565b6040928301516001600160501b031991909116600090815260046020529290922080546001600160801b031981166001600160801b039182169094011692909217909155505b6001600160401b0381166000908152600b60205260408120805460ff191681559061163560018301826157c3565b50600060029190910155600101611490565b50600c805467ffffffffffffffff60401b1967ffffffffffffffff1982166001600160401b039283168501831617908116600160401b91829004831694909403909116029190911790555050600160008051602061592c83398151915255565b600c54600160801b90046001600160401b031681565b565b600654600160201b900463ffffffff1681565b6004602052600090815260409020546001600160801b03811690600160801b900460ff1682565b6117016138fd565b60008060008484606081101561171657600080fd5b50600280546001600160a01b0360208481013582166001600160a01b031993841617909355600380548535909216919092161790556000805260079052604001357f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e2555050505050565b60008051602061592c83398151915254806117d0576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556117ea61302a565b6006600c9054906101000a900463ffffffff1660010163ffffffff168b63ffffffff1614611847576040805162461bcd60e51b815260206004820152600560248201526466636b313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561189257600080fd5b505afa1580156118a6573d6000803e3d6000fd5b5050506001891490506118e8576040805162461bcd60e51b815260206004820152600560248201526466636b313360d81b604482015290519081900360640190fd5b606087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506000600c60109054906101000a90046001600160401b0316905060006119bf8e848a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525061391192505050565b600c54909150600160801b90046001600160401b03168290036119f78f8f8f8f6000816119e857fe5b90506020020135878686613fd4565b6006600c81819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff160217905550508e63ffffffff167f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842460405160405180910390a250505050600160008051602061592c833981519152555050505050505050505050565b60008051602061592c8339815191525480611ad8576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525560148314611b27576040805162461bcd60e51b8152602060048201526005602482015264061686631360dc1b604482015290519081900360640190fd5b336000908152600a6020908152604080832063ffffffff8616845290915290205415611b82576040805162461bcd60e51b8152602060048201526005602482015264616866313160d81b604482015290519081900360640190fd5b83836040518083838082843760408051919093018190038120336000818152600a602090815286822063ffffffff8d16808452908252918790209390935583529082018481529382018a905295507f9ea39b45a0cc96a2139996ec8dd30326216111249750781e563ae27c31ae87669450879350899289925060608201848480828437600083820152604051601f909101601f1916909201829003965090945050505050a2600160008051602061592c8339815191525550505050565b600760205260009081526040902080546001820154600283015460039093015463ffffffff808416946001600160401b03600160201b86041694600160601b9004909116929186565b600c546001600160401b031681565b60008051602061592c8339815191525480611ce7576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556000611d1783600660049054906101000a900463ffffffff166141c3565b60068054600160201b80820463ffffffff908116859003811690910267ffffffff00000000198316178082168501821663ffffffff199091161790925591925016805b82820163ffffffff168163ffffffff16101561200d5763ffffffff8116600090815260056020526040812080546001600160b01b0319811690915561ffff600160a01b820416916001600160a01b0390911690611db782846132c2565b6001600160501b031981166000908152600460205260409020549091506001600160801b03168015611ffe576001600160501b03198216600090815260046020526040812080546001600160801b03808216859003166001600160801b031990911617905561ffff8516611e415783611e39816001600160801b0385166141de565b915050611fbe565b600354604080516310603dad60e01b815261ffff8816600482015290516000926001600160a01b0316916310603dad916024808301926020929190829003018186803b158015611e9057600080fd5b505afa158015611ea4573d6000803e3d6000fd5b505050506040513d6020811015611eba57600080fd5b5051604080516001600160a01b038084166024830152881660448201526001600160801b038616606482018190526084808301919091528251808303909101815260a490910182526020810180516001600160e01b0316639a83400d60e01b1781529151815193945030936203d0909382918083835b60208310611f4f5780518252601f199092019160209182019101611f30565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114611fb2576040519150601f19603f3d011682016040523d82523d6000602084013e611fb7565b606091505b5090925050505b80611ffc576001600160501b03198316600090815260046020526040902080546001600160801b038082168501166001600160801b03199091161790555b505b50505050806001019050611d5a565b5063ffffffff82161561205f576040805163ffffffff808416825284840116602082015281517f9b5478c99b5ca41beec4f6f6084126d6f9e26382d017b4bb67c37c9e8453a313929181900390910190a15b5050600160008051602061592c833981519152555050565b600c546001600160401b03166000908152600b6020526040812060020154819043108015906120c25750600c546001600160401b03166000908152600b602052604090206002015415155b905080156121155760095460ff1661210b576009805460ff191660011790556040517fc71028c67eb0ef128ea270a59a674629e767d51c1af44ed6753fd2fad2c7b67790600090a15b60019150506112b0565b60009150506112b0565b5090565b6000805460ff19166001908117909155429055565b600b602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff9092169492939092908301828280156121dc5780601f106121b1576101008083540402835291602001916121dc565b820191906000526020600020905b8154815290600101906020018083116121bf57829003601f168201915b5050505050908060020154905083565b6000805460ff19168155600155565b60095460ff161590565b600a60209081526000928352604080842090915290825290205481565b60005460ff1681565b6000333014612269576040805162461bcd60e51b8152602060048201526005602482015264077746731360dc1b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038816916370a0823191602480820192602092909190829003018186803b1580156122b357600080fd5b505afa1580156122c7573d6000803e3d6000fd5b505050506040513d60208110156122dd57600080fd5b505190506122f586866001600160801b038716614243565b61232e576040805162461bcd60e51b8152602060048201526005602482015264777467313160d81b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b15801561237857600080fd5b505afa15801561238c573d6000803e3d6000fd5b505050506040513d60208110156123a257600080fd5b5051905060006123b8838363ffffffff61436a16565b9050846001600160801b0316811115612400576040805162461bcd60e51b81526020600482015260056024820152643bba33989960d91b604482015290519081900360640190fd5b6124098161372e565b98975050505050505050565b6005602052600090815260409020546001600160a01b03811690600160a01b900461ffff1682565b60008051602061592c833981519152548061248d576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556124a76143ac565b6124e0576040805162461bcd60e51b8152602060048201526005602482015264726273313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561252b57600080fd5b505afa15801561253f573d6000803e3d6000fd5b505060065463ffffffff600160601b8204811693506000925061256e918691600160401b9091041684036141c3565b600654909150600090600160601b900463ffffffff168290036001015b8363ffffffff168163ffffffff161161269d576125a661580a565b5063ffffffff808216600090815260076020908152604091829020825160c08101845281548086168083526001600160401b03600160201b83041694830194909452600160601b900490941692840192909252600182015460608401526002820154608084015260039091015460a0830152612651576040805162461bcd60e51b815260206004820152600560248201526466726b313160d81b604482015290519081900360640190fd5b60209081015163ffffffff8316600090815260079092526040822080546001600160801b031916815560018082018490556002820184905560039091019290925592909201910161258b565b506006805463ffffffff600160601b808304821686900382160263ffffffff60601b199092169190911791829055600c80546001600160401b03600160801b80830482168790039091160267ffffffffffffffff60801b1990911617905560408051600160401b90930482168352948490039081166020830152845190947f6f3a8259cce1ea2680115053d21c971aa1764295a45850f520525f2bfdf3c9d3928290030190a1505050600160008051602061592c833981519152555050565b60008051602061592c83398151915254806127ac576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556127ca60008333614431565b604051600090339084908381818185875af1925050503d806000811461280c576040519150601f19603f3d011682016040523d82523d6000602084013e612811565b606091505b505090508061284f576040805162461bcd60e51b8152602060048201526005602482015264667765313160d81b604482015290519081900360640190fd5b50600160008051602061592c833981519152555050565b600c54600160401b90046001600160401b031681565b60008051602061592c83398151915254806128cc576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152819055600354604080516375698bb160e11b81526001600160a01b0387811660048301529151919092169163ead31762916024808301926020929190829003018186803b15801561292d57600080fd5b505afa158015612941573d6000803e3d6000fd5b505050506040513d602081101561295757600080fd5b50519050600061296733836132c2565b6001600160501b031981166000908152600460208181526040808420548151639a83400d60e01b81526001600160a01b038c16948101949094523360248501526001600160801b038a8116604486015216606484018190529051949550933092639a83400d92608480830193919282900301818787803b1580156129ea57600080fd5b505af11580156129fe573d6000803e3d6000fd5b505050506040513d6020811015612a1457600080fd5b50519050612a23848233614431565b50505050600160008051602061592c83398151915255505050565b60065463ffffffff1681565b60008051602061592c8339815191525480612a9a576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556000612ab833876132c2565b60095490915060ff16612afa576040805162461bcd60e51b8152602060048201526005602482015264666574313160d81b604482015290519081900360640190fd5b63ffffffff8716600090815260086020908152604080832061ffff8a16845290915290205460ff1615612b5c576040805162461bcd60e51b81526020600482015260056024820152643332ba189960d91b604482015290519081900360640190fd5b60025460065463ffffffff600160401b909104811660009081526007602090815260409182902060030154915163c81a27ad60e01b815260048101838152938c166024820152336044820181905261ffff8c1660648301526001600160801b038b16608483015260c060a4830190815260c483018a90526001600160a01b039096169563c81a27ad958e9492938e938e938e938e93909260e4909101908590850280828437600081840152601f19601f8201169050808301925050509850505050505050505060206040518083038186803b158015612c3a57600080fd5b505afa158015612c4e573d6000803e3d6000fd5b505050506040513d6020811015612c6457600080fd5b5051612c9f576040805162461bcd60e51b8152602060048201526005602482015264666574313360d81b604482015290519081900360640190fd5b6001600160501b031981166000908152600460205260409020546001600160801b0316612cd2818763ffffffff6144f416565b6001600160501b0319909216600090815260046020908152604080832080546001600160801b03969096166001600160801b03199096169590951790945563ffffffff90991681526008895282812061ffff909816815296909752909420805460ff1916600190811790915560008051602061592c833981519152555050505050565b60008051602061592c8339815191525480612da5576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255612dbf61302a565b600354604080516375698bb160e11b81526001600160a01b0387811660048301529151600093929092169163ead3176291602480820192602092909190829003018186803b158015612e1057600080fd5b505afa158015612e24573d6000803e3d6000fd5b505050506040513d6020811015612e3a57600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038816916370a08231916024808301926020929190829003018186803b158015612e8857600080fd5b505afa158015612e9c573d6000803e3d6000fd5b505050506040513d6020811015612eb257600080fd5b50519050612ee2863330612ed46cffffffffffffffffffffffffff8a1661372e565b6001600160801b031661455a565b612f1b576040805162461bcd60e51b8152602060048201526005602482015264333218189960d91b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b158015612f6557600080fd5b505afa158015612f79573d6000803e3d6000fd5b505050506040513d6020811015612f8f57600080fd5b505190506000612fad612fa8838563ffffffff61436a16565b61372e565b9050612fba848288613772565b50505050600160008051602061592c8339815191525550505050565b600060046000612fe685856132c2565b6001600160501b03191681526020810191909152604001600020546001600160801b03169392505050565b600654600160601b900463ffffffff1681565b60015481565b60095460ff16156116bd576040805162461bcd60e51b8152602060048201526005602482015264667265313160d81b604482015290519081900360640190fd5b60608160000151826020015183604001518460600151604051602001808563ffffffff1663ffffffff1660e01b8152600401846001600160a01b03166001600160a01b031660601b81526014018361ffff1661ffff1660f01b8152600201826001600160801b03166001600160801b031660801b81526010019450505050506040516020818303038152906040529050919050565b600c5460408051606081019091524361438001916001600160401b03808216600160401b9092041601908085600781111561313657fe5b8152602080820186905260409182018590526001600160401b0384166000908152600b9091522081518154829060ff1916600183600781111561317557fe5b02179055506020828101518051613192926001850192019061583f565b50604082015181600201559050507fd0943372c08b438a88d4b39d77216901079eda9ca59d45349841c099083b6830338286868660405180866001600160a01b03166001600160a01b03168152602001856001600160401b03166001600160401b0316815260200184600781111561320657fe5b60ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561324d578181015183820152602001613235565b50505050905090810190601f16801561327a5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15050600c805460016001600160401b03600160401b808404821692909201160267ffffffffffffffff60401b199091161790555050565b60a01b61ffff60a01b166001600160a01b03919091161760501b90565b60278251816132ea57fe5b0615613325576040805162461bcd60e51b8152602060048201526005602482015264706f77313160d81b604482015290519081900360640190fd5b6006547fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090600090600160201b900463ffffffff165b8451821015613517576000806000806133748987614687565b9350935093509350600061338884846132c2565b6001600160501b03198116600090815260046020526040908190205481518083019092529192506001600160801b0390911690806133cc838663ffffffff6144f416565b6001600160801b03908116825260ff60209283018190526001600160501b0319861660009081526004845260409020845181549590940151909116600160801b0260ff60801b19939092166001600160801b0319909416939093179190911617905585156134ae576040805180820182526001600160a01b03878116825261ffff878116602080850191825260065463ffffffff9081168e011660009081526005909152949094209251835494516001600160a01b031990951692169190911761ffff60a01b1916600160a01b93909116929092029190911790556001909601955b505060408051602080820199909952941515858201526001600160a01b03909316606085015261ffff90911660808401526001600160801b031660a0808401919091528151808403909101815260c090920190528051930192909220916027919091019061335b565b838314613553576040805162461bcd60e51b81526020600482015260056024820152643837bb989960d91b604482015290519081900360640190fd5b60065463ffffffff828116600160201b90920416146135c3576006546040805163ffffffff808416600160201b9094048116840181168252928401909216602083015280517fc4faeb4e73f28a46e4a5fa2db5b89c39698816488534ab7f0717c46f0852c3669281900390910190a15b6006805463ffffffff909216600160201b0267ffffffff000000001990921691909117905550505050565b600c546001600160401b03600160401b90910481169082161115613641576040805162461bcd60e51b8152602060048201526005602482015264706373323160d81b604482015290519081900360640190fd5b600061364e826006613829565b600c549091506001600160401b0316805b8282016001600160401b0316816001600160401b031610156136bb576001600160401b0381166000908152600b60205260408120805460ff19168155906136a960018301826157c3565b5060006002919091015560010161365f565b5050600c8054600160801b6001600160401b03600160401b808404821687900382160267ffffffffffffffff60401b19909316929092178083168601831667ffffffffffffffff19909116178181048316959095039091160267ffffffffffffffff60801b199093169290921790915550565b6000600160801b821061211f5760405162461bcd60e51b815260040180806020018281038252602781526020018061594c6027913960400191505060405180910390fd5b61377a61579c565b6040518060800160405280600063ffffffff1681526020018561ffff168152602001846001600160801b03168152602001836001600160a01b0316815250905060606137c5826146ce565b90506137d26001826130ff565b604080516001600160801b038616815290516001600160a01b0385169161ffff88169133917fb6866b029f3aa29cd9e2bff8159a8ccaa4389f7a087c710968e0b200c0c73b08919081900360200190a45050505050565b6000816001600160401b0316836001600160401b03161061384a578161384c565b825b9392505050565b61385b61579c565b60006138678382614738565b63ffffffff168352905061387b8382614751565b61ffff16602084015290506138908382614761565b6001600160801b0316604084015290506138aa8382614771565b6001600160a01b031660608401529050602a81146138f7576040805162461bcd60e51b8152602060048201526005602482015264072647031360dc1b604482015290519081900360640190fd5b50919050565b600160008051602061592c83398151915255565b82516000906009900615613954576040805162461bcd60e51b8152602060048201526005602482015264666373313160d81b604482015290519081900360640190fd5b50600c5483517fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470916001600160401b03808216600160801b9092041601906020868101918291908801016000805b82851015613e7557845160f81c60058160078111156139bd57fe5b14156139cf5760129590950194613e6f565b60008160078111156139dd57fe5b14156139ef5760099590950194613e6f565b60028160078111156139fd57fe5b1415613a0f5760369590950194613e6f565b8486036001826007811115613a2057fe5b1415613a93576060613a378d600184016035614781565b9050613a4161579c565b613a4a82613853565b9050613a568f8261482b565b613a5e6158b9565b50604080518082019091526001815260208101839052613a7e818c6148b5565b50506001909801975060369690960195613e6d565b6003826007811115613aa157fe5b1415613b2b57613aaf6158d1565b613abc8d83600101614ab6565b604080820151825160209384015183518086019f909f5260018f8501526001600160a01b0390921660608f015261ffff1660808e01526001600160801b031660a0808e01919091528151808e03909101815260c0909c0190528a519a0199909920985060369690960195613e6d565b6006826007811115613b3957fe5b1415613c37576060613b508d600184016035614781565b9050613b5a61579c565b613b6382614b12565b9050613b6f8f82614bb6565b60008090508b818360200151846040015185606001516040516020018086815260200185151515158152602001846001600160a01b03166001600160a01b031681526020018361ffff1661ffff168152602001826001600160801b03166001600160801b0316815260200195505050505050604051602081830303815290604052805190602001209b50613c016158b9565b50604080518082019091526006815260208101849052613c21818d6148b5565b5050600190990198505060369690960195613e6d565b6007826007811115613c4557fe5b1415613e385789518361ffff1610613c8c576040805162461bcd60e51b8152602060048201526005602482015264666373313360d81b604482015290519081900360640190fd5b613c9461579c565b613ca18d83600101614c40565b90508a8461ffff1681518110613cb357fe5b602002602001015163ffffffff16600014613d5f576060613cfb8d876001600160401b03168e8861ffff1681518110613ce857fe5b602002602001015163ffffffff16614781565b90506000613d1c828460200151856060015186604001518760000151614cb0565b905080613d58576040805162461bcd60e51b8152602060048201526005602482015264667070313560d81b604482015290519081900360640190fd5b5050613dfc565b602080820151604080516001600160601b0319909216828401528051808303601401815260349092018152815191830191909120818401516001600160a01b03166000908152600a8452828120606086015163ffffffff1682529093529120541480613dfa576040805162461bcd60e51b8152602060048201526005602482015264333838189b60d91b604482015290519081900360640190fd5b505b8a8461ffff1681518110613e0c57fe5b602002602001015163ffffffff16850194508380600101945050600960060260ff168801975050613e6d565b6040805162461bcd60e51b8152602060048201526005602482015264199c1c0c4d60da1b604482015290519081900360640190fd5b505b506139a2565b828514613eb1576040805162461bcd60e51b81526020600482015260056024820152643331b9989960d91b604482015290519081900360640190fd5b8851826001600160401b031614613ef7576040805162461bcd60e51b81526020600482015260056024820152641998dccc4d60da1b604482015290519081900360640190fd5b87518161ffff1614613f38576040805162461bcd60e51b8152602060048201526005602482015264666373313560d81b604482015290519081900360640190fd5b600c546001600160401b03808216600160401b90920481169190910181169087161115613f94576040805162461bcd60e51b81526020600482015260056024820152643331b9989b60d91b604482015290519081900360640190fd5b5050600c80546001600160401b03808216909603909516600160801b0267ffffffffffffffff60801b199095169490941790935550919695505050505050565b82516009900615614014576040805162461bcd60e51b8152602060048201526005602482015264063626231360dc1b604482015290519081900360640190fd5b82516002546040805163e54ee6b160e01b815263ffffffff6009909404938416600482015290516001600160a01b039092169163e54ee6b191602480820192602092909190829003018186803b15801561406d57600080fd5b505afa158015614081573d6000803e3d6000fd5b505050506040513d602081101561409757600080fd5b50516140d2576040805162461bcd60e51b8152602060048201526005602482015264636362313160d81b604482015290519081900360640190fd5b63ffffffff6000198801166000908152600760205260408120600301546140fe90899089908989614ecc565b6040805160c0810182524363ffffffff90811682526001600160401b03968716602080840191825296821683850190815260608401998a526080840195865260a084019b8c529c821660009081526007909752929095209051815492519b5163ffffffff19909316908616176bffffffffffffffff000000001916600160201b9b9096169a909a029490941763ffffffff60601b1916600160601b94909316939093029190911787555090516001860155516002850155505160039092019190915550565b60008163ffffffff168363ffffffff161061384a578161384c565b6040516000906127109082906001600160a01b038616908390869084818181858888f193505050503d8060008114614232576040519150601f19603f3d011682016040523d82523d6000602084013e614237565b606091505b50909695505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485946060948a16939092909182918083835b602083106142c25780518252601f1990920191602091820191016142a3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614324576040519150601f19603f3d011682016040523d82523d6000602084013e614329565b606091505b50915091506000815160001480614353575081806020019051602081101561435057600080fd5b50515b905082801561435f5750805b979650505050505050565b600061384c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061511c565b60065460009063ffffffff600160401b82048116600160601b909204161180156143fb5750600654600163ffffffff600160401b90920482160181166000908152600760205260409020541615155b801561442c5750600654600160401b900463ffffffff90811660010181166000908152600760205260409020541643115b905090565b600061443d82856132c2565b6001600160501b031981166000908152600460205260409020549091506001600160801b0316614473818563ffffffff6151b316565b6001600160501b0319831660009081526004602090815260409182902080546001600160801b0319166001600160801b0394851617905581519287168352905161ffff8816926001600160a01b038716927f3ac065a1e69cd78fa12ba7269660a2894da2ec7f1ff1135ed5ca04de4b4e389e92918290030190a35050505050565b60008282016001600160801b03808516908216101561384c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1781529251825160009485946060948b16939092909182918083835b602083106145e15780518252601f1990920191602091820191016145c2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614643576040519150601f19603f3d011682016040523d82523d6000602084013e614648565b606091505b50915091506000815160001480614672575081806020019051602081101561466f57600080fd5b50515b90508280156124095750979650505050505050565b60008080808461469787826151f5565b955090506146a58782614771565b945090506146b38782614751565b935090506146c18782614761565b9598949750929550505050565b602081810151604080840151606094850151825160009581019590955260f09390931b6001600160f01b031916602485015260801b6001600160801b0319166026840152921b6001600160601b03191660368201528151808203602a018152604a90910190915290565b6004810160006147488484615221565b90509250929050565b6002810160006147488484615273565b60108101600061474884846152ba565b6014810160006147488484615301565b6060818301845110156147c3576040805162461bcd60e51b8152602060048201526005602482015264627365313160d81b604482015290519081900360640190fd5b6060826040519080825280601f01601f1916602001820160405280156147f0576020820181803883390190505b509050821561482357602081018381016020860187015b8183101561481f578051835260209283019201614807565b5050505b949350505050565b806020015161ffff16816000015163ffffffff168363ffffffff167fc4e73a5b67a0594d06ea2b5c311c2aa44aa340dd4dd9ec5a1a718dc391b644708460600151856040015160405180836001600160a01b03166001600160a01b03168152602001826001600160801b03166001600160801b031681526020019250505060405180910390a45050565b6001600160401b0381166000908152600b60209081526040918290208054600191820180548551600261010095831615959095026000190190911693909304601f810185900485028401850190955284835260ff909116936060938301828280156149615780601f1061493657610100808354040283529160200191614961565b820191906000526020600020905b81548152906001019060200180831161494457829003601f168201915b505050505090508360000151600781111561497857fe5b82600781111561498457fe5b146149be576040805162461bcd60e51b8152602060048201526005602482015264373b38189960d91b604482015290519081900360640190fd5b6001845160078111156149cd57fe5b1415614a1f576149e1818560200151615348565b614a1a576040805162461bcd60e51b8152602060048201526005602482015264766e70313360d81b604482015290519081900360640190fd5b614ab0565b600684516007811115614a2e57fe5b1415614a7b57614a42818560200151615387565b614a1a576040805162461bcd60e51b81526020600482015260056024820152641d9b9c0c4d60da1b604482015290519081900360640190fd5b6040805162461bcd60e51b8152602060048201526005602482015264766e70313560d81b604482015290519081900360640190fd5b50505050565b614abe6158d1565b60048201614acc8482614751565b61ffff1683529050614ade8482614761565b6001600160801b031660208401526002019050614afb8482614771565b6001600160a01b0316604084015250909392505050565b614b1a61579c565b6000614b268382614738565b63ffffffff1683529050614b3a8382614771565b6001600160a01b031660208401529050614b548382614751565b61ffff1660408401529050614b698382614761565b6001600160801b031660608401529050602a81146138f7576040805162461bcd60e51b8152602060048201526005602482015264072667031360dc1b604482015290519081900360640190fd5b806040015161ffff16816000015163ffffffff168363ffffffff167f66fc63d751ecbefca61d4e2e7c534e4f29c61aed8ece23ed635277a7ea6f9bc48460200151856060015160405180836001600160a01b03166001600160a01b03168152602001826001600160801b03166001600160801b031681526020019250505060405180910390a45050565b614c4861579c565b81614c538482614738565b63ffffffff1683529050614c6784826153b0565b6001600160601b03191660208401529050614c828482614771565b6001600160a01b031660408401529050614c9c8482614738565b63ffffffff16606084015250909392505050565b604080516001600160601b031986166020820152815180820360140181526034909101909152600090606090614ce5906153c0565b614cf6614cf18761546a565b6153c0565b614d02614cf18661546a565b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313532000000815250601d01807f5265676973746572207a6b53796e63207075626b65793a0a0a0000000000000081525060190184805190602001908083835b60208310614d845780518252601f199092019160209182019101614d65565b51815160209384036101000a6000190180199092169116179052600560f91b91909301908152680dcdedcc6ca744060f60bb1b60018201528551600a90910192860191508083835b60208310614deb5780518252601f199092019160209182019101614dcc565b51815160209384036101000a6000190180199092169116179052600560f91b919093019081526d0c2c6c6deeadce840d2c8744060f60931b60018201528451600f90910192850191508083835b60208310614e575780518252601f199092019160209182019101614e38565b5181516020939093036101000a600019018019909116921691909117905261050560f11b920191825250600201602c6159738239602c01935050505060405160208183030381529060405290506000614eb08883615483565b6001600160a01b03908116908616149250505095945050505050565b60008060028763ffffffff168763ffffffff1660405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310614f345780518252601f199092019160209182019101614f15565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015614f73573d6000803e3d6000fd5b5050506040513d6020811015614f8857600080fd5b5051604080516020818101849052818301899052825180830384018152606090920192839052815193945060029391929182918401908083835b60208310614fe15780518252601f199092019160209182019101614fc2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015615020573d6000803e3d6000fd5b5050506040513d602081101561503557600080fd5b5051604080516020818101849052818301889052825180830384018152606090920192839052815193945060029391929182918401908083835b6020831061508e5780518252601f19909201916020918201910161506f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156150cd573d6000803e3d6000fd5b5050506040513d60208110156150e257600080fd5b50516040518451828652919250906020828282018760025afa81865280801561510a5761510c565bfe5b5050905198975050505050505050565b600081848411156151ab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015615170578181015183820152602001615158565b50505050905090810190601f16801561519d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061384c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061557f565b60008082600101915083838151811061520a57fe5b0160200151919460f89290921c1515935090915050565b6000808260040190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264189d1d4c0d60da1b604482015290519081900360640190fd5b929092015192915050565b6000808260020190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a3a981960d91b604482015290519081900360640190fd5b6000808260100190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a3a989b60d91b604482015290519081900360640190fd5b6000808260140190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264627461313160d81b604482015290519081900360640190fd5b600060606153598460046026614781565b9050606061536a8460046026614781565b905080805190602001208280519060200120149250505092915050565b60008061539584601a6155e4565b905060006153a484601a6155e4565b91909114949350505050565b6014810160006147488484615672565b60608082516002026040519080825280601f01601f1916602001820160405280156153f2576020820181803883390190505b5090506020830183518101602083015b8183101561546057825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050615402565b5091949350505050565b606061547d8263ffffffff1660046156be565b92915050565b600082516041146154c3576040805162461bcd60e51b8152602060048201526005602482015264076657331360dc1b604482015290519081900360640190fd5b600080806154d1868261574a565b935090506154df868261574a565b809350819250505060008682815181106154f557fe5b602001015160f81c60f81b60f81c90506001868051906020012082868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015615569573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6000836001600160801b0316836001600160801b0316111582906151ab5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615170578181015183820152602001615158565b60006020821115615624576040805162461bcd60e51b8152602060048201526005602482015264074726d31360dc1b604482015290519081900360640190fd5b8183511015615662576040805162461bcd60e51b815260206004820152600560248201526474726d313160d81b604482015290519081900360640190fd5b5060209182015191036008021c90565b600081601401835110156156b5576040805162461bcd60e51b8152602060048201526005602482015264062746232360dc1b604482015290519081900360640190fd5b50016020015190565b606060208260ff161115615701576040805162461bcd60e51b8152602060048201526005602482015264627432313160d81b604482015290519081900360640190fd5b8160ff166040519080825280601f01601f19166020018201604052801561572f576020820181803883390190505b5060ff6008602094850302169390931b918301919091525090565b60208101600061474884846000808260200190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a31199960d91b604482015290519081900360640190fd5b60408051608081018252600080825260208201819052918101829052606081019190915290565b50805460018160011615610100020316600290046000825580601f106157e95750615807565b601f01602090049060005260206000209081019061580791906158f1565b50565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061588057805160ff19168380011785556158ad565b828001600101855582156158ad579182015b828111156158ad578251825591602001919060010190615892565b5061211f9291506158f1565b60408051808201909152600081526060602082015290565b604080516060810182526000808252602082018190529181019190915290565b6112b091905b8082111561211f57600081556001016158f756fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c008e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf453616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974734f6e6c79207369676e2074686973206d65737361676520666f722061207472757374656420636c69656e7421a265627a7a72315820a71825d1c66a9c01cb73565bea646b85c86cee11d9eaa152a0ca2e5c5691721a64736f6c63430005100032
Deployed Bytecode
0x6080604052600436106102385760003560e01c80636b27a0441161012e578063b269b9ae116100ab578063d6973fc61161006f578063d6973fc614610be8578063e17376b514610c89578063fa6b53c314610cdb578063faf4d8cb14610d18578063ffeec23714610d2d57610238565b8063b269b9ae146109d5578063c488a09c14610b49578063c57b22be14610b7c578063c94c5b7c14610b91578063cd24ee0814610bd357610238565b80638ae20dc9116100f25780638ae20dc9146109ff578063922e149214610a3e5780639a83400d14610a53578063a2f9f1ce14610ac3578063a6289e5a14610b1957610238565b80636b27a044146108e457806378b91e70146108f95780637d4907981461090e578063871b8ff1146109d55780638773334c146109ea57610238565b806334f6bb1c116101bc5780634e913cd9116101805780634e913cd914610626578063595a5ebc146107a75780635cd0783e1461082857806367708dae1461089f5780636a387fc9146108b457610238565b806334f6bb1c146104f75780633b154b73146105285780633c06e5141461053d5780633c6461a914610552578063439fab91146105ab57610238565b80632a3174f4116102035780632a3174f4146104215780632b8c062a146104365780632d24006c146104705780632d2da8061461049e5780632f804bd2146104c457610238565b8060e21461023d5780630231c02c1461027e57806321ae605414610356578063253946451461037d578063264c0912146103f8575b600080fd5b34801561024957600080fd5b5061027c6004803603604081101561026057600080fd5b50803563ffffffff1690602001356001600160a01b0316610d42565b005b34801561028a57600080fd5b5061027c600480360360608110156102a157600080fd5b63ffffffff8235169190810190604081016020820135600160201b8111156102c857600080fd5b8201836020820111156102da57600080fd5b803590602001918460208302840111600160201b831117156102fb57600080fd5b919390929091602081019035600160201b81111561031857600080fd5b82018360208201111561032a57600080fd5b803590602001918460018302840111600160201b8311171561034b57600080fd5b509092509050610f36565b34801561036257600080fd5b5061036b61127a565b60408051918252519081900360200190f35b34801561038957600080fd5b5061027c600480360360208110156103a057600080fd5b810190602081018135600160201b8111156103ba57600080fd5b8201836020820111156103cc57600080fd5b803590602001918460018302840111600160201b831117156103ed57600080fd5b50909250905061129e565b34801561040457600080fd5b5061040d6112a2565b604080519115158252519081900360200190f35b34801561042d57600080fd5b5061036b6112ab565b34801561044257600080fd5b5061040d6004803603604081101561045957600080fd5b50803563ffffffff16906020013561ffff166112b3565b34801561047c57600080fd5b506104856112d3565b6040805163ffffffff9092168252519081900360200190f35b61027c600480360360208110156104b457600080fd5b50356001600160a01b03166112e6565b3480156104d057600080fd5b5061027c600480360360208110156104e757600080fd5b50356001600160401b031661137a565b34801561050357600080fd5b5061050c6116a7565b604080516001600160401b039092168252519081900360200190f35b34801561053457600080fd5b5061027c6116bd565b34801561054957600080fd5b506104856116bf565b34801561055e57600080fd5b506105866004803603602081101561057557600080fd5b50356001600160501b0319166116d2565b604080516001600160801b03909316835260ff90911660208301528051918290030190f35b3480156105b757600080fd5b5061027c600480360360208110156105ce57600080fd5b810190602081018135600160201b8111156105e857600080fd5b8201836020820111156105fa57600080fd5b803590602001918460018302840111600160201b8311171561061b57600080fd5b5090925090506116f9565b34801561063257600080fd5b5061027c600480360360c081101561064957600080fd5b63ffffffff8235811692602081013590911691810190606081016040820135600160201b81111561067957600080fd5b82018360208201111561068b57600080fd5b803590602001918460208302840111600160201b831117156106ac57600080fd5b919390929091602081019035600160201b8111156106c957600080fd5b8201836020820111156106db57600080fd5b803590602001918460018302840111600160201b831117156106fc57600080fd5b919390929091602081019035600160201b81111561071957600080fd5b82018360208201111561072b57600080fd5b803590602001918460018302840111600160201b8311171561074c57600080fd5b919390929091602081019035600160201b81111561076957600080fd5b82018360208201111561077b57600080fd5b803590602001918460208302840111600160201b8311171561079c57600080fd5b509092509050611780565b3480156107b357600080fd5b5061027c600480360360408110156107ca57600080fd5b810190602081018135600160201b8111156107e457600080fd5b8201836020820111156107f657600080fd5b803590602001918460018302840111600160201b8311171561081757600080fd5b91935091503563ffffffff16611a88565b34801561083457600080fd5b506108586004803603602081101561084b57600080fd5b503563ffffffff16611c3f565b6040805163ffffffff97881681526001600160401b03909616602087015293909516848401526060840191909152608083015260a082019290925290519081900360c00190f35b3480156108ab57600080fd5b5061050c611c88565b3480156108c057600080fd5b5061027c600480360360208110156108d757600080fd5b503563ffffffff16611c97565b3480156108f057600080fd5b5061040d612077565b34801561090557600080fd5b5061027c612123565b34801561091a57600080fd5b506109416004803603602081101561093157600080fd5b50356001600160401b0316612138565b6040518084600781111561095157fe5b60ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015610998578181015183820152602001610980565b50505050905090810190601f1680156109c55780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b3480156109e157600080fd5b5061027c6121ec565b3480156109f657600080fd5b5061040d6121fb565b348015610a0b57600080fd5b5061036b60048036036040811015610a2257600080fd5b5080356001600160a01b0316906020013563ffffffff16612205565b348015610a4a57600080fd5b5061040d612222565b348015610a5f57600080fd5b50610aa760048036036080811015610a7657600080fd5b506001600160a01b0381358116916020810135909116906001600160801b036040820135811691606001351661222b565b604080516001600160801b039092168252519081900360200190f35b348015610acf57600080fd5b50610af360048036036020811015610ae657600080fd5b503563ffffffff16612415565b604080516001600160a01b03909316835261ffff90911660208301528051918290030190f35b348015610b2557600080fd5b5061027c60048036036020811015610b3c57600080fd5b503563ffffffff1661243d565b348015610b5557600080fd5b5061027c60048036036020811015610b6c57600080fd5b50356001600160801b031661275c565b348015610b8857600080fd5b5061050c612866565b348015610b9d57600080fd5b5061027c60048036036040811015610bb457600080fd5b5080356001600160a01b031690602001356001600160801b031661287c565b348015610bdf57600080fd5b50610485612a3e565b348015610bf457600080fd5b5061027c60048036036080811015610c0b57600080fd5b63ffffffff8235169161ffff602082013516916001600160801b036040830135169190810190608081016060820135600160201b811115610c4b57600080fd5b820183602082011115610c5d57600080fd5b803590602001918460208302840111600160201b83111715610c7e57600080fd5b509092509050612a4a565b348015610c9557600080fd5b5061027c60048036036060811015610cac57600080fd5b506001600160a01b0381358116916cffffffffffffffffffffffffff6020820135169160409091013516612d55565b348015610ce757600080fd5b50610aa760048036036040811015610cfe57600080fd5b5080356001600160a01b0316906020013561ffff16612fd6565b348015610d2457600080fd5b50610485613011565b348015610d3957600080fd5b5061036b613024565b60008051602061592c8339815191525480610d92576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255610dac61302a565b62ffffff63ffffffff84161115610df2576040805162461bcd60e51b8152602060048201526005602482015264666565313160d81b604482015290519081900360640190fd5b60006001600160a01b038316610e0a57506000610e86565b600354604080516375698bb160e11b81526001600160a01b0386811660048301529151919092169163ead31762916024808301926020929190829003018186803b158015610e5757600080fd5b505afa158015610e6b573d6000803e3d6000fd5b505050506040513d6020811015610e8157600080fd5b505190505b610e8e61579c565b60405180608001604052808663ffffffff168152602001336001600160a01b031681526020018361ffff16815260200160006001600160801b031681525090506060610ed98261306a565b9050610ee66006826130ff565b6000610ef233856132c2565b6001600160501b0319166000908152600460205260409020805460ff60801b191660ff60801b1790555050600160008051602061592c833981519152555050505050565b60008051602061592c8339815191525480610f86576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255610fa061302a565b600660089054906101000a900463ffffffff1660010163ffffffff168663ffffffff1614610ffd576040805162461bcd60e51b815260206004820152600560248201526466766b313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b50506002805463ffffffff808b166000908152600760209081526040918290209485015494549151633711baa560e21b815260248101869052600160601b90920490921660448201819052606060048301908152606483018c90526001600160a01b03909416965063dc46ea9495508b948b949093919290918291608401908790870280828437600081840152601f19601f8201169050808301925050509550505050505060206040518083038186803b15801561111957600080fd5b505afa15801561112d573d6000803e3d6000fd5b505050506040513d602081101561114357600080fd5b505161117e576040805162461bcd60e51b815260206004820152600560248201526466766b313360d81b604482015290519081900360640190fd5b6111d383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff8c1681526007602052604090206001015492506132df915050565b63ffffffff861660009081526007602052604090205461120290600160201b90046001600160401b03166135ee565b6006805463ffffffff600160401b80830482166001018216026bffffffff00000000000000001990921691909117909155604051908716907f0cdbd8bd7813095001c5fe7917bd69d834dc01db7c1dfcf52ca135bd2038441390600090a2600160008051602061592c83398151915255505050505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081565b5050565b60095460ff1681565b620a8c005b90565b600860209081526000928352604080842090915290825290205460ff1681565b600654600160401b900463ffffffff1681565b60008051602061592c8339815191525480611336576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525561135061302a565b611364600061135e3461372e565b84613772565b600160008051602061592c833981519152555050565b60008051602061592c83398151915254806113ca576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525560095460ff1661141b576040805162461bcd60e51b8152602060048201526005602482015264636f65303160d81b604482015290519081900360640190fd5b600c5460009061143b90600160401b90046001600160401b031684613829565b90506000816001600160401b031611611483576040805162461bcd60e51b815260206004820152600560248201526431b7b2981960d91b604482015290519081900360640190fd5b600c546001600160401b03165b600c546001600160401b039081168301811690821610156116475760016001600160401b0382166000908152600b602052604090205460ff1660078111156114d457fe5b1415611607576114e261579c565b6115ab600b6000846001600160401b03166001600160401b031681526020019081526020016000206001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115a15780601f10611576576101008083540402835291602001916115a1565b820191906000526020600020905b81548152906001019060200180831161158457829003601f168201915b5050505050613853565b905060006115c1826060015183602001516132c2565b6040928301516001600160501b031991909116600090815260046020529290922080546001600160801b031981166001600160801b039182169094011692909217909155505b6001600160401b0381166000908152600b60205260408120805460ff191681559061163560018301826157c3565b50600060029190910155600101611490565b50600c805467ffffffffffffffff60401b1967ffffffffffffffff1982166001600160401b039283168501831617908116600160401b91829004831694909403909116029190911790555050600160008051602061592c83398151915255565b600c54600160801b90046001600160401b031681565b565b600654600160201b900463ffffffff1681565b6004602052600090815260409020546001600160801b03811690600160801b900460ff1682565b6117016138fd565b60008060008484606081101561171657600080fd5b50600280546001600160a01b0360208481013582166001600160a01b031993841617909355600380548535909216919092161790556000805260079052604001357f6d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6e2555050505050565b60008051602061592c83398151915254806117d0576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556117ea61302a565b6006600c9054906101000a900463ffffffff1660010163ffffffff168b63ffffffff1614611847576040805162461bcd60e51b815260206004820152600560248201526466636b313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561189257600080fd5b505afa1580156118a6573d6000803e3d6000fd5b5050506001891490506118e8576040805162461bcd60e51b815260206004820152600560248201526466636b313360d81b604482015290519081900360640190fd5b606087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506000600c60109054906101000a90046001600160401b0316905060006119bf8e848a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525061391192505050565b600c54909150600160801b90046001600160401b03168290036119f78f8f8f8f6000816119e857fe5b90506020020135878686613fd4565b6006600c81819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff160217905550508e63ffffffff167f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842460405160405180910390a250505050600160008051602061592c833981519152555050505050505050505050565b60008051602061592c8339815191525480611ad8576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c8339815191525560148314611b27576040805162461bcd60e51b8152602060048201526005602482015264061686631360dc1b604482015290519081900360640190fd5b336000908152600a6020908152604080832063ffffffff8616845290915290205415611b82576040805162461bcd60e51b8152602060048201526005602482015264616866313160d81b604482015290519081900360640190fd5b83836040518083838082843760408051919093018190038120336000818152600a602090815286822063ffffffff8d16808452908252918790209390935583529082018481529382018a905295507f9ea39b45a0cc96a2139996ec8dd30326216111249750781e563ae27c31ae87669450879350899289925060608201848480828437600083820152604051601f909101601f1916909201829003965090945050505050a2600160008051602061592c8339815191525550505050565b600760205260009081526040902080546001820154600283015460039093015463ffffffff808416946001600160401b03600160201b86041694600160601b9004909116929186565b600c546001600160401b031681565b60008051602061592c8339815191525480611ce7576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556000611d1783600660049054906101000a900463ffffffff166141c3565b60068054600160201b80820463ffffffff908116859003811690910267ffffffff00000000198316178082168501821663ffffffff199091161790925591925016805b82820163ffffffff168163ffffffff16101561200d5763ffffffff8116600090815260056020526040812080546001600160b01b0319811690915561ffff600160a01b820416916001600160a01b0390911690611db782846132c2565b6001600160501b031981166000908152600460205260409020549091506001600160801b03168015611ffe576001600160501b03198216600090815260046020526040812080546001600160801b03808216859003166001600160801b031990911617905561ffff8516611e415783611e39816001600160801b0385166141de565b915050611fbe565b600354604080516310603dad60e01b815261ffff8816600482015290516000926001600160a01b0316916310603dad916024808301926020929190829003018186803b158015611e9057600080fd5b505afa158015611ea4573d6000803e3d6000fd5b505050506040513d6020811015611eba57600080fd5b5051604080516001600160a01b038084166024830152881660448201526001600160801b038616606482018190526084808301919091528251808303909101815260a490910182526020810180516001600160e01b0316639a83400d60e01b1781529151815193945030936203d0909382918083835b60208310611f4f5780518252601f199092019160209182019101611f30565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114611fb2576040519150601f19603f3d011682016040523d82523d6000602084013e611fb7565b606091505b5090925050505b80611ffc576001600160501b03198316600090815260046020526040902080546001600160801b038082168501166001600160801b03199091161790555b505b50505050806001019050611d5a565b5063ffffffff82161561205f576040805163ffffffff808416825284840116602082015281517f9b5478c99b5ca41beec4f6f6084126d6f9e26382d017b4bb67c37c9e8453a313929181900390910190a15b5050600160008051602061592c833981519152555050565b600c546001600160401b03166000908152600b6020526040812060020154819043108015906120c25750600c546001600160401b03166000908152600b602052604090206002015415155b905080156121155760095460ff1661210b576009805460ff191660011790556040517fc71028c67eb0ef128ea270a59a674629e767d51c1af44ed6753fd2fad2c7b67790600090a15b60019150506112b0565b60009150506112b0565b5090565b6000805460ff19166001908117909155429055565b600b602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff9092169492939092908301828280156121dc5780601f106121b1576101008083540402835291602001916121dc565b820191906000526020600020905b8154815290600101906020018083116121bf57829003601f168201915b5050505050908060020154905083565b6000805460ff19168155600155565b60095460ff161590565b600a60209081526000928352604080842090915290825290205481565b60005460ff1681565b6000333014612269576040805162461bcd60e51b8152602060048201526005602482015264077746731360dc1b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038816916370a0823191602480820192602092909190829003018186803b1580156122b357600080fd5b505afa1580156122c7573d6000803e3d6000fd5b505050506040513d60208110156122dd57600080fd5b505190506122f586866001600160801b038716614243565b61232e576040805162461bcd60e51b8152602060048201526005602482015264777467313160d81b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b15801561237857600080fd5b505afa15801561238c573d6000803e3d6000fd5b505050506040513d60208110156123a257600080fd5b5051905060006123b8838363ffffffff61436a16565b9050846001600160801b0316811115612400576040805162461bcd60e51b81526020600482015260056024820152643bba33989960d91b604482015290519081900360640190fd5b6124098161372e565b98975050505050505050565b6005602052600090815260409020546001600160a01b03811690600160a01b900461ffff1682565b60008051602061592c833981519152548061248d576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556124a76143ac565b6124e0576040805162461bcd60e51b8152602060048201526005602482015264726273313160d81b604482015290519081900360640190fd5b60035460408051634b18bd0f60e01b815233600482015290516001600160a01b0390921691634b18bd0f91602480820192600092909190829003018186803b15801561252b57600080fd5b505afa15801561253f573d6000803e3d6000fd5b505060065463ffffffff600160601b8204811693506000925061256e918691600160401b9091041684036141c3565b600654909150600090600160601b900463ffffffff168290036001015b8363ffffffff168163ffffffff161161269d576125a661580a565b5063ffffffff808216600090815260076020908152604091829020825160c08101845281548086168083526001600160401b03600160201b83041694830194909452600160601b900490941692840192909252600182015460608401526002820154608084015260039091015460a0830152612651576040805162461bcd60e51b815260206004820152600560248201526466726b313160d81b604482015290519081900360640190fd5b60209081015163ffffffff8316600090815260079092526040822080546001600160801b031916815560018082018490556002820184905560039091019290925592909201910161258b565b506006805463ffffffff600160601b808304821686900382160263ffffffff60601b199092169190911791829055600c80546001600160401b03600160801b80830482168790039091160267ffffffffffffffff60801b1990911617905560408051600160401b90930482168352948490039081166020830152845190947f6f3a8259cce1ea2680115053d21c971aa1764295a45850f520525f2bfdf3c9d3928290030190a1505050600160008051602061592c833981519152555050565b60008051602061592c83398151915254806127ac576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556127ca60008333614431565b604051600090339084908381818185875af1925050503d806000811461280c576040519150601f19603f3d011682016040523d82523d6000602084013e612811565b606091505b505090508061284f576040805162461bcd60e51b8152602060048201526005602482015264667765313160d81b604482015290519081900360640190fd5b50600160008051602061592c833981519152555050565b600c54600160401b90046001600160401b031681565b60008051602061592c83398151915254806128cc576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152819055600354604080516375698bb160e11b81526001600160a01b0387811660048301529151919092169163ead31762916024808301926020929190829003018186803b15801561292d57600080fd5b505afa158015612941573d6000803e3d6000fd5b505050506040513d602081101561295757600080fd5b50519050600061296733836132c2565b6001600160501b031981166000908152600460208181526040808420548151639a83400d60e01b81526001600160a01b038c16948101949094523360248501526001600160801b038a8116604486015216606484018190529051949550933092639a83400d92608480830193919282900301818787803b1580156129ea57600080fd5b505af11580156129fe573d6000803e3d6000fd5b505050506040513d6020811015612a1457600080fd5b50519050612a23848233614431565b50505050600160008051602061592c83398151915255505050565b60065463ffffffff1681565b60008051602061592c8339815191525480612a9a576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c833981519152556000612ab833876132c2565b60095490915060ff16612afa576040805162461bcd60e51b8152602060048201526005602482015264666574313160d81b604482015290519081900360640190fd5b63ffffffff8716600090815260086020908152604080832061ffff8a16845290915290205460ff1615612b5c576040805162461bcd60e51b81526020600482015260056024820152643332ba189960d91b604482015290519081900360640190fd5b60025460065463ffffffff600160401b909104811660009081526007602090815260409182902060030154915163c81a27ad60e01b815260048101838152938c166024820152336044820181905261ffff8c1660648301526001600160801b038b16608483015260c060a4830190815260c483018a90526001600160a01b039096169563c81a27ad958e9492938e938e938e938e93909260e4909101908590850280828437600081840152601f19601f8201169050808301925050509850505050505050505060206040518083038186803b158015612c3a57600080fd5b505afa158015612c4e573d6000803e3d6000fd5b505050506040513d6020811015612c6457600080fd5b5051612c9f576040805162461bcd60e51b8152602060048201526005602482015264666574313360d81b604482015290519081900360640190fd5b6001600160501b031981166000908152600460205260409020546001600160801b0316612cd2818763ffffffff6144f416565b6001600160501b0319909216600090815260046020908152604080832080546001600160801b03969096166001600160801b03199096169590951790945563ffffffff90991681526008895282812061ffff909816815296909752909420805460ff1916600190811790915560008051602061592c833981519152555050505050565b60008051602061592c8339815191525480612da5576040805162461bcd60e51b815260206004820152601f602482015260008051602061590c833981519152604482015290519081900360640190fd5b600060008051602061592c83398151915255612dbf61302a565b600354604080516375698bb160e11b81526001600160a01b0387811660048301529151600093929092169163ead3176291602480820192602092909190829003018186803b158015612e1057600080fd5b505afa158015612e24573d6000803e3d6000fd5b505050506040513d6020811015612e3a57600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038816916370a08231916024808301926020929190829003018186803b158015612e8857600080fd5b505afa158015612e9c573d6000803e3d6000fd5b505050506040513d6020811015612eb257600080fd5b50519050612ee2863330612ed46cffffffffffffffffffffffffff8a1661372e565b6001600160801b031661455a565b612f1b576040805162461bcd60e51b8152602060048201526005602482015264333218189960d91b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b158015612f6557600080fd5b505afa158015612f79573d6000803e3d6000fd5b505050506040513d6020811015612f8f57600080fd5b505190506000612fad612fa8838563ffffffff61436a16565b61372e565b9050612fba848288613772565b50505050600160008051602061592c8339815191525550505050565b600060046000612fe685856132c2565b6001600160501b03191681526020810191909152604001600020546001600160801b03169392505050565b600654600160601b900463ffffffff1681565b60015481565b60095460ff16156116bd576040805162461bcd60e51b8152602060048201526005602482015264667265313160d81b604482015290519081900360640190fd5b60608160000151826020015183604001518460600151604051602001808563ffffffff1663ffffffff1660e01b8152600401846001600160a01b03166001600160a01b031660601b81526014018361ffff1661ffff1660f01b8152600201826001600160801b03166001600160801b031660801b81526010019450505050506040516020818303038152906040529050919050565b600c5460408051606081019091524361438001916001600160401b03808216600160401b9092041601908085600781111561313657fe5b8152602080820186905260409182018590526001600160401b0384166000908152600b9091522081518154829060ff1916600183600781111561317557fe5b02179055506020828101518051613192926001850192019061583f565b50604082015181600201559050507fd0943372c08b438a88d4b39d77216901079eda9ca59d45349841c099083b6830338286868660405180866001600160a01b03166001600160a01b03168152602001856001600160401b03166001600160401b0316815260200184600781111561320657fe5b60ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561324d578181015183820152602001613235565b50505050905090810190601f16801561327a5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a15050600c805460016001600160401b03600160401b808404821692909201160267ffffffffffffffff60401b199091161790555050565b60a01b61ffff60a01b166001600160a01b03919091161760501b90565b60278251816132ea57fe5b0615613325576040805162461bcd60e51b8152602060048201526005602482015264706f77313160d81b604482015290519081900360640190fd5b6006547fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090600090600160201b900463ffffffff165b8451821015613517576000806000806133748987614687565b9350935093509350600061338884846132c2565b6001600160501b03198116600090815260046020526040908190205481518083019092529192506001600160801b0390911690806133cc838663ffffffff6144f416565b6001600160801b03908116825260ff60209283018190526001600160501b0319861660009081526004845260409020845181549590940151909116600160801b0260ff60801b19939092166001600160801b0319909416939093179190911617905585156134ae576040805180820182526001600160a01b03878116825261ffff878116602080850191825260065463ffffffff9081168e011660009081526005909152949094209251835494516001600160a01b031990951692169190911761ffff60a01b1916600160a01b93909116929092029190911790556001909601955b505060408051602080820199909952941515858201526001600160a01b03909316606085015261ffff90911660808401526001600160801b031660a0808401919091528151808403909101815260c090920190528051930192909220916027919091019061335b565b838314613553576040805162461bcd60e51b81526020600482015260056024820152643837bb989960d91b604482015290519081900360640190fd5b60065463ffffffff828116600160201b90920416146135c3576006546040805163ffffffff808416600160201b9094048116840181168252928401909216602083015280517fc4faeb4e73f28a46e4a5fa2db5b89c39698816488534ab7f0717c46f0852c3669281900390910190a15b6006805463ffffffff909216600160201b0267ffffffff000000001990921691909117905550505050565b600c546001600160401b03600160401b90910481169082161115613641576040805162461bcd60e51b8152602060048201526005602482015264706373323160d81b604482015290519081900360640190fd5b600061364e826006613829565b600c549091506001600160401b0316805b8282016001600160401b0316816001600160401b031610156136bb576001600160401b0381166000908152600b60205260408120805460ff19168155906136a960018301826157c3565b5060006002919091015560010161365f565b5050600c8054600160801b6001600160401b03600160401b808404821687900382160267ffffffffffffffff60401b19909316929092178083168601831667ffffffffffffffff19909116178181048316959095039091160267ffffffffffffffff60801b199093169290921790915550565b6000600160801b821061211f5760405162461bcd60e51b815260040180806020018281038252602781526020018061594c6027913960400191505060405180910390fd5b61377a61579c565b6040518060800160405280600063ffffffff1681526020018561ffff168152602001846001600160801b03168152602001836001600160a01b0316815250905060606137c5826146ce565b90506137d26001826130ff565b604080516001600160801b038616815290516001600160a01b0385169161ffff88169133917fb6866b029f3aa29cd9e2bff8159a8ccaa4389f7a087c710968e0b200c0c73b08919081900360200190a45050505050565b6000816001600160401b0316836001600160401b03161061384a578161384c565b825b9392505050565b61385b61579c565b60006138678382614738565b63ffffffff168352905061387b8382614751565b61ffff16602084015290506138908382614761565b6001600160801b0316604084015290506138aa8382614771565b6001600160a01b031660608401529050602a81146138f7576040805162461bcd60e51b8152602060048201526005602482015264072647031360dc1b604482015290519081900360640190fd5b50919050565b600160008051602061592c83398151915255565b82516000906009900615613954576040805162461bcd60e51b8152602060048201526005602482015264666373313160d81b604482015290519081900360640190fd5b50600c5483517fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470916001600160401b03808216600160801b9092041601906020868101918291908801016000805b82851015613e7557845160f81c60058160078111156139bd57fe5b14156139cf5760129590950194613e6f565b60008160078111156139dd57fe5b14156139ef5760099590950194613e6f565b60028160078111156139fd57fe5b1415613a0f5760369590950194613e6f565b8486036001826007811115613a2057fe5b1415613a93576060613a378d600184016035614781565b9050613a4161579c565b613a4a82613853565b9050613a568f8261482b565b613a5e6158b9565b50604080518082019091526001815260208101839052613a7e818c6148b5565b50506001909801975060369690960195613e6d565b6003826007811115613aa157fe5b1415613b2b57613aaf6158d1565b613abc8d83600101614ab6565b604080820151825160209384015183518086019f909f5260018f8501526001600160a01b0390921660608f015261ffff1660808e01526001600160801b031660a0808e01919091528151808e03909101815260c0909c0190528a519a0199909920985060369690960195613e6d565b6006826007811115613b3957fe5b1415613c37576060613b508d600184016035614781565b9050613b5a61579c565b613b6382614b12565b9050613b6f8f82614bb6565b60008090508b818360200151846040015185606001516040516020018086815260200185151515158152602001846001600160a01b03166001600160a01b031681526020018361ffff1661ffff168152602001826001600160801b03166001600160801b0316815260200195505050505050604051602081830303815290604052805190602001209b50613c016158b9565b50604080518082019091526006815260208101849052613c21818d6148b5565b5050600190990198505060369690960195613e6d565b6007826007811115613c4557fe5b1415613e385789518361ffff1610613c8c576040805162461bcd60e51b8152602060048201526005602482015264666373313360d81b604482015290519081900360640190fd5b613c9461579c565b613ca18d83600101614c40565b90508a8461ffff1681518110613cb357fe5b602002602001015163ffffffff16600014613d5f576060613cfb8d876001600160401b03168e8861ffff1681518110613ce857fe5b602002602001015163ffffffff16614781565b90506000613d1c828460200151856060015186604001518760000151614cb0565b905080613d58576040805162461bcd60e51b8152602060048201526005602482015264667070313560d81b604482015290519081900360640190fd5b5050613dfc565b602080820151604080516001600160601b0319909216828401528051808303601401815260349092018152815191830191909120818401516001600160a01b03166000908152600a8452828120606086015163ffffffff1682529093529120541480613dfa576040805162461bcd60e51b8152602060048201526005602482015264333838189b60d91b604482015290519081900360640190fd5b505b8a8461ffff1681518110613e0c57fe5b602002602001015163ffffffff16850194508380600101945050600960060260ff168801975050613e6d565b6040805162461bcd60e51b8152602060048201526005602482015264199c1c0c4d60da1b604482015290519081900360640190fd5b505b506139a2565b828514613eb1576040805162461bcd60e51b81526020600482015260056024820152643331b9989960d91b604482015290519081900360640190fd5b8851826001600160401b031614613ef7576040805162461bcd60e51b81526020600482015260056024820152641998dccc4d60da1b604482015290519081900360640190fd5b87518161ffff1614613f38576040805162461bcd60e51b8152602060048201526005602482015264666373313560d81b604482015290519081900360640190fd5b600c546001600160401b03808216600160401b90920481169190910181169087161115613f94576040805162461bcd60e51b81526020600482015260056024820152643331b9989b60d91b604482015290519081900360640190fd5b5050600c80546001600160401b03808216909603909516600160801b0267ffffffffffffffff60801b199095169490941790935550919695505050505050565b82516009900615614014576040805162461bcd60e51b8152602060048201526005602482015264063626231360dc1b604482015290519081900360640190fd5b82516002546040805163e54ee6b160e01b815263ffffffff6009909404938416600482015290516001600160a01b039092169163e54ee6b191602480820192602092909190829003018186803b15801561406d57600080fd5b505afa158015614081573d6000803e3d6000fd5b505050506040513d602081101561409757600080fd5b50516140d2576040805162461bcd60e51b8152602060048201526005602482015264636362313160d81b604482015290519081900360640190fd5b63ffffffff6000198801166000908152600760205260408120600301546140fe90899089908989614ecc565b6040805160c0810182524363ffffffff90811682526001600160401b03968716602080840191825296821683850190815260608401998a526080840195865260a084019b8c529c821660009081526007909752929095209051815492519b5163ffffffff19909316908616176bffffffffffffffff000000001916600160201b9b9096169a909a029490941763ffffffff60601b1916600160601b94909316939093029190911787555090516001860155516002850155505160039092019190915550565b60008163ffffffff168363ffffffff161061384a578161384c565b6040516000906127109082906001600160a01b038616908390869084818181858888f193505050503d8060008114614232576040519150601f19603f3d011682016040523d82523d6000602084013e614237565b606091505b50909695505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485946060948a16939092909182918083835b602083106142c25780518252601f1990920191602091820191016142a3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614324576040519150601f19603f3d011682016040523d82523d6000602084013e614329565b606091505b50915091506000815160001480614353575081806020019051602081101561435057600080fd5b50515b905082801561435f5750805b979650505050505050565b600061384c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061511c565b60065460009063ffffffff600160401b82048116600160601b909204161180156143fb5750600654600163ffffffff600160401b90920482160181166000908152600760205260409020541615155b801561442c5750600654600160401b900463ffffffff90811660010181166000908152600760205260409020541643115b905090565b600061443d82856132c2565b6001600160501b031981166000908152600460205260409020549091506001600160801b0316614473818563ffffffff6151b316565b6001600160501b0319831660009081526004602090815260409182902080546001600160801b0319166001600160801b0394851617905581519287168352905161ffff8816926001600160a01b038716927f3ac065a1e69cd78fa12ba7269660a2894da2ec7f1ff1135ed5ca04de4b4e389e92918290030190a35050505050565b60008282016001600160801b03808516908216101561384c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1781529251825160009485946060948b16939092909182918083835b602083106145e15780518252601f1990920191602091820191016145c2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614643576040519150601f19603f3d011682016040523d82523d6000602084013e614648565b606091505b50915091506000815160001480614672575081806020019051602081101561466f57600080fd5b50515b90508280156124095750979650505050505050565b60008080808461469787826151f5565b955090506146a58782614771565b945090506146b38782614751565b935090506146c18782614761565b9598949750929550505050565b602081810151604080840151606094850151825160009581019590955260f09390931b6001600160f01b031916602485015260801b6001600160801b0319166026840152921b6001600160601b03191660368201528151808203602a018152604a90910190915290565b6004810160006147488484615221565b90509250929050565b6002810160006147488484615273565b60108101600061474884846152ba565b6014810160006147488484615301565b6060818301845110156147c3576040805162461bcd60e51b8152602060048201526005602482015264627365313160d81b604482015290519081900360640190fd5b6060826040519080825280601f01601f1916602001820160405280156147f0576020820181803883390190505b509050821561482357602081018381016020860187015b8183101561481f578051835260209283019201614807565b5050505b949350505050565b806020015161ffff16816000015163ffffffff168363ffffffff167fc4e73a5b67a0594d06ea2b5c311c2aa44aa340dd4dd9ec5a1a718dc391b644708460600151856040015160405180836001600160a01b03166001600160a01b03168152602001826001600160801b03166001600160801b031681526020019250505060405180910390a45050565b6001600160401b0381166000908152600b60209081526040918290208054600191820180548551600261010095831615959095026000190190911693909304601f810185900485028401850190955284835260ff909116936060938301828280156149615780601f1061493657610100808354040283529160200191614961565b820191906000526020600020905b81548152906001019060200180831161494457829003601f168201915b505050505090508360000151600781111561497857fe5b82600781111561498457fe5b146149be576040805162461bcd60e51b8152602060048201526005602482015264373b38189960d91b604482015290519081900360640190fd5b6001845160078111156149cd57fe5b1415614a1f576149e1818560200151615348565b614a1a576040805162461bcd60e51b8152602060048201526005602482015264766e70313360d81b604482015290519081900360640190fd5b614ab0565b600684516007811115614a2e57fe5b1415614a7b57614a42818560200151615387565b614a1a576040805162461bcd60e51b81526020600482015260056024820152641d9b9c0c4d60da1b604482015290519081900360640190fd5b6040805162461bcd60e51b8152602060048201526005602482015264766e70313560d81b604482015290519081900360640190fd5b50505050565b614abe6158d1565b60048201614acc8482614751565b61ffff1683529050614ade8482614761565b6001600160801b031660208401526002019050614afb8482614771565b6001600160a01b0316604084015250909392505050565b614b1a61579c565b6000614b268382614738565b63ffffffff1683529050614b3a8382614771565b6001600160a01b031660208401529050614b548382614751565b61ffff1660408401529050614b698382614761565b6001600160801b031660608401529050602a81146138f7576040805162461bcd60e51b8152602060048201526005602482015264072667031360dc1b604482015290519081900360640190fd5b806040015161ffff16816000015163ffffffff168363ffffffff167f66fc63d751ecbefca61d4e2e7c534e4f29c61aed8ece23ed635277a7ea6f9bc48460200151856060015160405180836001600160a01b03166001600160a01b03168152602001826001600160801b03166001600160801b031681526020019250505060405180910390a45050565b614c4861579c565b81614c538482614738565b63ffffffff1683529050614c6784826153b0565b6001600160601b03191660208401529050614c828482614771565b6001600160a01b031660408401529050614c9c8482614738565b63ffffffff16606084015250909392505050565b604080516001600160601b031986166020820152815180820360140181526034909101909152600090606090614ce5906153c0565b614cf6614cf18761546a565b6153c0565b614d02614cf18661546a565b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313532000000815250601d01807f5265676973746572207a6b53796e63207075626b65793a0a0a0000000000000081525060190184805190602001908083835b60208310614d845780518252601f199092019160209182019101614d65565b51815160209384036101000a6000190180199092169116179052600560f91b91909301908152680dcdedcc6ca744060f60bb1b60018201528551600a90910192860191508083835b60208310614deb5780518252601f199092019160209182019101614dcc565b51815160209384036101000a6000190180199092169116179052600560f91b919093019081526d0c2c6c6deeadce840d2c8744060f60931b60018201528451600f90910192850191508083835b60208310614e575780518252601f199092019160209182019101614e38565b5181516020939093036101000a600019018019909116921691909117905261050560f11b920191825250600201602c6159738239602c01935050505060405160208183030381529060405290506000614eb08883615483565b6001600160a01b03908116908616149250505095945050505050565b60008060028763ffffffff168763ffffffff1660405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310614f345780518252601f199092019160209182019101614f15565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015614f73573d6000803e3d6000fd5b5050506040513d6020811015614f8857600080fd5b5051604080516020818101849052818301899052825180830384018152606090920192839052815193945060029391929182918401908083835b60208310614fe15780518252601f199092019160209182019101614fc2565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015615020573d6000803e3d6000fd5b5050506040513d602081101561503557600080fd5b5051604080516020818101849052818301889052825180830384018152606090920192839052815193945060029391929182918401908083835b6020831061508e5780518252601f19909201916020918201910161506f565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156150cd573d6000803e3d6000fd5b5050506040513d60208110156150e257600080fd5b50516040518451828652919250906020828282018760025afa81865280801561510a5761510c565bfe5b5050905198975050505050505050565b600081848411156151ab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015615170578181015183820152602001615158565b50505050905090810190601f16801561519d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061384c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061557f565b60008082600101915083838151811061520a57fe5b0160200151919460f89290921c1515935090915050565b6000808260040190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264189d1d4c0d60da1b604482015290519081900360640190fd5b929092015192915050565b6000808260020190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a3a981960d91b604482015290519081900360640190fd5b6000808260100190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a3a989b60d91b604482015290519081900360640190fd5b6000808260140190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264627461313160d81b604482015290519081900360640190fd5b600060606153598460046026614781565b9050606061536a8460046026614781565b905080805190602001208280519060200120149250505092915050565b60008061539584601a6155e4565b905060006153a484601a6155e4565b91909114949350505050565b6014810160006147488484615672565b60608082516002026040519080825280601f01601f1916602001820160405280156153f2576020820181803883390190505b5090506020830183518101602083015b8183101561546057825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050615402565b5091949350505050565b606061547d8263ffffffff1660046156be565b92915050565b600082516041146154c3576040805162461bcd60e51b8152602060048201526005602482015264076657331360dc1b604482015290519081900360640190fd5b600080806154d1868261574a565b935090506154df868261574a565b809350819250505060008682815181106154f557fe5b602001015160f81c60f81b60f81c90506001868051906020012082868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015615569573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6000836001600160801b0316836001600160801b0316111582906151ab5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315615170578181015183820152602001615158565b60006020821115615624576040805162461bcd60e51b8152602060048201526005602482015264074726d31360dc1b604482015290519081900360640190fd5b8183511015615662576040805162461bcd60e51b815260206004820152600560248201526474726d313160d81b604482015290519081900360640190fd5b5060209182015191036008021c90565b600081601401835110156156b5576040805162461bcd60e51b8152602060048201526005602482015264062746232360dc1b604482015290519081900360640190fd5b50016020015190565b606060208260ff161115615701576040805162461bcd60e51b8152602060048201526005602482015264627432313160d81b604482015290519081900360640190fd5b8160ff166040519080825280601f01601f19166020018201604052801561572f576020820181803883390190505b5060ff6008602094850302169390931b918301919091525090565b60208101600061474884846000808260200190508084511015615268576040805162461bcd60e51b8152602060048201526005602482015264313a31199960d91b604482015290519081900360640190fd5b60408051608081018252600080825260208201819052918101829052606081019190915290565b50805460018160011615610100020316600290046000825580601f106157e95750615807565b601f01602090049060005260206000209081019061580791906158f1565b50565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061588057805160ff19168380011785556158ad565b828001600101855582156158ad579182015b828111156158ad578251825591602001919060010190615892565b5061211f9291506158f1565b60408051808201909152600081526060602082015290565b604080516060810182526000808252602082018190529181019190915290565b6112b091905b8082111561211f57600081556001016158f756fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c008e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf453616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974734f6e6c79207369676e2074686973206d65737361676520666f722061207472757374656420636c69656e7421a265627a7a72315820a71825d1c66a9c01cb73565bea646b85c86cee11d9eaa152a0ca2e5c5691721a64736f6c63430005100032
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.