Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multi Chain
Multichain Addresses
1 address found via
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 12809999 | 804 days 15 hrs ago | IN | Create: ZkSyncCommitBlock | 0 ETH | 0.14500722 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ZkSyncCommitBlock
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; pragma experimental ABIEncoderV2; 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 "./uniswap/UniswapV2Factory.sol"; import "./PairTokenManager.sol"; /// @title zkSync main contract /// @author Matter Labs /// @author ZKSwap L2 Labs contract ZkSyncCommitBlock is PairTokenManager, Storage, Config, Events, ReentrancyGuard { using SafeMath for uint256; using SafeMathUInt128 for uint128; bytes32 public constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; /// @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 Commit Multi block - collect onchain operations, create its commitment, emit BlockCommit event /// @param _blockInfo: /// _blockNumber Block number /// _blockCount Block count /// _feeAccount Account to collect fees /// _chunks Account to collect fees [array] /// @param _newRootAndCommitment: /// _newRoot New root of the block. /// _newCommitment New commitment of the block. /// @param _publicDatas: /// _publicData Operations pubdata /// _ethWitness Data passed to ethereum outside pubdata of the circuit. /// @param _ethWitnessSizes Amount of eth witness bytes for the corresponding operation. [offsets, data] function commitMultiBlock( uint32[] calldata _blockInfo, bytes32[] calldata _newRootAndCommitment, bytes[] calldata _publicDatas, uint32[] calldata _ethWitnessSizes ) external nonReentrant { requireActive(); uint32 _blockNumber = _blockInfo[0]; uint32 _blockCount = _blockInfo[1]; require(_blockNumber == totalBlocksCommitted + 1, "fck11"); // only commit next block governance.requireActiveValidator(msg.sender); for (uint32 i = 0; i < _blockCount; i++) { uint32 chunks = _blockInfo[3+i]; bytes memory publicData = _publicDatas[2*i]; bytes memory ethWitness = _publicDatas[2*i+1]; uint32 blockNumber = _blockNumber+i; bytes32 newRoot = _newRootAndCommitment[2*i]; bytes32 newCommitment = _newRootAndCommitment[2*i+1]; uint32[] memory ethWitnessSizes = _ethWitnessSizes; uint32 ethWitnessSizesOffset = _ethWitnessSizes[i]; // Unpack onchain operations and store them. // Get priority operations number for this block. uint64 prevTotalCommittedPriorityRequests = totalCommittedPriorityRequests; bytes32 withdrawalsDataHash = collectOnchainMultiOps([blockNumber, ethWitnessSizesOffset+_blockCount], publicData, ethWitness, ethWitnessSizes); uint64 nPriorityRequestProcessed = totalCommittedPriorityRequests - prevTotalCommittedPriorityRequests; createCommittedMultiBlock(blockNumber, chunks, newRoot, newCommitment, 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 { revert("fb1"); // verify one block is not supported // 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 Creates multiblock verify info function createMultiblockCommitment(uint32 _blockNumberFrom, uint32 _blockNumberTo) internal returns (uint32[] memory blockSizes, uint256[] memory inputs) { uint32 numberOfBlocks = _blockNumberTo - _blockNumberFrom + 1; blockSizes = new uint32[](numberOfBlocks); inputs = new uint256[](numberOfBlocks); for (uint32 i = 0; i < numberOfBlocks; i++) { blockSizes[i] = blocks[_blockNumberFrom + i].chunks; bytes32 blockCommitment = blocks[_blockNumberFrom + i].commitment; uint256 mask = (~uint256(0)) >> 3; inputs[i] = uint256(blockCommitment) & mask; } } /// @notice Multiblock verification. /// @notice Verify proof -> process onchain withdrawals (accrue balances from withdrawals) -> remove priority requests /// @param _blockNumberFrom Block number from /// @param _blockNumberTo Block number to /// @param _recursiveInput Multiblock proof inputs /// @param _proof Multiblock proof /// @param _subProofLimbs Multiblock proof subproof limbs function verifyBlocks( uint32 _blockNumberFrom, uint32 _blockNumberTo, uint256[] calldata _recursiveInput, uint256[] calldata _proof, uint256[] calldata _subProofLimbs ) external nonReentrant { requireActive(); require(_blockNumberFrom <= _blockNumberTo, "vbs11"); // vbs11 - must verify non empty sequence of blocks require(_blockNumberFrom == totalBlocksVerified + 1, "mbfvk11"); // only verify from next block governance.requireActiveValidator(msg.sender); (uint32[] memory aggregatedBlockSizes, uint256[] memory aggregatedInputs) = createMultiblockCommitment(_blockNumberFrom, _blockNumberTo); require(verifier.verifyMultiblockProof(_recursiveInput, _proof, aggregatedBlockSizes, aggregatedInputs, _subProofLimbs), "mbfvk13"); for (uint32 _blockNumber = _blockNumberFrom; _blockNumber <= _blockNumberTo; _blockNumber++){ deleteRequests( blocks[_blockNumber].priorityOperations ); } totalBlocksVerified = _blockNumberTo; emit MultiblockVerification(_blockNumberFrom, _blockNumberTo); } /// @notice Check withdrawls in verified block and generate pending withdraw if necessary /// @param _blockNumberFrom Block number from /// @param _blockNumberTo Block number to /// @param _withdrawalsData - withdraw data of next verified block function checkWithdrawals(uint32 _blockNumberFrom, uint32 _blockNumberTo, bytes[] calldata _withdrawalsData) external nonReentrant { require(_blockNumberFrom <= _blockNumberTo, "cw1"); require(_blockNumberFrom == totalBlocksChecked + 1, "cw2"); require(_blockNumberTo <= totalBlocksVerified, "cw3"); for (uint32 _blockNumber = _blockNumberFrom; _blockNumber <= _blockNumberTo; _blockNumber++){ processOnchainWithdrawals(_withdrawalsData[_blockNumber - _blockNumberFrom], blocks[_blockNumber].withdrawalsDataHash); } totalBlocksChecked = _blockNumberTo; } /// @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; } } 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 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 ); } /// @notice Store committed block structure to the storage. /// @param _nCommittedPriorityRequests - number of priority requests in block function createCommittedMultiBlock( uint32 _blockNumber, uint32 _chunks, bytes32 _newRoot, bytes32 _newCommitment, bytes memory _publicData, bytes32 _withdrawalDataHash, uint64 _nCommittedPriorityRequests ) internal { require(verifier.isBlockSizeSupported(_chunks), "ccb11"); blocks[_blockNumber] = Block( uint32(block.number), // committed at _nCommittedPriorityRequests, // number of priority onchain ops in block _chunks, _withdrawalDataHash, // hash of onchain withdrawals data (will be used during checking block withdrawal data in verifyBlock function) _newCommitment, // 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); } function emitCreatePairCommitEvent(uint32 _blockNumber, Operations.CreatePair memory createPairData) internal { emit CreatePairCommit(_blockNumber, createPairData.accountId, createPairData.tokenA, createPairData.tokenB, createPairData.tokenPair, createPairData.pair); } /// @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 if (opType == Operations.OpType.AddLiquidity) { pubDataPtr += UNISWAP_ADD_LIQ_BYTES; } else if (opType == Operations.OpType.RemoveLiquidity) { pubDataPtr += UNISWAP_RM_LIQ_BYTES; } else if (opType == Operations.OpType.Swap) { pubDataPtr += UNISWAP_SWAP_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 if (opType == Operations.OpType.CreatePair) { bytes memory pubData = Bytes.slice(_publicData, pubdataOffset + 1, CREATE_PAIR_BYTES - 1); Operations.CreatePair memory createPairData = Operations.readCreatePairPubdata(pubData); emitCreatePairCommitEvent(_blockNumber, createPairData); OnchainOperation memory onchainOp = OnchainOperation( Operations.OpType.CreatePair, pubData ); commitNextPriorityOperation(onchainOp, currentPriorityRequestId); currentPriorityRequestId++; pubDataPtr += CREATE_PAIR_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 Gets operations packed in bytes array. Unpacks it and stores onchain operations. /// @param _blockInfo: 1/ _blockNumber Franklin block number 2/ _ethWitnessSizesOffset /// @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 collectOnchainMultiOps(uint32[2] memory _blockInfo, 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; uint32 processedOperationsRequiringEthWitness = _blockInfo[1]; withdrawalsDataHash = EMPTY_STRING_KECCAK; uint32 _blockNumber = _blockInfo[0]; 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 if (opType == Operations.OpType.AddLiquidity) { pubDataPtr += UNISWAP_ADD_LIQ_BYTES; } else if (opType == Operations.OpType.RemoveLiquidity) { pubDataPtr += UNISWAP_RM_LIQ_BYTES; } else if (opType == Operations.OpType.Swap) { pubDataPtr += UNISWAP_SWAP_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 if (opType == Operations.OpType.CreatePair) { bytes memory pubData = Bytes.slice(_publicData, pubdataOffset + 1, CREATE_PAIR_BYTES - 1); Operations.CreatePair memory createPairData = Operations.readCreatePairPubdata(pubData); emitCreatePairCommitEvent(_blockNumber, createPairData); OnchainOperation memory onchainOp = OnchainOperation( Operations.OpType.CreatePair, pubData ); commitNextPriorityOperation(onchainOp, currentPriorityRequestId); currentPriorityRequestId++; pubDataPtr += CREATE_PAIR_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 ZKSwap 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 if (_onchainOp.opType == Operations.OpType.CreatePair) { require(Operations.createPairPubdataMatch(priorReqPubdata, _onchainOp.pubData), "vnp15"); } else { revert("vnp16"); // 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 } /// @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; } // The contract is too large. Break some functions to zkSyncExitAddress function() external payable { address nextAddress = zkSyncExitAddress; require(nextAddress != address(0), "zkSyncExitAddress should be set"); // Execute external function from facet using delegatecall and return any value. assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), nextAddress, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } }
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 "./VerifierExit.sol"; import "./Operations.sol"; import "./uniswap/UniswapV2Factory.sol"; /// @title ZKSwap storage contract /// @author Matter Labs /// @author ZKSwap L2 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; VerifierExit internal verifierExit; /// @notice Governance contract. Contains the governor (the owner) of whole system, validators list, possible tokens list Governance internal governance; UniswapV2Factory internal pairmanager; 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 checked blocks uint32 public totalBlocksChecked; /// @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; mapping(uint32 => mapping(uint32 => bool)) public swap_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; } address public zkSyncCommitBlockAddress; address public zkSyncExitAddress; /// @notice Limit the max amount for each ERC20 deposit uint128 public maxDepositAmount; /// @notice withdraw erc20 token gas limit uint256 public withdrawGasLimit; }
pragma solidity ^0.5.0; /// @title ZKSwap configuration constants /// @author Matter Labs /// @author ZKSwap L2 Labs contract Config { /// @notice ERC20 token withdrawal gas limit, used only for complete withdrawals uint256 constant ERC20_WITHDRAWAL_GAS_LIMIT = 350000; /// @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 = 11; /// @notice ZKSwap 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 fee tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0) uint16 constant MAX_AMOUNT_OF_REGISTERED_FEE_TOKENS = 32 - 1; /// @notice start ID for user tokens uint16 constant USER_TOKENS_START_ID = 32; /// @notice Max amount of user tokens registered in the network uint16 constant MAX_AMOUNT_OF_REGISTERED_USER_TOKENS = 16352; /// @notice Max amount of tokens registered in the network uint16 constant MAX_AMOUNT_OF_REGISTERED_TOKENS = 16384 - 1; /// @notice Max account id that could be registered in the network uint32 constant MAX_ACCOUNT_ID = (2 ** 28) - 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 CREATE_PAIR_BYTES = 3 * CHUNK_BYTES; uint256 constant DEPOSIT_BYTES = 4 * CHUNK_BYTES; uint256 constant TRANSFER_TO_NEW_BYTES = 4 * CHUNK_BYTES; uint256 constant PARTIAL_EXIT_BYTES = 5 * CHUNK_BYTES; uint256 constant TRANSFER_BYTES = 2 * CHUNK_BYTES; uint256 constant UNISWAP_ADD_LIQ_BYTES = 3 * CHUNK_BYTES; uint256 constant UNISWAP_RM_LIQ_BYTES = 3 * CHUNK_BYTES; uint256 constant UNISWAP_SWAP_BYTES = 2 * CHUNK_BYTES; /// @notice Full exit operation length uint256 constant FULL_EXIT_BYTES = 4 * 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 = 5 * 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; // @notice Default amount limit for each ERC20 deposit uint128 constant DEFAULT_MAX_DEPOSIT_AMOUNT = 2 ** 85; }
pragma solidity ^0.5.0; import "./Upgradeable.sol"; import "./Operations.sol"; /// @title ZKSwap events /// @author Matter Labs /// @author ZKSwap L2 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 a sequence of blocks is verified event MultiblockVerification(uint32 indexed blockNumberFrom, uint32 indexed blockNumberTo); /// @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 ); event OnchainCreatePair( uint16 indexed tokenAId, uint16 indexed tokenBId, uint16 indexed pairId, address pair ); /// @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 indexed totalBlocksVerified, uint32 indexed 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, bytes userData, 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 ); event CreatePairCommit( uint32 indexed zkSyncBlockId, uint32 indexed accountId, uint16 tokenAId, uint16 tokenBId, uint16 indexed tokenPairId, address pair ); } /// @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 ZKSwap operations tools library Operations { // Circuit ops and their pubdata (chunks * bytes) /// @notice ZKSwap circuit operation type enum OpType { Noop, Deposit, TransferToNew, PartialExit, _CloseAccount, // used for correct op id offset Transfer, FullExit, ChangePubKey, CreatePair, AddLiquidity, RemoveLiquidity, Swap } // 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 ZKSwap 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.owner) = Bytes.readAddress(_data, offset); // owner (offset, parsed.tokenId) = Bytes.readUInt16(_data, offset); // tokenId (offset, parsed.amount) = Bytes.readUInt128(_data, offset); // amount } 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.owner, // owner op.tokenId, // tokenId op.amount // amount ); } // 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); } // CreatePair pubdata struct CreatePair { uint32 accountId; uint16 tokenA; uint16 tokenB; uint16 tokenPair; address pair; } uint public constant PACKED_CREATE_PAIR_PUBDATA_BYTES = ACCOUNT_ID_BYTES + TOKEN_BYTES + TOKEN_BYTES + TOKEN_BYTES + ADDRESS_BYTES; function readCreatePairPubdata(bytes memory _data) internal pure returns (CreatePair memory parsed) { uint offset = 0; (offset, parsed.accountId) = Bytes.readUInt32(_data, offset); // accountId (offset, parsed.tokenA) = Bytes.readUInt16(_data, offset); // tokenAId (offset, parsed.tokenB) = Bytes.readUInt16(_data, offset); // tokenBId (offset, parsed.tokenPair) = Bytes.readUInt16(_data, offset); // pairId (offset, parsed.pair) = Bytes.readAddress(_data, offset); // pairId require(offset == PACKED_CREATE_PAIR_PUBDATA_BYTES, "rcp10"); // reading invalid create pair pubdata size } function writeCreatePairPubdata(CreatePair memory op) internal pure returns (bytes memory buf) { buf = abi.encodePacked( bytes4(0), // accountId (ignored) (update when ACCOUNT_ID_BYTES is changed) op.tokenA, // tokenAId op.tokenB, // tokenBId op.tokenPair, // pairId op.pair // pair account ); } /// @notice Check that create pair pubdata from request and block matches function createPairPubdataMatch(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_CREATE_PAIR_PUBDATA_BYTES - ACCOUNT_ID_BYTES); bytes memory rhs_trimmed = Bytes.slice(_rhs, ACCOUNT_ID_BYTES, PACKED_CREATE_PAIR_PUBDATA_BYTES - ACCOUNT_ID_BYTES); return keccak256(lhs_trimmed) == keccak256(rhs_trimmed); } }
pragma solidity =0.5.16; import './interfaces/IUniswapV2Factory.sol'; import './UniswapV2Pair.sol'; contract UniswapV2Factory is IUniswapV2Factory { mapping(address => mapping(address => address)) public getPair; address[] public allPairs; address public zkSyncAddress; event PairCreated(address indexed token0, address indexed token1, address pair, uint); constructor() public { } function initialize(bytes calldata data) external { } function setZkSyncAddress(address _zksyncAddress) external { require(zkSyncAddress == address(0), "szsa1"); zkSyncAddress = _zksyncAddress; } /// @notice PairManager 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 allPairsLength() external view returns (uint) { return allPairs.length; } function createPair(address tokenA, address tokenB) external returns (address pair) { require(msg.sender == zkSyncAddress, 'fcp1'); require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES'); (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); //require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS'); require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient bytes memory bytecode = type(UniswapV2Pair).creationCode; bytes32 salt = keccak256(abi.encodePacked(token0, token1)); assembly { pair := create2(0, add(bytecode, 32), mload(bytecode), salt) } require(zkSyncAddress != address(0), 'wzk'); IUniswapV2Pair(pair).initialize(token0, token1); getPair[token0][token1] = pair; getPair[token1][token0] = pair; // populate mapping in the reverse direction allPairs.push(pair); emit PairCreated(token0, token1, pair, allPairs.length); } function mint(address pair, address to, uint amount) external { require(msg.sender == zkSyncAddress, 'fmt1'); IUniswapV2Pair(pair).mint(to, amount); } function burn(address pair, address to, uint amount) external { require(msg.sender == zkSyncAddress, 'fbr1'); IUniswapV2Pair(pair).burn(to, amount); } }
pragma solidity ^0.5.0; contract PairTokenManager { /// @notice Max amount of pair tokens registered in the network. uint16 constant MAX_AMOUNT_OF_PAIR_TOKENS = 49152; uint16 constant PAIR_TOKEN_START_ID = 16384; /// @notice Total number of pair tokens registered in the network uint16 public totalPairTokens; /// @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 Token added to Franklin net event NewToken( address indexed token, uint16 indexed tokenId ); function addPairToken(address _token) internal { require(tokenIds[_token] == 0, "pan1"); // token exists require(totalPairTokens < MAX_AMOUNT_OF_PAIR_TOKENS, "pan2"); // no free identifiers for tokens uint16 newPairTokenId = PAIR_TOKEN_START_ID + totalPairTokens; totalPairTokens++; tokenAddresses[newPairTokenId] = _token; tokenIds[_token] = newPairTokenId; emit NewToken(_token, newPairTokenId); } /// @notice Validate pair token address /// @param _tokenAddr Token address /// @return tokens id function validatePairTokenAddress(address _tokenAddr) public view returns (uint16) { uint16 tokenId = tokenIds[_tokenAddr]; require(tokenId != 0, "pms3"); require(tokenId <= (PAIR_TOKEN_START_ID -1 + MAX_AMOUNT_OF_PAIR_TOKENS), "pms4"); return tokenId; } }
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 /// @author ZKSwap L2 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 tokenLister changed event NewTokenLister( address newTokenLister ); /// @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 fee tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0) uint16 public totalFeeTokens; /// @notice Total number of ERC20 user tokens registered in the network uint16 public totalUserTokens; /// @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; address public tokenLister; constructor() public { networkGovernor = msg.sender; } /// @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 { require(networkGovernor == address(0), "init0"); (address _networkGovernor, address _tokenLister) = abi.decode(initializationParameters, (address, address)); networkGovernor = _networkGovernor; tokenLister = _tokenLister; } /// @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); require(_newGovernor != address(0), "zero address is passed as _newGovernor"); if (networkGovernor != _newGovernor) { networkGovernor = _newGovernor; emit NewGovernor(_newGovernor); } } /// @notice Change current governor /// @param _newTokenLister Address of the new governor function changeTokenLister(address _newTokenLister) external { requireGovernor(msg.sender); require(_newTokenLister != address(0), "zero address is passed as _newTokenLister"); if (tokenLister != _newTokenLister) { tokenLister = _newTokenLister; emit NewTokenLister(_newTokenLister); } } /// @notice Add fee token to the list of networks tokens /// @param _token Token address function addFeeToken(address _token) external { requireGovernor(msg.sender); require(tokenIds[_token] == 0, "gan11"); // token exists require(totalFeeTokens < MAX_AMOUNT_OF_REGISTERED_FEE_TOKENS, "fee12"); // no free identifiers for tokens require( _token != address(0), "address cannot be zero" ); totalFeeTokens++; uint16 newTokenId = totalFeeTokens; // it is not `totalTokens - 1` because tokenId = 0 is reserved for eth tokenAddresses[newTokenId] = _token; tokenIds[_token] = newTokenId; emit NewToken(_token, newTokenId); } /// @notice Add token to the list of networks tokens /// @param _token Token address function addToken(address _token) external { requireTokenLister(msg.sender); require(tokenIds[_token] == 0, "gan11"); // token exists require(totalUserTokens < MAX_AMOUNT_OF_REGISTERED_USER_TOKENS, "gan12"); // no free identifiers for tokens require( _token != address(0), "address cannot be zero" ); uint16 newTokenId = USER_TOKENS_START_ID + totalUserTokens; totalUserTokens++; 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 Check if specified address can list token /// @param _address Address to check function requireTokenLister(address _address) public view { require(_address == networkGovernor || _address == tokenLister, "grr11"); // token lister or 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 <= totalFeeTokens) || (_tokenId >= USER_TOKENS_START_ID && _tokenId < (USER_TOKENS_START_ID + totalUserTokens )); } /// @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 require(tokenId <= MAX_AMOUNT_OF_REGISTERED_TOKENS, "gvs12"); return tokenId; } function getTokenAddress(uint16 _tokenId) external view returns (address) { address tokenAddr = tokenAddresses[_tokenId]; return tokenAddr; } }
pragma solidity ^0.5.0; pragma experimental ABIEncoderV2; import "./KeysWithPlonkAggVerifier.sol"; // Hardcoded constants to avoid accessing store contract Verifier is KeysWithPlonkAggVerifier { 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 verifyMultiblockProof( uint256[] calldata _recursiveInput, uint256[] calldata _proof, uint32[] calldata _block_sizes, uint256[] calldata _individual_vks_inputs, uint256[] calldata _subproofs_limbs ) external view returns (bool) { if (DUMMY_VERIFIER) { uint oldGasValue = gasleft(); uint tmp; while (gasleft() + 500000 > oldGasValue) { tmp += 1; } return true; } uint8[] memory vkIndexes = new uint8[](_block_sizes.length); for (uint32 i = 0; i < _block_sizes.length; i++) { vkIndexes[i] = blockSizeToVkIndex(_block_sizes[i]); } VerificationKey memory vk = getVkAggregated(uint32(_block_sizes.length)); return verify_serialized_proof_with_recursion(_recursiveInput, _proof, VK_TREE_ROOT, VK_MAX_INDEX, vkIndexes, _individual_vks_inputs, _subproofs_limbs, vk); } }
pragma solidity ^0.5.0; pragma experimental ABIEncoderV2; import "./KeysWithPlonkSingleVerifier.sol"; // Hardcoded constants to avoid accessing store contract VerifierExit is KeysWithPlonkSingleVerifier { function initialize(bytes calldata) external { } /// @notice VerifierExit 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 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); } function concatBytes(bytes memory param1, bytes memory param2) public pure returns (bytes memory) { bytes memory merged = new bytes(param1.length + param2.length); uint k = 0; for (uint i = 0; i < param1.length; i++) { merged[k] = param1[i]; k++; } for (uint i = 0; i < param2.length; i++) { merged[k] = param2[i]; k++; } return merged; } function verifyLpExitProof( bytes calldata _account_data, bytes calldata _pair_data0, bytes calldata _pair_data1, uint256[] calldata _proof ) external view returns (bool) { bytes memory _data1 = concatBytes(_account_data, _pair_data0); bytes memory _data2 = concatBytes(_data1, _pair_data1); bytes32 commitment = sha256(_data2); 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 = getVkLpExit(); require(vk.num_inputs == inputs.length); return verify(proof, vk); } }
pragma solidity ^0.5.0; /// @title Interface of the upgradeable contract /// @author Matter Labs /// @author ZKSwap L2 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; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); }
pragma solidity =0.5.16; import './interfaces/IUniswapV2Pair.sol'; import './UniswapV2ERC20.sol'; import './libraries/Math.sol'; import './libraries/UQ112x112.sol'; import './interfaces/IUNISWAPERC20.sol'; import './interfaces/IUniswapV2Factory.sol'; import './interfaces/IUniswapV2Callee.sol'; contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { using UniswapSafeMath for uint; using UQ112x112 for uint224; address public factory; address public token0; address public token1; uint private unlocked = 1; modifier lock() { require(unlocked == 1, 'UniswapV2: LOCKED'); unlocked = 0; _; unlocked = 1; } constructor() public { factory = msg.sender; } // called once by the factory at time of deployment function initialize(address _token0, address _token1) external { require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check token0 = _token0; token1 = _token1; } function mint(address to, uint amount) external lock { require(msg.sender == factory, 'mt1'); _mint(to, amount); } function burn(address to, uint amount) external lock { require(msg.sender == factory, 'br1'); _burn(to, amount); } }
pragma solidity >=0.5.0 <0.7.0; pragma experimental ABIEncoderV2; import "./PlonkAggCore.sol"; // Hardcoded constants to avoid accessing store contract KeysWithPlonkAggVerifier is AggVerifierWithDeserialize { uint256 constant VK_TREE_ROOT = 0x0a3cdc9655e61bf64758c1e8df745723e9b83addd4f0d0f2dd65dc762dc1e9e7; uint8 constant VK_MAX_INDEX = 5; function isBlockSizeSupportedInternal(uint32 _size) internal pure returns (bool) { if (_size == uint32(6)) { return true; } else if (_size == uint32(12)) { return true; } else if (_size == uint32(48)) { return true; } else if (_size == uint32(96)) { return true; } else if (_size == uint32(204)) { return true; } else if (_size == uint32(420)) { return true; } else { return false; } } function blockSizeToVkIndex(uint32 _chunks) internal pure returns (uint8) { if (_chunks == uint32(6)) { return 0; } else if (_chunks == uint32(12)) { return 1; } else if (_chunks == uint32(48)) { return 2; } else if (_chunks == uint32(96)) { return 3; } else if (_chunks == uint32(204)) { return 4; } else if (_chunks == uint32(420)) { return 5; } } function getVkAggregated(uint32 _blocks) internal pure returns (VerificationKey memory vk) { if (_blocks == uint32(1)) { return getVkAggregated1(); } else if (_blocks == uint32(5)) { return getVkAggregated5(); } } function getVkAggregated1() internal pure returns(VerificationKey memory vk) { vk.domain_size = 4194304; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x18c95f1ae6514e11a1b30fd7923947c5ffcec5347f16e91b4dd654168326bede); vk.gate_setup_commitments[0] = PairingsBn254.new_g1( 0x19fbd6706b4cbde524865701eae0ae6a270608a09c3afdab7760b685c1c6c41b, 0x25082a191f0690c175cc9af1106c6c323b5b5de4e24dc23be1e965e1851bca48 ); vk.gate_setup_commitments[1] = PairingsBn254.new_g1( 0x16c02d9ca95023d1812a58d16407d1ea065073f02c916290e39242303a8a1d8e, 0x230338b422ce8533e27cd50086c28cb160cf05a7ae34ecd5899dbdf449dc7ce0 ); vk.gate_setup_commitments[2] = PairingsBn254.new_g1( 0x1db0d133243750e1ea692050bbf6068a49dc9f6bae1f11960b6ce9e10adae0f5, 0x12a453ed0121ae05de60848b4374d54ae4b7127cb307372e14e8daf5097c5123 ); vk.gate_setup_commitments[3] = PairingsBn254.new_g1( 0x1062ed5e86781fd34f78938e5950c2481a79f132085d2bc7566351ddff9fa3b7, 0x2fd7aac30f645293cc99883ab57d8c99a518d5b4ab40913808045e8653497346 ); vk.gate_setup_commitments[4] = PairingsBn254.new_g1( 0x062755048bb95739f845e8659795813127283bf799443d62fea600ae23e7f263, 0x2af86098beaa241281c78a454c5d1aa6e9eedc818c96cd1e6518e1ac2d26aa39 ); vk.gate_setup_commitments[5] = PairingsBn254.new_g1( 0x0994e25148bbd25be655034f81062d1ebf0a1c2b41e0971434beab1ae8101474, 0x27cc8cfb1fafd13068aeee0e08a272577d89f8aa0fb8507aabbc62f37587b98f ); vk.gate_setup_commitments[6] = PairingsBn254.new_g1( 0x044edf69ce10cfb6206795f92c3be2b0d26ab9afd3977b789840ee58c7dbe927, 0x2a8aa20c106f8dc7e849bc9698064dcfa9ed0a4050d794a1db0f13b0ee3def37 ); vk.gate_selector_commitments[0] = PairingsBn254.new_g1( 0x136967f1a2696db05583a58dbf8971c5d9d1dc5f5c97e88f3b4822aa52fefa1c, 0x127b41299ea5c840c3b12dbe7b172380f432b7b63ce3b004750d6abb9e7b3b7a ); vk.gate_selector_commitments[1] = PairingsBn254.new_g1( 0x02fd5638bf3cc2901395ad1124b951e474271770a337147a2167e9797ab9d951, 0x0fcb2e56b077c8461c36911c9252008286d782e96030769bf279024fc81d412a ); vk.copy_permutation_commitments[0] = PairingsBn254.new_g1( 0x1865c60ecad86f81c6c952445707203c9c7fdace3740232ceb704aefd5bd45b3, 0x2f35e29b39ec8bb054e2cff33c0299dd13f8c78ea24a07622128a7444aba3f26 ); vk.copy_permutation_commitments[1] = PairingsBn254.new_g1( 0x2a86ec9c6c1f903650b5abbf0337be556b03f79aecc4d917e90c7db94518dde6, 0x15b1b6be641336eebd58e7991be2991debbbd780e70c32b49225aa98d10b7016 ); vk.copy_permutation_commitments[2] = PairingsBn254.new_g1( 0x213e42fcec5297b8e01a602684fcd412208d15bdac6b6331a8819d478ba46899, 0x03223485f4e808a3b2496ae1a3c0dfbcbf4391cffc57ee01e8fca114636ead18 ); vk.copy_permutation_commitments[3] = PairingsBn254.new_g1( 0x2e9b02f8cf605ad1a36e99e990a07d435de06716448ad53053c7a7a5341f71e1, 0x2d6fdf0bc8bd89112387b1894d6f24b45dcb122c09c84344b6fc77a619dd1d59 ); vk.copy_permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.copy_permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.copy_permutation_non_residues[2] = PairingsBn254.new_fr( 0x000000000000000000000000000000000000000000000000000000000000000a ); vk.g2_x = PairingsBn254.new_g2( [0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1, 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0], [0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4, 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55] ); } function getVkAggregated5() internal pure returns(VerificationKey memory vk) { vk.domain_size = 16777216; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x1951441010b2b95a6e47a6075066a50a036f5ba978c050f2821df86636c0facb); vk.gate_setup_commitments[0] = PairingsBn254.new_g1( 0x023cfc69ef1b002da66120fce352ede75893edd8cd8196403a54e1eceb82cd43, 0x2baf3bd673e46be9df0d43ca30f834671543c22db422f450b2efd8c931e9b34e ); vk.gate_setup_commitments[1] = PairingsBn254.new_g1( 0x23783fe0e5c3f83c02c864e25fe766afb727134c9a77ae6b9694efb7b46f31ab, 0x1903d01005e447d061c16323a1d604d8fbd4b5cc9b64945a71f1234d280c4d3a ); vk.gate_setup_commitments[2] = PairingsBn254.new_g1( 0x2897df6c6fa993661b2b0b0cf52460278e33533de71b3c0f7ed7c1f20af238c6, 0x042344afee0aed5505e59bce4ebbe942a91268a8af6b77ea95f603b5b726e8cb ); vk.gate_setup_commitments[3] = PairingsBn254.new_g1( 0x0fceed33e78426afc38d8a68c0d93413d2bbaa492b087125271d33d52bdb07b8, 0x0057e4f63be36edb56e91da931f3d0ba72d1862d4b7751c59b92b6ae9f1fcc11 ); vk.gate_setup_commitments[4] = PairingsBn254.new_g1( 0x14230a35f172cd77a2147cecc20b2a13148363cbab78709489a29d08001e26fb, 0x04f1040477d77896475080b5abb8091cda2cce4917ee0ba5dd62d0ab1be379b4 ); vk.gate_setup_commitments[5] = PairingsBn254.new_g1( 0x20d1a079ad80a8abb7fd8ba669dddbbe23231360a5f0ba679b6536b6bf980649, 0x120c5a845903bd6de4105eb8cef90e6dff2c3888ada16c90e1efb393778d6a4d ); vk.gate_setup_commitments[6] = PairingsBn254.new_g1( 0x1af6b9e362e458a96b8bbbf8f8ce2bdbd650fb68478360c408a2acf1633c1ce1, 0x27033728b767b44c659e7896a6fcc956af97566a5a1135f87a2e510976a62d41 ); vk.gate_selector_commitments[0] = PairingsBn254.new_g1( 0x0dbfb3c5f5131eb6f01e12b1a6333b0ad22cc8292b666e46e9bd4d80802cccdf, 0x2d058711c42fd2fd2eef33fb327d111a27fe2063b46e1bb54b32d02e9676e546 ); vk.gate_selector_commitments[1] = PairingsBn254.new_g1( 0x0c8c7352a84dd3f32412b1a96acd94548a292411fd7479d8609ca9bd872f1e36, 0x0874203fd8012d6976698cc2df47bca14bc04879368ade6412a2109c1e71e5e8 ); vk.copy_permutation_commitments[0] = PairingsBn254.new_g1( 0x1b17bb7c319b1cf15461f4f0b69d98e15222320cb2d22f4e3a5f5e0e9e51f4bd, 0x0cf5bc338235ded905926006027aa2aab277bc32a098cd5b5353f5545cbd2825 ); vk.copy_permutation_commitments[1] = PairingsBn254.new_g1( 0x0794d3cfbc2fdd756b162571a40e40b8f31e705c77063f30a4e9155dbc00e0ef, 0x1f821232ab8826ea5bf53fe9866c74e88a218c8d163afcaa395eda4db57b7a23 ); vk.copy_permutation_commitments[2] = PairingsBn254.new_g1( 0x224d93783aa6856621a9bbec495f4830c94994e266b240db9d652dbb394a283b, 0x161bcec99f3bc449d655c0ca59874dafe1194138eec91af34392b09a83338ca1 ); vk.copy_permutation_commitments[3] = PairingsBn254.new_g1( 0x1fa27e2916b2c11d39c74c0e61063190da31c102d2b7da5c0a61ec8c5e82f132, 0x0a815ee76cd8aa600e6f66463b25a0ee57814bfdf06c65a91ddc70cede41caae ); vk.copy_permutation_non_residues[0] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000005 ); vk.copy_permutation_non_residues[1] = PairingsBn254.new_fr( 0x0000000000000000000000000000000000000000000000000000000000000007 ); vk.copy_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; import "./PlonkSingleCore.sol"; // Hardcoded constants to avoid accessing store contract KeysWithPlonkSingleVerifier is SingleVerifierWithDeserialize { function isBlockSizeSupportedInternal(uint32 _size) internal pure returns (bool) { if (_size == uint32(6)) { return true; } else if (_size == uint32(12)) { return true; } else if (_size == uint32(48)) { return true; } else if (_size == uint32(96)) { return true; } else if (_size == uint32(204)) { return true; } else if (_size == uint32(420)) { return true; } else { return false; } } 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( 0x1abc710835cdc78389d61b670b0e8d26416a63c9bd3d6ed435103ebbb8a8665e, 0x138c6678230ed19f90b947d0a9027bd9fc458bbd1d2b8371fa72e28470a97b9c ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x28d81ac76e1ddf630b4bf8e4a789cf9c4470c5e5cc010a24849b20ab595b8b22, 0x251ca3cf0829b261d3be8d6cbd25aa97d9af716819c29f6319d806f075e79655 ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x1504c8c227833a1152f3312d258412c334ac7ae213e21427ff63028729bc28fa, 0x0f0942f3fede795cbe624fb9ddf9be90ba546609383f2246c3c9b92af7aab5fd ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x1f14a5bb19ea2897ac6b9fbdbd2b4e371be09f8e90a47ae26602d399c9bcd311, 0x029c6ea094247da75d9a66cea627c3c77d48b898003125d4f8e785435dc2cf23 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x102cdd83e2d70638a70d700622b662607f8a2d92f5c36053a4ddb4b600d75bcf, 0x09ef3679579d761507ef69eaf49c978b271f0e4500468da1ebd7197f3ff5d6ac ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x2c2bd1d2fa3d4b3915d0fe465469e11ee563e79751da71c6082fcd0ca4e41cd5, 0x0304f16147a8af177dcc703370931d5161bda9dcf3e091787b9a54377ab54c32 ); // 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( 0x14420680f992f4bc8d8012e2d8b14a774cf9114adf1e41b3c02c20cc1648398e, 0x237d3d5cdee5e3d7d58f4eb336ecd7aa5ec88d89205861b410420f6b9f6b26a1 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x221045ae5578ccb35e0a198d83c0fb191da8cdc98423fc46e580f1762682c73e, 0x15b7f3d74fcd258fdd2ae6001693a7c615e654d613a506d213aaf0ad314e338d ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x03e47981b459b3be258a6353593898babec571ccf3e0362d53a67f078f04830a, 0x0809556ab6eb28403bb5a749fcdbd8656940add7685ff5473dc3a9ad940034df ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x2c02322c53d7e6a6474b15c7db738419e3f4d1263e9f98ebb56c24906f555ef9, 0x2322c69f51366551665b584d797e0fdadb16fe31b1e7ae2f532847a75b3aeaab ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x2147e39b49c2bef4168884c0ac9e38bb4dc65b41ba21953f7ded2daab7fe1534, 0x071f3548c9ca2c6a8d10b11d553263ebe0afaf1f663b927ef970bd6c3974cb68 ); 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 getVkLpExit() internal pure returns(VerificationKey memory vk) { vk.domain_size = 524288; vk.num_inputs = 1; vk.omega = PairingsBn254.new_fr(0x0cf1526aaafac6bacbb67d11a4077806b123f767e4b0883d14cc0193568fc082); vk.selector_commitments[0] = PairingsBn254.new_g1( 0x067d967299b3d380f2e461409fbacb82d9af8c85b62de082a423f344fb0b9d38, 0x2440bd569ac24e9525b29e433334ee98d72cb8eb19af65250ee0099fb470d873 ); vk.selector_commitments[1] = PairingsBn254.new_g1( 0x086a9ed0f6175964593e516a8c1fc8bbd0a9c8afb724ebbce08a7772bd7b8837, 0x0aca3794dc6a2f0cab69dfed529d31deb7a5e9e6c339e3c07d8d88df0f7abd6b ); vk.selector_commitments[2] = PairingsBn254.new_g1( 0x00b6bfec3aceb55618e6caf637c978c3fe2344568c64515022fcfa00e490eb97, 0x0f890fe6b9cb943fb4887df1529cdae99e2494eabf675f89905215eb51c29c6e ); vk.selector_commitments[3] = PairingsBn254.new_g1( 0x0968470be841bcbfbcccc10dd0d8b63a871cdb3289c214fc59f38c88ab15146a, 0x1a9b4d034050fa0b119bb64ba0e967fd09f224c6fd9cd8b54cd6f081085dfb98 ); vk.selector_commitments[4] = PairingsBn254.new_g1( 0x080dbe10de0cacf12db303a86049c7a4d42f068a9def099e0cb874008f210b1b, 0x02f17638d3410ab573e33a4e6c6cf0c918bea2aa4f1025ca5ee13d7a950c4058 ); vk.selector_commitments[5] = PairingsBn254.new_g1( 0x267043dbe00520bd8bbf55a96b51fde6b3b64219eca9e2fd8309693db0cf0392, 0x08dbbfa17faad841228af22a03fab7ec20f765036a2acae62f543f61e55b6e8c ); // 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( 0x215141775449677e3dbe25ff6c5e5d99336a29d952a61d5ec87618346e78df30, 0x29502caeb6afaf2acd13766d52fac2907efb7d11c66cd8beb93c8321d380b215 ); vk.permutation_commitments[0] = PairingsBn254.new_g1( 0x150790105b9f5455ae6f91daa6b03c5793fb7bcfcd9d5d37d3b643b77535b10a, 0x2b644a9736282f80fae8d35f00cbddf2bba3560c54f3d036ec1c8014c147a506 ); vk.permutation_commitments[1] = PairingsBn254.new_g1( 0x1b898666ded092a449935de7d707ad8d65809c2baccdd7dd7cfdaf2fb27e1262, 0x2a24c241dcad93b7bdf1cce2427c9c54f731a7d50c27a825e2af3dabb66dc81f ); vk.permutation_commitments[2] = PairingsBn254.new_g1( 0x049892634dbbfa0c364523827cd7e604b70a7e24a4cb111cb8fccb7c05b04d7f, 0x1e5d8d7c0bf92d822dcf339a52c326a35cadf010b888b8f26e155a68c7e23dc9 ); vk.permutation_commitments[3] = PairingsBn254.new_g1( 0x04f90846cb1598aa05164a78d171ea918154414652d07d3f5cab84a26e6aa158, 0x0975ba8858f136bb8b1b043daf8dfed33709f72ba37e01e5de62c81f3928a13c ); 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; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function initialize(address, address) external; function mint(address to, uint amount) external; function burn(address to, uint amount) external; }
pragma solidity =0.5.16; import './interfaces/IUniswapV2ERC20.sol'; import './libraries/UniswapSafeMath.sol'; contract UniswapV2ERC20 is IUniswapV2ERC20 { using UniswapSafeMath for uint; string public constant name = 'ZKSWAP V2'; string public constant symbol = 'ZKS-V2'; uint8 public constant decimals = 18; uint public totalSupply; mapping(address => uint) public balanceOf; mapping(address => mapping(address => uint)) public allowance; event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); constructor() public { uint chainId; assembly { chainId := chainid } } function _mint(address to, uint value) internal { totalSupply = totalSupply.add(value); balanceOf[to] = balanceOf[to].add(value); emit Transfer(address(0), to, value); } function _burn(address from, uint value) internal { balanceOf[from] = balanceOf[from].sub(value); totalSupply = totalSupply.sub(value); emit Transfer(from, address(0), value); } function _approve(address owner, address spender, uint value) private { allowance[owner][spender] = value; emit Approval(owner, spender, value); } function _transfer(address from, address to, uint value) private { balanceOf[from] = balanceOf[from].sub(value); balanceOf[to] = balanceOf[to].add(value); emit Transfer(from, to, value); } function approve(address spender, uint value) external returns (bool) { _approve(msg.sender, spender, value); return true; } function transfer(address to, uint value) external returns (bool) { _transfer(msg.sender, to, value); return true; } function transferFrom(address from, address to, uint value) external returns (bool) { if (allowance[from][msg.sender] != uint(-1)) { allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); } _transfer(from, to, value); return true; } }
pragma solidity =0.5.16; // a library for performing various math operations library Math { function min(uint x, uint y) internal pure returns (uint z) { z = x < y ? x : y; } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } }
pragma solidity =0.5.16; // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) // range: [0, 2**112 - 1] // resolution: 1 / 2**112 library UQ112x112 { uint224 constant Q112 = 2**112; // encode a uint112 as a UQ112x112 function encode(uint112 y) internal pure returns (uint224 z) { z = uint224(y) * Q112; // never overflows } // divide a UQ112x112 by a uint112, returning a UQ112x112 function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { z = x / uint224(y); } }
pragma solidity >=0.5.0; interface IUNISWAPERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); }
pragma solidity >=0.5.0; interface IUniswapV2Callee { function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; }
pragma solidity >=0.5.0 <0.7.0; pragma experimental ABIEncoderV2; import "./PlonkCoreLib.sol"; contract Plonk4AggVerifierWithAccessToDNext { uint256 constant r_mod = 21888242871839275222246405745257275088548364400416034343698204186575808495617; using PairingsBn254 for PairingsBn254.G1Point; using PairingsBn254 for PairingsBn254.G2Point; using PairingsBn254 for PairingsBn254.Fr; using TranscriptLibrary for TranscriptLibrary.Transcript; uint256 constant ZERO = 0; uint256 constant ONE = 1; uint256 constant TWO = 2; uint256 constant THREE = 3; uint256 constant FOUR = 4; uint256 constant STATE_WIDTH = 4; uint256 constant NUM_DIFFERENT_GATES = 2; uint256 constant NUM_SETUP_POLYS_FOR_MAIN_GATE = 7; uint256 constant NUM_SETUP_POLYS_RANGE_CHECK_GATE = 0; uint256 constant ACCESSIBLE_STATE_POLYS_ON_NEXT_STEP = 1; uint256 constant NUM_GATE_SELECTORS_OPENED_EXPLICITLY = 1; uint256 constant RECURSIVE_CIRCUIT_INPUT_COMMITMENT_MASK = 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; uint256 constant LIMB_WIDTH = 68; struct VerificationKey { uint256 domain_size; uint256 num_inputs; PairingsBn254.Fr omega; PairingsBn254.G1Point[NUM_SETUP_POLYS_FOR_MAIN_GATE + NUM_SETUP_POLYS_RANGE_CHECK_GATE] gate_setup_commitments; PairingsBn254.G1Point[NUM_DIFFERENT_GATES] gate_selector_commitments; PairingsBn254.G1Point[STATE_WIDTH] copy_permutation_commitments; PairingsBn254.Fr[STATE_WIDTH-1] copy_permutation_non_residues; PairingsBn254.G2Point g2_x; } struct Proof { uint256[] input_values; PairingsBn254.G1Point[STATE_WIDTH] wire_commitments; PairingsBn254.G1Point copy_permutation_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[NUM_GATE_SELECTORS_OPENED_EXPLICITLY] gate_selector_values_at_z; PairingsBn254.Fr copy_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 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); PairingsBn254.Fr memory inputs_term = 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])); inputs_term.add_assign(tmp); } inputs_term.mul_assign(proof.gate_selector_values_at_z[0]); rhs.add_assign(inputs_term); // now we need 5th power quotient_challenge.mul_assign(state.alpha); quotient_challenge.mul_assign(state.alpha); quotient_challenge.mul_assign(state.alpha); quotient_challenge.mul_assign(state.alpha); quotient_challenge.mul_assign(state.alpha); PairingsBn254.Fr memory z_part = PairingsBn254.copy(proof.copy_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 add_contribution_from_range_constraint_gates( PartialVerifierState memory state, Proof memory proof, PairingsBn254.Fr memory current_alpha ) internal pure returns (PairingsBn254.Fr memory res) { // now add contribution from range constraint gate // we multiply selector commitment by all the factors (alpha*(c - 4d)(c - 4d - 1)(..-2)(..-3) + alpha^2 * (4b - c)()()() + {} + {}) PairingsBn254.Fr memory one_fr = PairingsBn254.new_fr(ONE); PairingsBn254.Fr memory two_fr = PairingsBn254.new_fr(TWO); PairingsBn254.Fr memory three_fr = PairingsBn254.new_fr(THREE); PairingsBn254.Fr memory four_fr = PairingsBn254.new_fr(FOUR); res = PairingsBn254.new_fr(0); PairingsBn254.Fr memory t0 = PairingsBn254.new_fr(0); PairingsBn254.Fr memory t1 = PairingsBn254.new_fr(0); PairingsBn254.Fr memory t2 = PairingsBn254.new_fr(0); for (uint256 i = 0; i < 3; i++) { current_alpha.mul_assign(state.alpha); // high - 4*low // this is 4*low t0 = PairingsBn254.copy(proof.wire_values_at_z[3 - i]); t0.mul_assign(four_fr); // high t1 = PairingsBn254.copy(proof.wire_values_at_z[2 - i]); t1.sub_assign(t0); // t0 is now t1 - {0,1,2,3} // first unroll manually for -0; t2 = PairingsBn254.copy(t1); // -1 t0 = PairingsBn254.copy(t1); t0.sub_assign(one_fr); t2.mul_assign(t0); // -2 t0 = PairingsBn254.copy(t1); t0.sub_assign(two_fr); t2.mul_assign(t0); // -3 t0 = PairingsBn254.copy(t1); t0.sub_assign(three_fr); t2.mul_assign(t0); t2.mul_assign(current_alpha); res.add_assign(t2); } // now also d_next - 4a current_alpha.mul_assign(state.alpha); // high - 4*low // this is 4*low t0 = PairingsBn254.copy(proof.wire_values_at_z[0]); t0.mul_assign(four_fr); // high t1 = PairingsBn254.copy(proof.wire_values_at_z_omega[0]); t1.sub_assign(t0); // t0 is now t1 - {0,1,2,3} // first unroll manually for -0; t2 = PairingsBn254.copy(t1); // -1 t0 = PairingsBn254.copy(t1); t0.sub_assign(one_fr); t2.mul_assign(t0); // -2 t0 = PairingsBn254.copy(t1); t0.sub_assign(two_fr); t2.mul_assign(t0); // -3 t0 = PairingsBn254.copy(t1); t0.sub_assign(three_fr); t2.mul_assign(t0); t2.mul_assign(current_alpha); res.add_assign(t2); return res; } function reconstruct_linearization_commitment( 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} * (selector(x) - selector(z)) // + v^{7..9} * (permutation(x) - permutation(z)) // ] // W'(x) = 1 / (x - z*omega) * // [ // + v^10 (z(x) - z(z*omega)) <- we need this power // + v^11 * (d(x) - d(z*omega)) // ] // // we reconstruct linearization polynomial virtual selector // for that purpose we first linearize over main gate (over all it's selectors) // and multiply them by value(!) of the corresponding main gate selector res = PairingsBn254.copy_g1(vk.gate_setup_commitments[STATE_WIDTH + 1]); // index of q_const(x) 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.gate_setup_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.gate_setup_commitments[STATE_WIDTH].point_mul(tmp_fr); res.point_add_assign(tmp_g1); // d_next tmp_g1 = vk.gate_setup_commitments[STATE_WIDTH+2].point_mul(proof.wire_values_at_z_omega[0]); // index of q_d_next(x) res.point_add_assign(tmp_g1); // multiply by main gate selector(z) res.point_mul_assign(proof.gate_selector_values_at_z[0]); // these is only one explicitly opened selector PairingsBn254.Fr memory current_alpha = PairingsBn254.new_fr(ONE); // calculate scalar contribution from the range check gate tmp_fr = add_contribution_from_range_constraint_gates(state, proof, current_alpha); tmp_g1 = vk.gate_selector_commitments[1].point_mul(tmp_fr); // selector commitment for range constraint gate * scalar res.point_add_assign(tmp_g1); // proceed as normal to copy permutation current_alpha.mul_assign(state.alpha); // alpha^5 PairingsBn254.Fr memory alpha_for_grand_product = PairingsBn254.copy(current_alpha); // 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.copy_permutation_non_residues.length; i++) { tmp_fr.assign(state.z); tmp_fr.mul_assign(vk.copy_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(alpha_for_grand_product); // alpha^n & L_{0}(z), and we bump current_alpha current_alpha.mul_assign(state.alpha); tmp_fr.assign(state.cached_lagrange_evals[0]); tmp_fr.mul_assign(current_alpha); grand_product_part_at_z.add_assign(tmp_fr); // prefactor for grand_product(x) is complete // add to the linearization a part from the term // - (a(z) + beta*perm_a + gamma)*()*()*z(z*omega) * beta * perm_d(X) 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.copy_grand_product_at_z_omega); last_permutation_part_at_z.mul_assign(alpha_for_grand_product); // we multiply by the power of alpha from the argument // actually multiply prefactors by z(x) and perm_d(x) and combine them tmp_g1 = proof.copy_permutation_grand_product_commitment.point_mul(grand_product_part_at_z); tmp_g1.point_sub_assign(vk.copy_permutation_commitments[STATE_WIDTH - 1].point_mul(last_permutation_part_at_z)); res.point_add_assign(tmp_g1); // multiply them by v immedately as linearization has a factor of v^1 res.point_mul_assign(state.v); // res now contains contribution from the gates linearization and // copy permutation part // now we need to add a part that is the rest // for z(x*omega): // - (a(z) + beta*perm_a + gamma)*()*()*(d(z) + gamma) * z(x*omega) } function aggregate_commitments( PartialVerifierState memory state, Proof memory proof, VerificationKey memory vk ) internal view returns (PairingsBn254.G1Point[2] memory res) { PairingsBn254.G1Point memory d = reconstruct_linearization_commitment(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 < NUM_GATE_SELECTORS_OPENED_EXPLICITLY; i++) { aggregation_challenge.mul_assign(state.v); tmp_g1 = vk.gate_selector_commitments[i].point_mul(aggregation_challenge); commitment_aggregation.point_add_assign(tmp_g1); } for (uint i = 0; i < vk.copy_permutation_commitments.length - 1; i++) { aggregation_challenge.mul_assign(state.v); tmp_g1 = vk.copy_permutation_commitments[i].point_mul(aggregation_challenge); commitment_aggregation.point_add_assign(tmp_g1); } aggregation_challenge.mul_assign(state.v); // now do prefactor for grand_product(x*omega) tmp_fr.assign(aggregation_challenge); tmp_fr.mul_assign(state.u); commitment_aggregation.point_add_assign(proof.copy_permutation_grand_product_commitment.point_mul(tmp_fr)); 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.gate_selector_values_at_z.length; i++) { aggregation_challenge.mul_assign(state.v); tmp_fr.assign(proof.gate_selector_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.copy_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(); res[0] = pair_with_generator; res[1] = pair_with_x; return res; } 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.copy_permutation_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(); state.cached_lagrange_evals = new PairingsBn254.Fr[](1); state.cached_lagrange_evals[0] = evaluate_lagrange_poly_out_of_domain( 0, vk.domain_size, vk.omega, state.z ); bool valid = verify_at_z(state, proof, vk); if (valid == false) { return false; } transcript.update_with_fr(proof.quotient_polynomial_at_z); 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]); } transcript.update_with_fr(proof.gate_selector_values_at_z[0]); 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.copy_grand_product_at_z_omega); 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 aggregate_for_verification(Proof memory proof, VerificationKey memory vk) internal view returns (bool valid, PairingsBn254.G1Point[2] memory part) { PartialVerifierState memory state; valid = verify_initial(state, proof, vk); if (valid == false) { return (valid, part); } part = aggregate_commitments(state, proof, vk); (valid, part); } function verify(Proof memory proof, VerificationKey memory vk) internal view returns (bool) { (bool valid, PairingsBn254.G1Point[2] memory recursive_proof_part) = aggregate_for_verification(proof, vk); if (valid == false) { return false; } valid = PairingsBn254.pairingProd2(recursive_proof_part[0], PairingsBn254.P2(), recursive_proof_part[1], vk.g2_x); return valid; } function verify_recursive( Proof memory proof, VerificationKey memory vk, uint256 recursive_vks_root, uint8 max_valid_index, uint8[] memory recursive_vks_indexes, uint256[] memory individual_vks_inputs, uint256[] memory subproofs_limbs ) internal view returns (bool) { (uint256 recursive_input, PairingsBn254.G1Point[2] memory aggregated_g1s) = reconstruct_recursive_public_input( recursive_vks_root, max_valid_index, recursive_vks_indexes, individual_vks_inputs, subproofs_limbs ); assert(recursive_input == proof.input_values[0]); (bool valid, PairingsBn254.G1Point[2] memory recursive_proof_part) = aggregate_for_verification(proof, vk); if (valid == false) { return false; } // aggregated_g1s = inner // recursive_proof_part = outer PairingsBn254.G1Point[2] memory combined = combine_inner_and_outer(aggregated_g1s, recursive_proof_part); valid = PairingsBn254.pairingProd2(combined[0], PairingsBn254.P2(), combined[1], vk.g2_x); return valid; } function combine_inner_and_outer(PairingsBn254.G1Point[2] memory inner, PairingsBn254.G1Point[2] memory outer) internal view returns (PairingsBn254.G1Point[2] memory result) { // reuse the transcript primitive TranscriptLibrary.Transcript memory transcript = TranscriptLibrary.new_transcript(); transcript.update_with_g1(inner[0]); transcript.update_with_g1(inner[1]); transcript.update_with_g1(outer[0]); transcript.update_with_g1(outer[1]); PairingsBn254.Fr memory challenge = transcript.get_challenge(); // 1 * inner + challenge * outer result[0] = PairingsBn254.copy_g1(inner[0]); result[1] = PairingsBn254.copy_g1(inner[1]); PairingsBn254.G1Point memory tmp = outer[0].point_mul(challenge); result[0].point_add_assign(tmp); tmp = outer[1].point_mul(challenge); result[1].point_add_assign(tmp); return result; } function reconstruct_recursive_public_input( uint256 recursive_vks_root, uint8 max_valid_index, uint8[] memory recursive_vks_indexes, uint256[] memory individual_vks_inputs, uint256[] memory subproofs_aggregated ) internal pure returns (uint256 recursive_input, PairingsBn254.G1Point[2] memory reconstructed_g1s) { assert(recursive_vks_indexes.length == individual_vks_inputs.length); bytes memory concatenated = abi.encodePacked(recursive_vks_root); uint8 index; for (uint256 i = 0; i < recursive_vks_indexes.length; i++) { index = recursive_vks_indexes[i]; assert(index <= max_valid_index); concatenated = abi.encodePacked(concatenated, index); } uint256 input; for (uint256 i = 0; i < recursive_vks_indexes.length; i++) { input = individual_vks_inputs[i]; assert(input < r_mod); concatenated = abi.encodePacked(concatenated, input); } concatenated = abi.encodePacked(concatenated, subproofs_aggregated); bytes32 commitment = sha256(concatenated); recursive_input = uint256(commitment) & RECURSIVE_CIRCUIT_INPUT_COMMITMENT_MASK; reconstructed_g1s[0] = PairingsBn254.new_g1_checked( subproofs_aggregated[0] + (subproofs_aggregated[1] << LIMB_WIDTH) + (subproofs_aggregated[2] << 2*LIMB_WIDTH) + (subproofs_aggregated[3] << 3*LIMB_WIDTH), subproofs_aggregated[4] + (subproofs_aggregated[5] << LIMB_WIDTH) + (subproofs_aggregated[6] << 2*LIMB_WIDTH) + (subproofs_aggregated[7] << 3*LIMB_WIDTH) ); reconstructed_g1s[1] = PairingsBn254.new_g1_checked( subproofs_aggregated[8] + (subproofs_aggregated[9] << LIMB_WIDTH) + (subproofs_aggregated[10] << 2*LIMB_WIDTH) + (subproofs_aggregated[11] << 3*LIMB_WIDTH), subproofs_aggregated[12] + (subproofs_aggregated[13] << LIMB_WIDTH) + (subproofs_aggregated[14] << 2*LIMB_WIDTH) + (subproofs_aggregated[15] << 3*LIMB_WIDTH) ); return (recursive_input, reconstructed_g1s); } } contract AggVerifierWithDeserialize is Plonk4AggVerifierWithAccessToDNext { uint256 constant SERIALIZED_PROOF_LENGTH = 34; 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.copy_permutation_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; } for (uint256 i = 0; i < proof.gate_selector_values_at_z.length; i++) { proof.gate_selector_values_at_z[i] = 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.copy_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; 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] ); } function verify_serialized_proof( uint256[] memory public_inputs, uint256[] memory serialized_proof, VerificationKey memory vk ) public view returns (bool) { require(vk.num_inputs == public_inputs.length); Proof memory proof = deserialize_proof(public_inputs, serialized_proof); bool valid = verify(proof, vk); return valid; } function verify_serialized_proof_with_recursion( uint256[] memory public_inputs, uint256[] memory serialized_proof, uint256 recursive_vks_root, uint8 max_valid_index, uint8[] memory recursive_vks_indexes, uint256[] memory individual_vks_inputs, uint256[] memory subproofs_limbs, VerificationKey memory vk ) public view returns (bool) { require(vk.num_inputs == public_inputs.length); Proof memory proof = deserialize_proof(public_inputs, serialized_proof); bool valid = verify_recursive(proof, vk, recursive_vks_root, max_valid_index, recursive_vks_indexes, individual_vks_inputs, subproofs_limbs); return valid; } }
pragma solidity >=0.5.0 <0.7.0; import "./PlonkCoreLib.sol"; contract Plonk4SingleVerifierWithAccessToDNext { 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 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(); state.cached_lagrange_evals = new PairingsBn254.Fr[](1); state.cached_lagrange_evals[0] = evaluate_lagrange_poly_out_of_domain( 0, 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); transcript.update_with_fr(proof.grand_product_at_z_omega); 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 SingleVerifierWithDeserialize is Plonk4SingleVerifierWithAccessToDNext { 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] ); } }
pragma solidity >=0.5.0; interface IUniswapV2ERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); }
pragma solidity =0.5.16; // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library UniswapSafeMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, 'ds-math-add-overflow'); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, 'ds-math-sub-underflow'); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); } }
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}); } }
{ "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "optimizer": { "enabled": true, "runs": 200 } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":true,"internalType":"uint32","name":"totalBlocksVerified","type":"uint32"},{"indexed":true,"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":"uint16","name":"tokenAId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"tokenBId","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"tokenPairId","type":"uint16"},{"indexed":false,"internalType":"address","name":"pair","type":"address"}],"name":"CreatePairCommit","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":true,"internalType":"uint32","name":"blockNumberFrom","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"blockNumberTo","type":"uint32"}],"name":"MultiblockVerification","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":"bytes","name":"userData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"expirationBlock","type":"uint256"}],"name":"NewPriorityRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"NewToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"tokenAId","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"tokenBId","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"pairId","type":"uint16"},{"indexed":false,"internalType":"address","name":"pair","type":"address"}],"name":"OnchainCreatePair","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"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"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":"uint32","name":"_blockNumberFrom","type":"uint32"},{"internalType":"uint32","name":"_blockNumberTo","type":"uint32"},{"internalType":"bytes[]","name":"_withdrawalsData","type":"bytes[]"}],"name":"checkWithdrawals","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":"_blockInfo","type":"uint32[]"},{"internalType":"bytes32[]","name":"_newRootAndCommitment","type":"bytes32[]"},{"internalType":"bytes[]","name":"_publicDatas","type":"bytes[]"},{"internalType":"uint32[]","name":"_ethWitnessSizes","type":"uint32[]"}],"name":"commitMultiBlock","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":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":true,"inputs":[],"name":"maxDepositAmount","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","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":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"swap_exited","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"tokenAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalBlocksChecked","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","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":true,"inputs":[],"name":"totalPairTokens","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"triggerExodusIfNeeded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":true,"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"}],"name":"validatePairTokenAddress","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","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":"uint32","name":"_blockNumberFrom","type":"uint32"},{"internalType":"uint32","name":"_blockNumberTo","type":"uint32"},{"internalType":"uint256[]","name":"_recursiveInput","type":"uint256[]"},{"internalType":"uint256[]","name":"_proof","type":"uint256[]"},{"internalType":"uint256[]","name":"_subProofLimbs","type":"uint256[]"}],"name":"verifyBlocks","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawGasLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"zkSyncCommitBlockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"zkSyncExitAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061567680620000216000396000f3fe60806040526004361061020f5760003560e01c80638ac7d29611610118578063c57b22be116100a0578063e96aa2051161006f578063e96aa20514610638578063fa6b53c314610658578063faf4d8cb14610678578063fc97a3031461068d578063ffeec237146106ad5761020f565b8063c57b22be146105d7578063cc54f026146105ec578063cd24ee081461060e578063e7f40cf6146106235761020f565b8063a2f9f1ce116100e7578063a2f9f1ce14610534578063a6289e5a14610562578063ae91773214610582578063b5d6b8be146105a2578063b7c73165146105b75761020f565b80638ac7d296146104c85780638ae20dc9146104dd5780638ed83271146104fd578063922e14921461051f5761020f565b80633c06e5141161019b5780635cd0783e1161016a5780635cd0783e1461041d57806367708dae1461044f5780636898e6fc146104645780636b27a044146104845780637d490798146104995761020f565b80633c06e5141461039a5780633c6461a9146103af5780634e913cd9146103dd578063595a5ebc146103fd5761020f565b8063241735bb116101e2578063241735bb14610301578063264c0912146103215780632b8c062a146103435780632d24006c1461036357806334f6bb1c146103785761020f565b80630231c02c1461026557806310603dad146102875780631523ab05146102bd57806321ae6054146102df575b6014546001600160a01b0316806102415760405162461bcd60e51b8152600401610238906151d2565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610260573d6000f35b3d6000fd5b34801561027157600080fd5b506102856102803660046140bc565b6106c2565b005b34801561029357600080fd5b506102a76102a2366004614080565b610719565b6040516102b49190614ed2565b60405180910390f35b3480156102c957600080fd5b506102d2610734565b6040516102b49190615401565b3480156102eb57600080fd5b506102f4610747565b6040516102b49190614fa4565b34801561030d57600080fd5b5061028561031c366004613f04565b610759565b34801561032d57600080fd5b50610336610bb7565b6040516102b49190614f96565b34801561034f57600080fd5b5061033661035e366004614141565b610bc0565b34801561036f57600080fd5b506102d2610be0565b34801561038457600080fd5b5061038d610bf3565b6040516102b491906154a5565b3480156103a657600080fd5b506102d2610c09565b3480156103bb57600080fd5b506103cf6103ca366004613ff0565b610c1c565b6040516102b49291906153b0565b3480156103e957600080fd5b506102856103f836600461417f565b610c43565b34801561040957600080fd5b5061028561041836600461402c565b610eeb565b34801561042957600080fd5b5061043d61043836600461409e565b611014565b6040516102b49695949392919061544b565b34801561045b57600080fd5b5061038d61105d565b34801561047057600080fd5b5061028561047f3660046142dc565b61106c565b34801561049057600080fd5b506103366112fc565b3480156104a557600080fd5b506104b96104b4366004614385565b6113a9565b6040516102b493929190615033565b3480156104d457600080fd5b506102f461145d565b3480156104e957600080fd5b506102f46104f8366004613ed4565b611463565b34801561050957600080fd5b50610512611480565b6040516102b491906153a2565b34801561052b57600080fd5b5061033661148f565b34801561054057600080fd5b5061055461054f36600461409e565b611498565b6040516102b4929190614f09565b34801561056e57600080fd5b5061028561057d36600461409e565b6114c0565b34801561058e57600080fd5b5061028561059d366004614275565b611774565b3480156105ae57600080fd5b506102a761195e565b3480156105c357600080fd5b506103366105d2366004614160565b61196d565b3480156105e357600080fd5b5061038d61198d565b3480156105f857600080fd5b506106016119a3565b6040516102b491906153cb565b34801561061a57600080fd5b506102d26119ad565b34801561062f57600080fd5b506102a76119b9565b34801561064457600080fd5b50610601610653366004613e7c565b6119c8565b34801561066457600080fd5b50610512610673366004613e9a565b611a2e565b34801561068457600080fd5b506102d2611a6e565b34801561069957600080fd5b506106016106a8366004613e7c565b611a81565b3480156106b957600080fd5b506102f4611a97565b60008051602061561483398151915254806106ef5760405162461bcd60e51b815260040161023890615352565b60006000805160206156148339815191525560405162461bcd60e51b815260040161023890615182565b6001602052600090815260409020546001600160a01b031681565b600b54600160601b900463ffffffff1681565b6000805160206155f483398151915281565b60008051602061561483398151915254806107865760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152556107a0611a9d565b6000898960008181106107af57fe5b90506020020160206107c4919081019061409e565b905060008a8a60018181106107d557fe5b90506020020160206107ea919081019061409e565b9050600b60109054906101000a900463ffffffff1660010163ffffffff168263ffffffff161461082c5760405162461bcd60e51b815260040161023890615312565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f9061085c903390600401614ee0565b60006040518083038186803b15801561087457600080fd5b505afa158015610888573d6000803e3d6000fd5b506000925050505b8163ffffffff168163ffffffff161015610b975760008c8c8360030163ffffffff168181106108bb57fe5b90506020020160206108d0919081019061409e565b9050606089898460020263ffffffff168181106108e957fe5b602002820190508035601e193684900301811261090557600080fd5b909101602081019150356001600160401b0381111561092357600080fd5b3681900382131561093357600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929350606092508c91508b905063ffffffff600160028802011681811061098757fe5b602002820190508035601e19368490030181126109a357600080fd5b909101602081019150356001600160401b038111156109c157600080fd5b368190038213156109d157600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093945050508786019190508e8e63ffffffff6002890216818110610a2157fe5b90506020020135905060008f8f8860020260010163ffffffff16818110610a4457fe5b90506020020135905060608c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050905060008d8d8a63ffffffff16818110610aa757fe5b9050602002016020610abc919081019061409e565b6012546040805180820190915263ffffffff8881168252838e01166020820152919250600160801b90046001600160401b031690600090610aff908a8a87611ac2565b601254909150600160801b90046001600160401b0316829003610b27888c89898e87876120ae565b600b805463ffffffff60801b198116600160801b9182900463ffffffff908116600101811690920217909155604051908916907f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842490600090a2505060019099019850610890975050505050505050565b505050600160008051602061561483398151915255505050505050505050565b600f5460ff1681565b600d60209081526000928352604080842090915290825290205460ff1681565b600b54600160401b900463ffffffff1681565b601254600160801b90046001600160401b031681565b600b54600160201b900463ffffffff1681565b6009602052600090815260409020546001600160801b03811690600160801b900460ff1682565b6000805160206156148339815191525480610c705760405162461bcd60e51b815260040161023890615352565b600060008051602061561483398151915255610c8a611a9d565b600b60109054906101000a900463ffffffff1660010163ffffffff168b63ffffffff1614610cca5760405162461bcd60e51b815260040161023890615312565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f90610cfa903390600401614ee0565b60006040518083038186803b158015610d1257600080fd5b505afa158015610d26573d6000803e3d6000fd5b505050600189149050610d4b5760405162461bcd60e51b815260040161023890615262565b606087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506000601260109054906101000a90046001600160401b031690506000610e228e848a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525061220892505050565b601254909150600160801b90046001600160401b0316829003610e5a8f8f8f8f600081610e4b57fe5b90506020020135878686612801565b600b601081819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff160217905550508e63ffffffff167f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842460405160405180910390a2505050506001600080516020615614833981519152555050505050505050505050565b6000805160206156148339815191525480610f185760405162461bcd60e51b815260040161023890615352565b60006000805160206156148339815191525560148314610f4a5760405162461bcd60e51b815260040161023890615232565b33600090815260106020908152604080832063ffffffff8616845290915290205415610f885760405162461bcd60e51b815260040161023890615242565b8383604051610f98929190614e3d565b604080519182900382203360008181526010602090815284822063ffffffff8916835290529290922055907f9ea39b45a0cc96a2139996ec8dd30326216111249750781e563ae27c31ae876690610ff49085908890889061540f565b60405180910390a260016000805160206156148339815191525550505050565b600c60205260009081526040902080546001820154600283015460039093015463ffffffff808416946001600160401b03600160201b86041694600160601b9004909116929186565b6012546001600160401b031681565b60008051602061561483398151915254806110995760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152556110b3611a9d565b8763ffffffff168963ffffffff1611156110df5760405162461bcd60e51b815260040161023890615102565b600b60089054906101000a900463ffffffff1660010163ffffffff168963ffffffff161461111f5760405162461bcd60e51b8152600401610238906150e2565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f9061114f903390600401614ee0565b60006040518083038186803b15801561116757600080fd5b505afa15801561117b573d6000803e3d6000fd5b5050505060608061118c8b8b6129b9565b600554604051633bab554560e11b81529294509092506001600160a01b031690637756aa8a906111ce908c908c908c908c90899089908e908e90600401614f24565b60206040518083038186803b1580156111e657600080fd5b505afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061121e9190810190613fd2565b61123a5760405162461bcd60e51b815260040161023890615092565b8a5b8a63ffffffff168163ffffffff16116112865763ffffffff81166000908152600c602052604090205461127e90600160201b90046001600160401b0316612ae2565b60010161123c565b50600b80546bffffffff00000000000000001916600160401b63ffffffff8d811691820292909217909255604051908d16907e20b79376a95828218ec245f1ef8471e6be4610392401a9d295ba435a24564790600090a35050600160008051602061561483398151915255505050505050505050565b6012546001600160401b03166000908152601160205260408120600201548190431080159061134757506012546001600160401b031660009081526011602052604090206002015415155b9050801561139a57600f5460ff1661139057600f805460ff191660011790556040517fc71028c67eb0ef128ea270a59a674629e767d51c1af44ed6753fd2fad2c7b67790600090a15b60019150506113a6565b60009150506113a6565b505b90565b6011602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff90921694929390929083018282801561144d5780601f106114225761010080835404028352916020019161144d565b820191906000526020600020905b81548152906001019060200180831161143057829003601f168201915b5050505050908060020154905083565b60165481565b601060209081526000928352604080842090915290825290205481565b6015546001600160801b031681565b60035460ff1681565b600a602052600090815260409020546001600160a01b03811690600160a01b900461ffff1682565b60008051602061561483398151915254806114ed5760405162461bcd60e51b815260040161023890615352565b600060008051602061561483398151915255611507612c0a565b6115235760405162461bcd60e51b8152600401610238906152d2565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f90611553903390600401614ee0565b60006040518083038186803b15801561156b57600080fd5b505afa15801561157f573d6000803e3d6000fd5b5050600b5463ffffffff600160801b820481169350600092506115ae918691600160401b909104168403612c8f565b600b54909150600090600160801b900463ffffffff168290036001015b8363ffffffff168163ffffffff16116116c0576115e6613c83565b5063ffffffff8082166000908152600c6020908152604091829020825160c08101845281548086168083526001600160401b03600160201b83041694830194909452600160601b900490941692840192909252600182015460608401526002820154608084015260039091015460a08301526116745760405162461bcd60e51b8152600401610238906151c2565b60209081015163ffffffff83166000908152600c9092526040822080546001600160801b03191681556001808201849055600282018490556003909101929092559290920191016115cb565b50600b805463ffffffff600160801b80830482168690038216810263ffffffff60801b199093169290921792839055601280546001600160401b0384820481168790031690930267ffffffffffffffff60801b1990931692909217909155604051948490039481861692600160401b9004909116907f6f3a8259cce1ea2680115053d21c971aa1764295a45850f520525f2bfdf3c9d390600090a35050506001600080516020615614833981519152555050565b60008051602061561483398151915254806117a15760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152558363ffffffff168563ffffffff1611156117df5760405162461bcd60e51b815260040161023890615192565b600b600c9054906101000a900463ffffffff1660010163ffffffff168563ffffffff161461181f5760405162461bcd60e51b815260040161023890615212565b600b5463ffffffff600160401b909104811690851611156118525760405162461bcd60e51b815260040161023890615172565b845b8463ffffffff168163ffffffff161161192057611918848488840363ffffffff1681811061187e57fe5b602002820190508035601e193684900301811261189a57600080fd5b909101602081019150356001600160401b038111156118b857600080fd5b368190038213156118c857600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff87168152600c60205260409020600101549250612cb3915050565b600101611854565b5050600b805463ffffffff909416600160601b0263ffffffff60601b1990941693909317909255505060016000805160206156148339815191525550565b6013546001600160a01b031681565b600e60209081526000928352604080842090915290825290205460ff1681565b601254600160401b90046001600160401b031681565b60005461ffff1681565b600b5463ffffffff1681565b6014546001600160a01b031681565b6001600160a01b03811660009081526002602052604081205461ffff1680611a025760405162461bcd60e51b815260040161023890615222565b61ffff8181161115611a265760405162461bcd60e51b815260040161023890615382565b90505b919050565b600060096000611a3e8585612f4f565b69ffffffffffffffffffff191681526020810191909152604001600020546001600160801b031690505b92915050565b600b54600160801b900463ffffffff1681565b60026020526000908152604090205461ffff1681565b60045481565b600f5460ff1615611ac05760405162461bcd60e51b815260040161023890615322565b565b8251600090600b900615611ae85760405162461bcd60e51b815260040161023890615062565b50601254835160208681015187516000805160206155f483398151915294600160801b81046001600160401b0390811691160193838901938493918a010191600091905b8386101561200f57855160f81c600581600b811115611b4757fe5b1415611b595760169690960195612009565b600081600b811115611b6757fe5b1415611b7957600b9690960195612009565b600281600b811115611b8757fe5b1415611b9957602c9690960195612009565b600981600b811115611ba757fe5b1415611bb95760219690960195612009565b600a81600b811115611bc757fe5b1415611bd95760219690960195612009565b600b81600b811115611be757fe5b1415611bf95760169690960195612009565b858703600182600b811115611c0a57fe5b1415611c7d576060611c218e60018401602b612f6c565b9050611c2b613cb8565b611c3482612ff9565b9050611c408582613086565b611c48613cdf565b50604080518082019091526001815260208101839052611c68818d6130e6565b505060019099019850602c9790970196612007565b600382600b811115611c8b57fe5b1415611cfb57611c99613cf7565b611ca68e836001016132b2565b90506000600190508b81836040015184600001518560200151604051602001611cd3959493929190614fb2565b60408051601f1981840301815291905280516020909101209b50505060379790970196612007565b600682600b811115611d0957fe5b1415611dbf576060611d208e60018401602b612f6c565b9050611d2a613cb8565b611d338261330b565b9050611d3f8582613392565b60008090508c81836020015184604001518560600151604051602001611d69959493929190614fb2565b604051602081830303815290604052805190602001209c50611d89613cdf565b50604080518082019091526006815260208101849052611da9818e6130e6565b50506001909a01995050602c9790970196612007565b600782600b811115611dcd57fe5b1415611f6e578a518463ffffffff1610611df95760405162461bcd60e51b815260040161023890615252565b611e01613cb8565b611e0e8e836001016133e6565b90508b8563ffffffff1681518110611e2257fe5b602002602001015163ffffffff16600014611eb3576060611e6c8e886001600160401b03168f8963ffffffff1681518110611e5957fe5b602002602001015163ffffffff16612f6c565b90506000611e8d82846020015185606001518660400151876000015161345b565b905080611eac5760405162461bcd60e51b815260040161023890615072565b5050611f30565b60008160200151604051602001611eca9190614e02565b60408051601f198184030181529181528151602092830120848201516001600160a01b0316600090815260108452828120606087015163ffffffff16825290935291205414905080611f2e5760405162461bcd60e51b815260040161023890615132565b505b8b8563ffffffff1681518110611f4257fe5b602002602001015163ffffffff16860195508480600101955050600b60050260ff168901985050612007565b600882600b811115611f7c57fe5b1415611fef576060611f938e600184016020612f6c565b9050611f9d613d17565b611fa6826134ef565b9050611fb28582613586565b611fba613cdf565b50604080518082019091526008815260208101839052611fda818d6130e6565b50506001909901985060219790970196612007565b60405162461bcd60e51b815260040161023890615342565b505b50611b2c565b83861461202e5760405162461bcd60e51b8152600401610238906151b2565b6012546001600160401b03808216600160401b9092048116919091018116908816111561206d5760405162461bcd60e51b815260040161023890615372565b5050601280546001600160401b03808216909703909616600160801b0267ffffffffffffffff60801b19909616959095179094555092979650505050505050565b60055460405163e54ee6b160e01b81526001600160a01b039091169063e54ee6b1906120de908990600401615401565b60206040518083038186803b1580156120f657600080fd5b505afa15801561210a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061212e9190810190613fd2565b61214a5760405162461bcd60e51b815260040161023890615112565b6040805160c0810182524363ffffffff90811682526001600160401b039384166020808401918252998216838501908152606084019687526080840198895260a08401998a529a82166000908152600c909a5292909820905181549251995163ffffffff19909316908916176bffffffffffffffff000000001916600160201b99909316989098029190911763ffffffff60601b1916600160601b919096160294909417855550915160018401559051600283015551600390910155565b8251600090600b90061561222e5760405162461bcd60e51b815260040161023890615062565b5060125483516000805160206155f4833981519152916001600160401b03808216600160801b9092041601906020868101918291908801016000805b8285101561271657845160f81c600581600b81111561228557fe5b14156122975760169590950194612710565b600081600b8111156122a557fe5b14156122b757600b9590950194612710565b600281600b8111156122c557fe5b14156122d757602c9590950194612710565b600981600b8111156122e557fe5b14156122f75760219590950194612710565b600a81600b81111561230557fe5b14156123175760219590950194612710565b600b81600b81111561232557fe5b14156123375760169590950194612710565b848603600182600b81111561234857fe5b14156123bb57606061235f8d60018401602b612f6c565b9050612369613cb8565b61237282612ff9565b905061237e8f82613086565b612386613cdf565b506040805180820190915260018152602081018390526123a6818c6130e6565b505060019098019750602c969096019561270e565b600382600b8111156123c957fe5b1415612439576123d7613cf7565b6123e48d836001016132b2565b90506000600190508a81836040015184600001518560200151604051602001612411959493929190614fb2565b60408051601f1981840301815291905280516020909101209a5050506037969096019561270e565b600682600b81111561244757fe5b14156124fd57606061245e8d60018401602b612f6c565b9050612468613cb8565b6124718261330b565b905061247d8f82613392565b60008090508b818360200151846040015185606001516040516020016124a7959493929190614fb2565b604051602081830303815290604052805190602001209b506124c7613cdf565b506040805180820190915260068152602081018490526124e7818d6130e6565b50506001909901985050602c969096019561270e565b600782600b81111561250b57fe5b14156126915789518361ffff16106125355760405162461bcd60e51b815260040161023890615252565b61253d613cb8565b61254a8d836001016133e6565b90508a8461ffff168151811061255c57fe5b602002602001015163ffffffff166000146125d85760606125918d876001600160401b03168e8861ffff1681518110611e5957fe5b905060006125b282846020015185606001518660400151876000015161345b565b9050806125d15760405162461bcd60e51b815260040161023890615072565b5050612655565b600081602001516040516020016125ef9190614e02565b60408051601f198184030181529181528151602092830120848201516001600160a01b0316600090815260108452828120606087015163ffffffff168252909352912054149050806126535760405162461bcd60e51b815260040161023890615132565b505b8a8461ffff168151811061266557fe5b602002602001015163ffffffff16850194508380600101945050600b60050260ff16880197505061270e565b600882600b81111561269f57fe5b1415611fef5760606126b68d600184016020612f6c565b90506126c0613d17565b6126c9826134ef565b90506126d58f82613586565b6126dd613cdf565b506040805180820190915260088152602081018390526126fd818c6130e6565b505060019098019750602196909601955b505b5061226a565b8285146127355760405162461bcd60e51b8152600401610238906151b2565b8851826001600160401b03161461275e5760405162461bcd60e51b815260040161023890615202565b87518161ffff16146127825760405162461bcd60e51b8152600401610238906152a2565b6012546001600160401b03808216600160401b909204811691909101811690871611156127c15760405162461bcd60e51b815260040161023890615372565b5050601280546001600160401b03808216909603909516600160801b0267ffffffffffffffff60801b199095169490941790935550919695505050505050565b8251600b9006156128245760405162461bcd60e51b815260040161023890615392565b825160055460405163e54ee6b160e01b8152600b909204916001600160a01b039091169063e54ee6b19061285c908490600401615401565b60206040518083038186803b15801561287457600080fd5b505afa158015612888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506128ac9190810190613fd2565b6128c85760405162461bcd60e51b815260040161023890615112565b63ffffffff6000198801166000908152600c60205260408120600301546128f4908990899089896135e0565b6040805160c0810182524363ffffffff90811682526001600160401b03968716602080840191825296821683850190815260608401998a526080840195865260a084019b8c529c82166000908152600c909752929095209051815492519b5163ffffffff19909316908616176bffffffffffffffff000000001916600160201b9b9096169a909a029490941763ffffffff60601b1916600160601b94909316939093029190911787555090516001860155516002850155505160039092019190915550565b606080600084840360010190508063ffffffff166040519080825280602002602001820160405280156129f6578160200160208202803883390190505b5092508063ffffffff16604051908082528060200260200182016040528015612a29578160200160208202803883390190505b50915060005b8163ffffffff168163ffffffff161015612ad95763ffffffff86820181166000908152600c60205260409020548551600160601b9091048216918691908416908110612a7757fe5b63ffffffff92831660209182029290920181019190915287830182166000908152600c9091526040902060020154845190916001600160fd1b0391828416918791908616908110612ac457fe5b60209081029190910101525050600101612a2f565b50509250929050565b6012546001600160401b03600160401b90910481169082161115612b185760405162461bcd60e51b8152600401610238906152e2565b6000612b2582600661377d565b6012549091506001600160401b0316805b8282016001600160401b0316816001600160401b03161015612b92576001600160401b0381166000908152601160205260408120805460ff1916815590612b806001830182613d45565b50600060029190910155600101612b36565b505060128054600160801b6001600160401b03600160401b80840482168790038216026fffffffffffffffff000000000000000019909316929092178083168601831667ffffffffffffffff19909116178181048316959095039091160267ffffffffffffffff60801b199093169290921790915550565b600b5460009063ffffffff600160401b82048116600160801b90920416118015612c595750600b54600163ffffffff600160401b90920482160181166000908152600c60205260409020541615155b8015612c8a5750600b54600160401b900463ffffffff90811660010181166000908152600c60205260409020541643115b905090565b60008163ffffffff168363ffffffff1610612caa5781612cac565b825b9392505050565b6027825181612cbe57fe5b0615612cdc5760405162461bcd60e51b8152600401610238906151f2565b600b546000805160206155f483398151915290600090600160201b900463ffffffff165b8451821015612e9b57600080600080612d19898761379e565b93509350935093506000612d2d8484612f4f565b69ffffffffffffffffffff198116600090815260096020526040908190205481518083019092529192506001600160801b039091169080612d74838663ffffffff6137e516565b6001600160801b03908116825260ff602092830181905269ffffffffffffffffffff19861660009081526009845260409020845181549590940151909116600160801b0260ff60801b19939092166001600160801b031990941693909317919091161790558515612e59576040805180820182526001600160a01b03878116825261ffff8781166020808501918252600b5463ffffffff9081168e01166000908152600a909152949094209251835494516001600160a01b031990951692169190911761ffff60a01b1916600160a01b93909116929092029190911790556001909601955b8886868686604051602001612e72959493929190614fb2565b604051602081830303815290604052805190602001209850602788019750505050505050612d00565b838314612eba5760405162461bcd60e51b815260040161023890615272565b600b5463ffffffff828116600160201b9092041614612f2457600b546040517fc4faeb4e73f28a46e4a5fa2db5b89c39698816488534ab7f0717c46f0852c36691612f1b9163ffffffff808316600160201b90930416820191850190615430565b60405180910390a15b600b805463ffffffff909216600160201b0267ffffffff000000001990921691909117905550505050565b60a01b61ffff60a01b166001600160a01b03919091161760501b90565b606081830184511015612f915760405162461bcd60e51b815260040161023890615162565b6060826040519080825280601f01601f191660200182016040528015612fbe576020820181803883390190505b5090508215612ff157602081018381016020860187015b81831015612fed578051835260209283019201612fd5565b5050505b949350505050565b613001613cb8565b600061300d8382613816565b63ffffffff1683529050613021838261382f565b61ffff1660208401529050613036838261383f565b6001600160801b031660408401529050613050838261384f565b6001600160a01b031660608401529050602a81146130805760405162461bcd60e51b815260040161023890615332565b50919050565b806020015161ffff16816000015163ffffffff168363ffffffff167fc4e73a5b67a0594d06ea2b5c311c2aa44aa340dd4dd9ec5a1a718dc391b64470846060015185604001516040516130da929190614eee565b60405180910390a45050565b6001600160401b0381166000908152601160209081526040918290208054600191820180548551600261010095831615959095026000190190911693909304601f810185900485028401850190955284835260ff909116936060938301828280156131925780601f1061316757610100808354040283529160200191613192565b820191906000526020600020905b81548152906001019060200180831161317557829003601f168201915b505050505090508360000151600b8111156131a957fe5b82600b8111156131b557fe5b146131d25760405162461bcd60e51b815260040161023890615292565b60018451600b8111156131e157fe5b1415613216576131f581856020015161385f565b6132115760405162461bcd60e51b815260040161023890615282565b6132ac565b60068451600b81111561322557fe5b14156132555761323981856020015161389e565b6132115760405162461bcd60e51b8152600401610238906150a2565b60088451600b81111561326457fe5b1415613294576132788185602001516138c7565b6132115760405162461bcd60e51b8152600401610238906151e2565b60405162461bcd60e51b8152600401610238906150d2565b50505050565b6132ba613cf7565b600482016132c8848261384f565b6001600160a01b0316604084015290506132e2848261382f565b61ffff16835290506132f4848261383f565b6001600160801b0316602084015250909392505050565b613313613cb8565b600061331f8382613816565b63ffffffff1683529050613333838261384f565b6001600160a01b03166020840152905061334d838261382f565b61ffff1660408401529050613362838261383f565b6001600160801b031660608401529050602a81146130805760405162461bcd60e51b8152600401610238906150b2565b806040015161ffff16816000015163ffffffff168363ffffffff167f66fc63d751ecbefca61d4e2e7c534e4f29c61aed8ece23ed635277a7ea6f9bc4846020015185606001516040516130da929190614eee565b6133ee613cb8565b816133f98482613816565b63ffffffff168352905061340d84826138e9565b6bffffffffffffffffffffffff19166020840152905061342d848261384f565b6001600160a01b0316604084015290506134478482613816565b63ffffffff16606084015250909392505050565b60006060613487866040516020016134739190614e02565b6040516020818303038152906040526138f9565b613498613493876139a3565b6138f9565b6134a4613493866139a3565b6040516020016134b693929190614e56565b604051602081830303815290604052905060006134d388836139b6565b6001600160a01b03868116911614925050505b95945050505050565b6134f7613d17565b60006135038382613816565b63ffffffff1683529050613517838261382f565b61ffff166020840152905061352c838261382f565b61ffff1660408401529050613541838261382f565b61ffff1660608401529050613556838261384f565b6001600160a01b031660808401529050601e81146130805760405162461bcd60e51b8152600401610238906152f2565b806060015161ffff16816000015163ffffffff168363ffffffff167f20c5fd01ebdff8049629c84c58f7230432fc2bfcb1c6393ef01c4d53fd3756a98460200151856040015186608001516040516130da939291906153d9565b60008060028763ffffffff168763ffffffff16604051602001613604929190614e17565b60408051601f198184030181529082905261361e91614e4a565b602060405180830381855afa15801561363b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061365e919081019061400e565b90506002818660001c604051602001613678929190614e17565b60408051601f198184030181529082905261369291614e4a565b602060405180830381855afa1580156136af573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506136d2919081019061400e565b90506002818560001c6040516020016136ec929190614e17565b60408051601f198184030181529082905261370691614e4a565b602060405180830381855afa158015613723573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250613746919081019061400e565b90506040518351828552602082602083018760025afa81865280801561376b5761376d565bfe5b5050905198975050505050505050565b6000816001600160401b0316836001600160401b031610612caa5781612cac565b6000808080846137ae8782613a7d565b955090506137bc878261384f565b945090506137ca878261382f565b935090506137d8878261383f565b9598949750929550505050565b60008282016001600160801b038085169082161015612cac5760405162461bcd60e51b8152600401610238906150f2565b6004810160006138268484613aa9565b90509250929050565b6002810160006138268484613ade565b6010810160006138268484613b08565b6014810160006138268484613b32565b600060606138708460046026612f6c565b905060606138818460046026612f6c565b905080805190602001208280519060200120149250505092915050565b6000806138ac84601a613b5c565b905060006138bb84601a613b5c565b91909114949350505050565b600060606138d8846004601a612f6c565b90506060613881846004601a612f6c565b6014810160006138268484613bb0565b60608082516002026040519080825280601f01601f19166020018201604052801561392b576020820181803883390190505b5090506020830183518101602083015b8183101561399957825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b60018301525060018301925060028101905061393b565b5091949350505050565b6060611a268263ffffffff166004613bdf565b600082516041146139d95760405162461bcd60e51b8152600401610238906151a2565b600080806139e78682613c4e565b935090506139f58682613c4e565b80935081925050506000868281518110613a0b57fe5b602001015160f81c60f81b60f81c90506001868051906020012082868660405160008152602001604052604051613a459493929190614ffe565b6020604051602081039080840390855afa158015613a67573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b600080826001019150838381518110613a9257fe5b0160200151919460f89290921c1515935090915050565b6000808260040190508084511015613ad35760405162461bcd60e51b815260040161023890615152565b929092015192915050565b6000808260020190508084511015613ad35760405162461bcd60e51b815260040161023890615122565b6000808260100190508084511015613ad35760405162461bcd60e51b815260040161023890615302565b6000808260140190508084511015613ad35760405162461bcd60e51b815260040161023890615362565b60006020821115613b7f5760405162461bcd60e51b815260040161023890615082565b8183511015613ba05760405162461bcd60e51b8152600401610238906152c2565b5060209182015191036008021c90565b60008160140183511015613bd65760405162461bcd60e51b8152600401610238906152b2565b50016020015190565b606060208260ff161115613c055760405162461bcd60e51b8152600401610238906150c2565b8160ff166040519080825280601f01601f191660200182016040528015613c33576020820181803883390190505b5060ff6008602094850302169390931b918301919091525090565b60208101600061382684846000808260200190508084511015613ad35760405162461bcd60e51b815260040161023890615142565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051808201909152600081526060602082015290565b604080516060810182526000808252602082018190529181019190915290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b50805460018160011615610100020316600290046000825580601f10613d6b5750613d89565b601f016020900490600052602060002090810190613d899190613d8c565b50565b6113a691905b808211156113a45760008155600101613d92565b8035611a68816155a9565b60008083601f840112613dc357600080fd5b5081356001600160401b03811115613dda57600080fd5b602083019150836020820283011115613df257600080fd5b9250929050565b8051611a68816155bd565b8035611a68816155c6565b8051611a68816155cf565b60008083601f840112613e2c57600080fd5b5081356001600160401b03811115613e4357600080fd5b602083019150836001820283011115613df257600080fd5b8035611a68816155d8565b8035611a68816155e1565b8035611a68816155ea565b600060208284031215613e8e57600080fd5b6000612ff18484613da6565b60008060408385031215613ead57600080fd5b6000613eb98585613da6565b9250506020613eca85828601613e5b565b9150509250929050565b60008060408385031215613ee757600080fd5b6000613ef38585613da6565b9250506020613eca85828601613e66565b6000806000806000806000806080898b031215613f2057600080fd5b88356001600160401b03811115613f3657600080fd5b613f428b828c01613db1565b985098505060208901356001600160401b03811115613f6057600080fd5b613f6c8b828c01613db1565b965096505060408901356001600160401b03811115613f8a57600080fd5b613f968b828c01613db1565b945094505060608901356001600160401b03811115613fb457600080fd5b613fc08b828c01613db1565b92509250509295985092959890939650565b600060208284031215613fe457600080fd5b6000612ff18484613df9565b60006020828403121561400257600080fd5b6000612ff18484613e04565b60006020828403121561402057600080fd5b6000612ff18484613e0f565b60008060006040848603121561404157600080fd5b83356001600160401b0381111561405757600080fd5b61406386828701613e1a565b9350935050602061407686828701613e66565b9150509250925092565b60006020828403121561409257600080fd5b6000612ff18484613e5b565b6000602082840312156140b057600080fd5b6000612ff18484613e66565b6000806000806000606086880312156140d457600080fd5b60006140e08888613e66565b95505060208601356001600160401b038111156140fc57600080fd5b61410888828901613db1565b945094505060408601356001600160401b0381111561412657600080fd5b61413288828901613e1a565b92509250509295509295909350565b6000806040838503121561415457600080fd5b6000613eb98585613e66565b6000806040838503121561417357600080fd5b6000613ef38585613e66565b60008060008060008060008060008060c08b8d03121561419e57600080fd5b60006141aa8d8d613e66565b9a505060206141bb8d828e01613e66565b99505060408b01356001600160401b038111156141d757600080fd5b6141e38d828e01613db1565b985098505060608b01356001600160401b0381111561420157600080fd5b61420d8d828e01613e1a565b965096505060808b01356001600160401b0381111561422b57600080fd5b6142378d828e01613e1a565b945094505060a08b01356001600160401b0381111561425557600080fd5b6142618d828e01613db1565b92509250509295989b9194979a5092959850565b6000806000806060858703121561428b57600080fd5b60006142978787613e66565b94505060206142a887828801613e66565b93505060408501356001600160401b038111156142c457600080fd5b6142d087828801613db1565b95989497509550505050565b60008060008060008060008060a0898b0312156142f857600080fd5b60006143048b8b613e66565b98505060206143158b828c01613e66565b97505060408901356001600160401b0381111561433157600080fd5b61433d8b828c01613db1565b965096505060608901356001600160401b0381111561435b57600080fd5b6143678b828c01613db1565b945094505060808901356001600160401b03811115613fb457600080fd5b60006020828403121561439757600080fd5b6000612ff18484613e71565b60006143af83836144d5565b505060200190565b60006143af8383614de7565b6143cc8161553c565b82525050565b6143cc816154c6565b60006143e783856154bd565b93506001600160fb1b038311156143fd57600080fd5b60208302925061440e83858461555d565b50500190565b600061441f826154b9565b61442981856154bd565b9350614434836154b3565b8060005b8381101561446257815161444c88826143a3565b9750614457836154b3565b925050600101614438565b509495945050505050565b6000614478826154b9565b61448281856154bd565b935061448d836154b3565b8060005b838110156144625781516144a588826143b7565b97506144b0836154b3565b925050600101614491565b6143cc816154d1565b6143cc6144d0826154d6565b6113a6565b6143cc816113a6565b6143cc6144d0826113a6565b60006144f683856154bd565b935061450383858461555d565b61450c83615595565b9093019392505050565b60006145228385611a29565b935061440e83858461555d565b600061453a826154b9565b6145448185611a29565b9350614554818560208601615569565b9290920192915050565b6000614569826154b9565b61457381856154bd565b9350614583818560208601615569565b61450c81615595565b6143cc81615547565b60006145a26005836154bd565b64666373313160d81b815260200192915050565b60006145c36005836154bd565b64667070313560d81b815260200192915050565b60006145e4600183611a29565b600560f91b815260010192915050565b60006146016005836154bd565b64074726d31360dc1b815260200192915050565b60006146226007836154bd565b666d6266766b313360c81b815260200192915050565b60006146456005836154bd565b641d9b9c0c4d60da1b815260200192915050565b60006146666005836154bd565b64072667031360dc1b815260200192915050565b60006146876005836154bd565b64627432313160d81b815260200192915050565b60006146a8601d83611a29565b7f19457468657265756d205369676e6564204d6573736167653a0a3135320000008152601d0192915050565b60006146e16005836154bd565b643b3738189b60d91b815260200192915050565b60006147026007836154bd565b666d6266766b313160c81b815260200192915050565b6000614725601b836154bd565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061475e6005836154bd565b64766273313160d81b815260200192915050565b600061477f6005836154bd565b64636362313160d81b815260200192915050565b60006147a06005836154bd565b64313a3a981960d91b815260200192915050565b60006147c16005836154bd565b64333838189b60d91b815260200192915050565b60006147e26005836154bd565b64313a31199960d91b815260200192915050565b60006148036005836154bd565b64189d1d4c0d60da1b815260200192915050565b60006148246005836154bd565b64627365313160d81b815260200192915050565b60006148456003836154bd565b6263773360e81b815260200192915050565b60006148646003836154bd565b6266623160e81b815260200192915050565b6000614883600983611a29565b680dcdedcc6ca744060f60bb1b815260090192915050565b60006148a86003836154bd565b6263773160e81b815260200192915050565b60006148c76005836154bd565b64076657331360dc1b815260200192915050565b60006148e86005836154bd565b643331b9989960d91b815260200192915050565b60006149096005836154bd565b6466726b313160d81b815260200192915050565b600061492a601f836154bd565b7f7a6b53796e6345786974416464726573732073686f756c642062652073657400815260200192915050565b60006149636005836154bd565b64766e70313560d81b815260200192915050565b60006149846005836154bd565b64706f77313160d81b815260200192915050565b60006149a56005836154bd565b641998dccc4d60da1b815260200192915050565b60006149c6600283611a29565b61050560f11b815260020192915050565b60006149e4602c83611a29565b7f4f6e6c79207369676e2074686973206d65737361676520666f7220612074727581526b7374656420636c69656e742160a01b6020820152602c0192915050565b6000614a326003836154bd565b6231bb9960e91b815260200192915050565b6000614a516004836154bd565b63706d733360e01b815260200192915050565b6000614a716005836154bd565b64061686631360dc1b815260200192915050565b6000614a926005836154bd565b64616866313160d81b815260200192915050565b6000614ab36005836154bd565b64666373313360d81b815260200192915050565b6000614ad46005836154bd565b6466636b313360d81b815260200192915050565b6000614af56005836154bd565b643837bb989960d91b815260200192915050565b6000614b16600e83611a29565b6d0c2c6c6deeadce840d2c8744060f60931b8152600e0192915050565b6000614b406005836154bd565b64766e70313360d81b815260200192915050565b6000614b616005836154bd565b64373b38189960d91b815260200192915050565b6000614b826005836154bd565b64666373313560d81b815260200192915050565b6000614ba36005836154bd565b64062746232360dc1b815260200192915050565b6000614bc46005836154bd565b6474726d313160d81b815260200192915050565b6000614be56005836154bd565b64726273313160d81b815260200192915050565b6000614c066005836154bd565b64706373323160d81b815260200192915050565b6000614c276005836154bd565b64072637031360dc1b815260200192915050565b6000614c486005836154bd565b64313a3a989b60d91b815260200192915050565b6000614c696005836154bd565b6466636b313160d81b815260200192915050565b6000614c8a6005836154bd565b64667265313160d81b815260200192915050565b6000614cab6005836154bd565b64072647031360dc1b815260200192915050565b6000614ccc6005836154bd565b64199c1c0c4d60da1b815260200192915050565b6000614ced601f836154bd565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00815260200192915050565b6000614d266005836154bd565b64627461313160d81b815260200192915050565b6000614d476005836154bd565b643331b9989b60d91b815260200192915050565b6000614d686004836154bd565b631c1b5ccd60e21b815260200192915050565b6000614d88601983611a29565b7f5265676973746572205a4b53776170207075626b65793a0a0a00000000000000815260190192915050565b6000614dc16005836154bd565b64063626231360dc1b815260200192915050565b6143cc81615502565b6143cc8161550e565b6143cc81615521565b6143cc8161552a565b6143cc81615536565b6000614e0e82846144c4565b50601401919050565b6000614e2382856144de565b602082019150614e3382846144de565b5060200192915050565b6000612ff1828486614516565b6000612cac828461452f565b6000614e618261469b565b9150614e6c82614d7b565b9150614e78828661452f565b9150614e83826145d7565b9150614e8e82614876565b9150614e9a828561452f565b9150614ea5826145d7565b9150614eb082614b09565b9150614ebc828461452f565b9150614ec7826149b9565b91506134e6826149d7565b60208101611a6882846143d2565b60208101611a6882846143c3565b60408101614efc82856143d2565b612cac6020830184614dd5565b60408101614f1782856143d2565b612cac6020830184614dde565b60a08082528101614f36818a8c6143db565b90508181036020830152614f4b81888a6143db565b90508181036040830152614f5f818761446d565b90508181036060830152614f738186614414565b90508181036080830152614f888184866143db565b9a9950505050505050505050565b60208101611a6882846144bb565b60208101611a6882846144d5565b60a08101614fc082886144d5565b614fcd60208301876144bb565b614fda60408301866143d2565b614fe76060830185614dde565b614ff46080830184614dd5565b9695505050505050565b6080810161500c82876144d5565b6150196020830186614df9565b61502660408301856144d5565b6134e660608301846144d5565b60608101615041828661458c565b8181036020830152615053818561455e565b9050612ff160408301846144d5565b60208082528101611a2681614595565b60208082528101611a26816145b6565b60208082528101611a26816145f4565b60208082528101611a2681614615565b60208082528101611a2681614638565b60208082528101611a2681614659565b60208082528101611a268161467a565b60208082528101611a26816146d4565b60208082528101611a26816146f5565b60208082528101611a2681614718565b60208082528101611a2681614751565b60208082528101611a2681614772565b60208082528101611a2681614793565b60208082528101611a26816147b4565b60208082528101611a26816147d5565b60208082528101611a26816147f6565b60208082528101611a2681614817565b60208082528101611a2681614838565b60208082528101611a2681614857565b60208082528101611a268161489b565b60208082528101611a26816148ba565b60208082528101611a26816148db565b60208082528101611a26816148fc565b60208082528101611a268161491d565b60208082528101611a2681614956565b60208082528101611a2681614977565b60208082528101611a2681614998565b60208082528101611a2681614a25565b60208082528101611a2681614a44565b60208082528101611a2681614a64565b60208082528101611a2681614a85565b60208082528101611a2681614aa6565b60208082528101611a2681614ac7565b60208082528101611a2681614ae8565b60208082528101611a2681614b33565b60208082528101611a2681614b54565b60208082528101611a2681614b75565b60208082528101611a2681614b96565b60208082528101611a2681614bb7565b60208082528101611a2681614bd8565b60208082528101611a2681614bf9565b60208082528101611a2681614c1a565b60208082528101611a2681614c3b565b60208082528101611a2681614c5c565b60208082528101611a2681614c7d565b60208082528101611a2681614c9e565b60208082528101611a2681614cbf565b60208082528101611a2681614ce0565b60208082528101611a2681614d19565b60208082528101611a2681614d3a565b60208082528101611a2681614d5b565b60208082528101611a2681614db4565b60208101611a688284614dd5565b604081016153be8285614dd5565b612cac6020830184614df9565b60208101611a688284614dde565b606081016153e78286614dde565b6153f46020830185614dde565b612ff160408301846143d2565b60208101611a688284614de7565b6040810161541d8286614de7565b81810360208301526134e68184866144ea565b6040810161543e8285614de7565b612cac6020830184614de7565b60c081016154598289614de7565b6154666020830188614df0565b6154736040830187614de7565b61548060608301866144d5565b61548d60808301856144d5565b61549a60a08301846144d5565b979650505050505050565b60208101611a688284614df0565b60200190565b5190565b90815260200190565b6000611a2682615515565b151590565b6bffffffffffffffffffffffff191690565b69ffffffffffffffffffff191690565b80611a298161559f565b6001600160801b031690565b61ffff1690565b6001600160a01b031690565b63ffffffff1690565b6001600160401b031690565b60ff1690565b6000611a2682615552565b6000611a26826154f8565b6000611a26826154c6565b82818337506000910152565b60005b8381101561558457818101518382015260200161556c565b838111156132ac5750506000910152565b601f01601f191690565b600c8110613d8957fe5b6155b2816154c6565b8114613d8957600080fd5b6155b2816154d1565b6155b2816154e8565b6155b2816113a6565b6155b28161550e565b6155b281615521565b6155b28161552a56fec5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4a365627a7a72315820e2d12ac9a23b5013fb0cda7f6a0ed023fb77d48a6c162cd292ea1c9d250c426a6c6578706572696d656e74616cf564736f6c63430005100040
Deployed Bytecode
0x60806040526004361061020f5760003560e01c80638ac7d29611610118578063c57b22be116100a0578063e96aa2051161006f578063e96aa20514610638578063fa6b53c314610658578063faf4d8cb14610678578063fc97a3031461068d578063ffeec237146106ad5761020f565b8063c57b22be146105d7578063cc54f026146105ec578063cd24ee081461060e578063e7f40cf6146106235761020f565b8063a2f9f1ce116100e7578063a2f9f1ce14610534578063a6289e5a14610562578063ae91773214610582578063b5d6b8be146105a2578063b7c73165146105b75761020f565b80638ac7d296146104c85780638ae20dc9146104dd5780638ed83271146104fd578063922e14921461051f5761020f565b80633c06e5141161019b5780635cd0783e1161016a5780635cd0783e1461041d57806367708dae1461044f5780636898e6fc146104645780636b27a044146104845780637d490798146104995761020f565b80633c06e5141461039a5780633c6461a9146103af5780634e913cd9146103dd578063595a5ebc146103fd5761020f565b8063241735bb116101e2578063241735bb14610301578063264c0912146103215780632b8c062a146103435780632d24006c1461036357806334f6bb1c146103785761020f565b80630231c02c1461026557806310603dad146102875780631523ab05146102bd57806321ae6054146102df575b6014546001600160a01b0316806102415760405162461bcd60e51b8152600401610238906151d2565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610260573d6000f35b3d6000fd5b34801561027157600080fd5b506102856102803660046140bc565b6106c2565b005b34801561029357600080fd5b506102a76102a2366004614080565b610719565b6040516102b49190614ed2565b60405180910390f35b3480156102c957600080fd5b506102d2610734565b6040516102b49190615401565b3480156102eb57600080fd5b506102f4610747565b6040516102b49190614fa4565b34801561030d57600080fd5b5061028561031c366004613f04565b610759565b34801561032d57600080fd5b50610336610bb7565b6040516102b49190614f96565b34801561034f57600080fd5b5061033661035e366004614141565b610bc0565b34801561036f57600080fd5b506102d2610be0565b34801561038457600080fd5b5061038d610bf3565b6040516102b491906154a5565b3480156103a657600080fd5b506102d2610c09565b3480156103bb57600080fd5b506103cf6103ca366004613ff0565b610c1c565b6040516102b49291906153b0565b3480156103e957600080fd5b506102856103f836600461417f565b610c43565b34801561040957600080fd5b5061028561041836600461402c565b610eeb565b34801561042957600080fd5b5061043d61043836600461409e565b611014565b6040516102b49695949392919061544b565b34801561045b57600080fd5b5061038d61105d565b34801561047057600080fd5b5061028561047f3660046142dc565b61106c565b34801561049057600080fd5b506103366112fc565b3480156104a557600080fd5b506104b96104b4366004614385565b6113a9565b6040516102b493929190615033565b3480156104d457600080fd5b506102f461145d565b3480156104e957600080fd5b506102f46104f8366004613ed4565b611463565b34801561050957600080fd5b50610512611480565b6040516102b491906153a2565b34801561052b57600080fd5b5061033661148f565b34801561054057600080fd5b5061055461054f36600461409e565b611498565b6040516102b4929190614f09565b34801561056e57600080fd5b5061028561057d36600461409e565b6114c0565b34801561058e57600080fd5b5061028561059d366004614275565b611774565b3480156105ae57600080fd5b506102a761195e565b3480156105c357600080fd5b506103366105d2366004614160565b61196d565b3480156105e357600080fd5b5061038d61198d565b3480156105f857600080fd5b506106016119a3565b6040516102b491906153cb565b34801561061a57600080fd5b506102d26119ad565b34801561062f57600080fd5b506102a76119b9565b34801561064457600080fd5b50610601610653366004613e7c565b6119c8565b34801561066457600080fd5b50610512610673366004613e9a565b611a2e565b34801561068457600080fd5b506102d2611a6e565b34801561069957600080fd5b506106016106a8366004613e7c565b611a81565b3480156106b957600080fd5b506102f4611a97565b60008051602061561483398151915254806106ef5760405162461bcd60e51b815260040161023890615352565b60006000805160206156148339815191525560405162461bcd60e51b815260040161023890615182565b6001602052600090815260409020546001600160a01b031681565b600b54600160601b900463ffffffff1681565b6000805160206155f483398151915281565b60008051602061561483398151915254806107865760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152556107a0611a9d565b6000898960008181106107af57fe5b90506020020160206107c4919081019061409e565b905060008a8a60018181106107d557fe5b90506020020160206107ea919081019061409e565b9050600b60109054906101000a900463ffffffff1660010163ffffffff168263ffffffff161461082c5760405162461bcd60e51b815260040161023890615312565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f9061085c903390600401614ee0565b60006040518083038186803b15801561087457600080fd5b505afa158015610888573d6000803e3d6000fd5b506000925050505b8163ffffffff168163ffffffff161015610b975760008c8c8360030163ffffffff168181106108bb57fe5b90506020020160206108d0919081019061409e565b9050606089898460020263ffffffff168181106108e957fe5b602002820190508035601e193684900301811261090557600080fd5b909101602081019150356001600160401b0381111561092357600080fd5b3681900382131561093357600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929350606092508c91508b905063ffffffff600160028802011681811061098757fe5b602002820190508035601e19368490030181126109a357600080fd5b909101602081019150356001600160401b038111156109c157600080fd5b368190038213156109d157600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093945050508786019190508e8e63ffffffff6002890216818110610a2157fe5b90506020020135905060008f8f8860020260010163ffffffff16818110610a4457fe5b90506020020135905060608c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050905060008d8d8a63ffffffff16818110610aa757fe5b9050602002016020610abc919081019061409e565b6012546040805180820190915263ffffffff8881168252838e01166020820152919250600160801b90046001600160401b031690600090610aff908a8a87611ac2565b601254909150600160801b90046001600160401b0316829003610b27888c89898e87876120ae565b600b805463ffffffff60801b198116600160801b9182900463ffffffff908116600101811690920217909155604051908916907f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842490600090a2505060019099019850610890975050505050505050565b505050600160008051602061561483398151915255505050505050505050565b600f5460ff1681565b600d60209081526000928352604080842090915290825290205460ff1681565b600b54600160401b900463ffffffff1681565b601254600160801b90046001600160401b031681565b600b54600160201b900463ffffffff1681565b6009602052600090815260409020546001600160801b03811690600160801b900460ff1682565b6000805160206156148339815191525480610c705760405162461bcd60e51b815260040161023890615352565b600060008051602061561483398151915255610c8a611a9d565b600b60109054906101000a900463ffffffff1660010163ffffffff168b63ffffffff1614610cca5760405162461bcd60e51b815260040161023890615312565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f90610cfa903390600401614ee0565b60006040518083038186803b158015610d1257600080fd5b505afa158015610d26573d6000803e3d6000fd5b505050600189149050610d4b5760405162461bcd60e51b815260040161023890615262565b606087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506000601260109054906101000a90046001600160401b031690506000610e228e848a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c91829185019084908082843760009201919091525061220892505050565b601254909150600160801b90046001600160401b0316829003610e5a8f8f8f8f600081610e4b57fe5b90506020020135878686612801565b600b601081819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff160217905550508e63ffffffff167f81a92942d0f9c33b897a438384c9c3d88be397776138efa3ba1a4fc8b626842460405160405180910390a2505050506001600080516020615614833981519152555050505050505050505050565b6000805160206156148339815191525480610f185760405162461bcd60e51b815260040161023890615352565b60006000805160206156148339815191525560148314610f4a5760405162461bcd60e51b815260040161023890615232565b33600090815260106020908152604080832063ffffffff8616845290915290205415610f885760405162461bcd60e51b815260040161023890615242565b8383604051610f98929190614e3d565b604080519182900382203360008181526010602090815284822063ffffffff8916835290529290922055907f9ea39b45a0cc96a2139996ec8dd30326216111249750781e563ae27c31ae876690610ff49085908890889061540f565b60405180910390a260016000805160206156148339815191525550505050565b600c60205260009081526040902080546001820154600283015460039093015463ffffffff808416946001600160401b03600160201b86041694600160601b9004909116929186565b6012546001600160401b031681565b60008051602061561483398151915254806110995760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152556110b3611a9d565b8763ffffffff168963ffffffff1611156110df5760405162461bcd60e51b815260040161023890615102565b600b60089054906101000a900463ffffffff1660010163ffffffff168963ffffffff161461111f5760405162461bcd60e51b8152600401610238906150e2565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f9061114f903390600401614ee0565b60006040518083038186803b15801561116757600080fd5b505afa15801561117b573d6000803e3d6000fd5b5050505060608061118c8b8b6129b9565b600554604051633bab554560e11b81529294509092506001600160a01b031690637756aa8a906111ce908c908c908c908c90899089908e908e90600401614f24565b60206040518083038186803b1580156111e657600080fd5b505afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061121e9190810190613fd2565b61123a5760405162461bcd60e51b815260040161023890615092565b8a5b8a63ffffffff168163ffffffff16116112865763ffffffff81166000908152600c602052604090205461127e90600160201b90046001600160401b0316612ae2565b60010161123c565b50600b80546bffffffff00000000000000001916600160401b63ffffffff8d811691820292909217909255604051908d16907e20b79376a95828218ec245f1ef8471e6be4610392401a9d295ba435a24564790600090a35050600160008051602061561483398151915255505050505050505050565b6012546001600160401b03166000908152601160205260408120600201548190431080159061134757506012546001600160401b031660009081526011602052604090206002015415155b9050801561139a57600f5460ff1661139057600f805460ff191660011790556040517fc71028c67eb0ef128ea270a59a674629e767d51c1af44ed6753fd2fad2c7b67790600090a15b60019150506113a6565b60009150506113a6565b505b90565b6011602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f810186900486028301860190965285825260ff90921694929390929083018282801561144d5780601f106114225761010080835404028352916020019161144d565b820191906000526020600020905b81548152906001019060200180831161143057829003601f168201915b5050505050908060020154905083565b60165481565b601060209081526000928352604080842090915290825290205481565b6015546001600160801b031681565b60035460ff1681565b600a602052600090815260409020546001600160a01b03811690600160a01b900461ffff1682565b60008051602061561483398151915254806114ed5760405162461bcd60e51b815260040161023890615352565b600060008051602061561483398151915255611507612c0a565b6115235760405162461bcd60e51b8152600401610238906152d2565b600754604051634b18bd0f60e01b81526001600160a01b0390911690634b18bd0f90611553903390600401614ee0565b60006040518083038186803b15801561156b57600080fd5b505afa15801561157f573d6000803e3d6000fd5b5050600b5463ffffffff600160801b820481169350600092506115ae918691600160401b909104168403612c8f565b600b54909150600090600160801b900463ffffffff168290036001015b8363ffffffff168163ffffffff16116116c0576115e6613c83565b5063ffffffff8082166000908152600c6020908152604091829020825160c08101845281548086168083526001600160401b03600160201b83041694830194909452600160601b900490941692840192909252600182015460608401526002820154608084015260039091015460a08301526116745760405162461bcd60e51b8152600401610238906151c2565b60209081015163ffffffff83166000908152600c9092526040822080546001600160801b03191681556001808201849055600282018490556003909101929092559290920191016115cb565b50600b805463ffffffff600160801b80830482168690038216810263ffffffff60801b199093169290921792839055601280546001600160401b0384820481168790031690930267ffffffffffffffff60801b1990931692909217909155604051948490039481861692600160401b9004909116907f6f3a8259cce1ea2680115053d21c971aa1764295a45850f520525f2bfdf3c9d390600090a35050506001600080516020615614833981519152555050565b60008051602061561483398151915254806117a15760405162461bcd60e51b815260040161023890615352565b6000600080516020615614833981519152558363ffffffff168563ffffffff1611156117df5760405162461bcd60e51b815260040161023890615192565b600b600c9054906101000a900463ffffffff1660010163ffffffff168563ffffffff161461181f5760405162461bcd60e51b815260040161023890615212565b600b5463ffffffff600160401b909104811690851611156118525760405162461bcd60e51b815260040161023890615172565b845b8463ffffffff168163ffffffff161161192057611918848488840363ffffffff1681811061187e57fe5b602002820190508035601e193684900301811261189a57600080fd5b909101602081019150356001600160401b038111156118b857600080fd5b368190038213156118c857600080fd5b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525063ffffffff87168152600c60205260409020600101549250612cb3915050565b600101611854565b5050600b805463ffffffff909416600160601b0263ffffffff60601b1990941693909317909255505060016000805160206156148339815191525550565b6013546001600160a01b031681565b600e60209081526000928352604080842090915290825290205460ff1681565b601254600160401b90046001600160401b031681565b60005461ffff1681565b600b5463ffffffff1681565b6014546001600160a01b031681565b6001600160a01b03811660009081526002602052604081205461ffff1680611a025760405162461bcd60e51b815260040161023890615222565b61ffff8181161115611a265760405162461bcd60e51b815260040161023890615382565b90505b919050565b600060096000611a3e8585612f4f565b69ffffffffffffffffffff191681526020810191909152604001600020546001600160801b031690505b92915050565b600b54600160801b900463ffffffff1681565b60026020526000908152604090205461ffff1681565b60045481565b600f5460ff1615611ac05760405162461bcd60e51b815260040161023890615322565b565b8251600090600b900615611ae85760405162461bcd60e51b815260040161023890615062565b50601254835160208681015187516000805160206155f483398151915294600160801b81046001600160401b0390811691160193838901938493918a010191600091905b8386101561200f57855160f81c600581600b811115611b4757fe5b1415611b595760169690960195612009565b600081600b811115611b6757fe5b1415611b7957600b9690960195612009565b600281600b811115611b8757fe5b1415611b9957602c9690960195612009565b600981600b811115611ba757fe5b1415611bb95760219690960195612009565b600a81600b811115611bc757fe5b1415611bd95760219690960195612009565b600b81600b811115611be757fe5b1415611bf95760169690960195612009565b858703600182600b811115611c0a57fe5b1415611c7d576060611c218e60018401602b612f6c565b9050611c2b613cb8565b611c3482612ff9565b9050611c408582613086565b611c48613cdf565b50604080518082019091526001815260208101839052611c68818d6130e6565b505060019099019850602c9790970196612007565b600382600b811115611c8b57fe5b1415611cfb57611c99613cf7565b611ca68e836001016132b2565b90506000600190508b81836040015184600001518560200151604051602001611cd3959493929190614fb2565b60408051601f1981840301815291905280516020909101209b50505060379790970196612007565b600682600b811115611d0957fe5b1415611dbf576060611d208e60018401602b612f6c565b9050611d2a613cb8565b611d338261330b565b9050611d3f8582613392565b60008090508c81836020015184604001518560600151604051602001611d69959493929190614fb2565b604051602081830303815290604052805190602001209c50611d89613cdf565b50604080518082019091526006815260208101849052611da9818e6130e6565b50506001909a01995050602c9790970196612007565b600782600b811115611dcd57fe5b1415611f6e578a518463ffffffff1610611df95760405162461bcd60e51b815260040161023890615252565b611e01613cb8565b611e0e8e836001016133e6565b90508b8563ffffffff1681518110611e2257fe5b602002602001015163ffffffff16600014611eb3576060611e6c8e886001600160401b03168f8963ffffffff1681518110611e5957fe5b602002602001015163ffffffff16612f6c565b90506000611e8d82846020015185606001518660400151876000015161345b565b905080611eac5760405162461bcd60e51b815260040161023890615072565b5050611f30565b60008160200151604051602001611eca9190614e02565b60408051601f198184030181529181528151602092830120848201516001600160a01b0316600090815260108452828120606087015163ffffffff16825290935291205414905080611f2e5760405162461bcd60e51b815260040161023890615132565b505b8b8563ffffffff1681518110611f4257fe5b602002602001015163ffffffff16860195508480600101955050600b60050260ff168901985050612007565b600882600b811115611f7c57fe5b1415611fef576060611f938e600184016020612f6c565b9050611f9d613d17565b611fa6826134ef565b9050611fb28582613586565b611fba613cdf565b50604080518082019091526008815260208101839052611fda818d6130e6565b50506001909901985060219790970196612007565b60405162461bcd60e51b815260040161023890615342565b505b50611b2c565b83861461202e5760405162461bcd60e51b8152600401610238906151b2565b6012546001600160401b03808216600160401b9092048116919091018116908816111561206d5760405162461bcd60e51b815260040161023890615372565b5050601280546001600160401b03808216909703909616600160801b0267ffffffffffffffff60801b19909616959095179094555092979650505050505050565b60055460405163e54ee6b160e01b81526001600160a01b039091169063e54ee6b1906120de908990600401615401565b60206040518083038186803b1580156120f657600080fd5b505afa15801561210a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061212e9190810190613fd2565b61214a5760405162461bcd60e51b815260040161023890615112565b6040805160c0810182524363ffffffff90811682526001600160401b039384166020808401918252998216838501908152606084019687526080840198895260a08401998a529a82166000908152600c909a5292909820905181549251995163ffffffff19909316908916176bffffffffffffffff000000001916600160201b99909316989098029190911763ffffffff60601b1916600160601b919096160294909417855550915160018401559051600283015551600390910155565b8251600090600b90061561222e5760405162461bcd60e51b815260040161023890615062565b5060125483516000805160206155f4833981519152916001600160401b03808216600160801b9092041601906020868101918291908801016000805b8285101561271657845160f81c600581600b81111561228557fe5b14156122975760169590950194612710565b600081600b8111156122a557fe5b14156122b757600b9590950194612710565b600281600b8111156122c557fe5b14156122d757602c9590950194612710565b600981600b8111156122e557fe5b14156122f75760219590950194612710565b600a81600b81111561230557fe5b14156123175760219590950194612710565b600b81600b81111561232557fe5b14156123375760169590950194612710565b848603600182600b81111561234857fe5b14156123bb57606061235f8d60018401602b612f6c565b9050612369613cb8565b61237282612ff9565b905061237e8f82613086565b612386613cdf565b506040805180820190915260018152602081018390526123a6818c6130e6565b505060019098019750602c969096019561270e565b600382600b8111156123c957fe5b1415612439576123d7613cf7565b6123e48d836001016132b2565b90506000600190508a81836040015184600001518560200151604051602001612411959493929190614fb2565b60408051601f1981840301815291905280516020909101209a5050506037969096019561270e565b600682600b81111561244757fe5b14156124fd57606061245e8d60018401602b612f6c565b9050612468613cb8565b6124718261330b565b905061247d8f82613392565b60008090508b818360200151846040015185606001516040516020016124a7959493929190614fb2565b604051602081830303815290604052805190602001209b506124c7613cdf565b506040805180820190915260068152602081018490526124e7818d6130e6565b50506001909901985050602c969096019561270e565b600782600b81111561250b57fe5b14156126915789518361ffff16106125355760405162461bcd60e51b815260040161023890615252565b61253d613cb8565b61254a8d836001016133e6565b90508a8461ffff168151811061255c57fe5b602002602001015163ffffffff166000146125d85760606125918d876001600160401b03168e8861ffff1681518110611e5957fe5b905060006125b282846020015185606001518660400151876000015161345b565b9050806125d15760405162461bcd60e51b815260040161023890615072565b5050612655565b600081602001516040516020016125ef9190614e02565b60408051601f198184030181529181528151602092830120848201516001600160a01b0316600090815260108452828120606087015163ffffffff168252909352912054149050806126535760405162461bcd60e51b815260040161023890615132565b505b8a8461ffff168151811061266557fe5b602002602001015163ffffffff16850194508380600101945050600b60050260ff16880197505061270e565b600882600b81111561269f57fe5b1415611fef5760606126b68d600184016020612f6c565b90506126c0613d17565b6126c9826134ef565b90506126d58f82613586565b6126dd613cdf565b506040805180820190915260088152602081018390526126fd818c6130e6565b505060019098019750602196909601955b505b5061226a565b8285146127355760405162461bcd60e51b8152600401610238906151b2565b8851826001600160401b03161461275e5760405162461bcd60e51b815260040161023890615202565b87518161ffff16146127825760405162461bcd60e51b8152600401610238906152a2565b6012546001600160401b03808216600160401b909204811691909101811690871611156127c15760405162461bcd60e51b815260040161023890615372565b5050601280546001600160401b03808216909603909516600160801b0267ffffffffffffffff60801b199095169490941790935550919695505050505050565b8251600b9006156128245760405162461bcd60e51b815260040161023890615392565b825160055460405163e54ee6b160e01b8152600b909204916001600160a01b039091169063e54ee6b19061285c908490600401615401565b60206040518083038186803b15801561287457600080fd5b505afa158015612888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506128ac9190810190613fd2565b6128c85760405162461bcd60e51b815260040161023890615112565b63ffffffff6000198801166000908152600c60205260408120600301546128f4908990899089896135e0565b6040805160c0810182524363ffffffff90811682526001600160401b03968716602080840191825296821683850190815260608401998a526080840195865260a084019b8c529c82166000908152600c909752929095209051815492519b5163ffffffff19909316908616176bffffffffffffffff000000001916600160201b9b9096169a909a029490941763ffffffff60601b1916600160601b94909316939093029190911787555090516001860155516002850155505160039092019190915550565b606080600084840360010190508063ffffffff166040519080825280602002602001820160405280156129f6578160200160208202803883390190505b5092508063ffffffff16604051908082528060200260200182016040528015612a29578160200160208202803883390190505b50915060005b8163ffffffff168163ffffffff161015612ad95763ffffffff86820181166000908152600c60205260409020548551600160601b9091048216918691908416908110612a7757fe5b63ffffffff92831660209182029290920181019190915287830182166000908152600c9091526040902060020154845190916001600160fd1b0391828416918791908616908110612ac457fe5b60209081029190910101525050600101612a2f565b50509250929050565b6012546001600160401b03600160401b90910481169082161115612b185760405162461bcd60e51b8152600401610238906152e2565b6000612b2582600661377d565b6012549091506001600160401b0316805b8282016001600160401b0316816001600160401b03161015612b92576001600160401b0381166000908152601160205260408120805460ff1916815590612b806001830182613d45565b50600060029190910155600101612b36565b505060128054600160801b6001600160401b03600160401b80840482168790038216026fffffffffffffffff000000000000000019909316929092178083168601831667ffffffffffffffff19909116178181048316959095039091160267ffffffffffffffff60801b199093169290921790915550565b600b5460009063ffffffff600160401b82048116600160801b90920416118015612c595750600b54600163ffffffff600160401b90920482160181166000908152600c60205260409020541615155b8015612c8a5750600b54600160401b900463ffffffff90811660010181166000908152600c60205260409020541643115b905090565b60008163ffffffff168363ffffffff1610612caa5781612cac565b825b9392505050565b6027825181612cbe57fe5b0615612cdc5760405162461bcd60e51b8152600401610238906151f2565b600b546000805160206155f483398151915290600090600160201b900463ffffffff165b8451821015612e9b57600080600080612d19898761379e565b93509350935093506000612d2d8484612f4f565b69ffffffffffffffffffff198116600090815260096020526040908190205481518083019092529192506001600160801b039091169080612d74838663ffffffff6137e516565b6001600160801b03908116825260ff602092830181905269ffffffffffffffffffff19861660009081526009845260409020845181549590940151909116600160801b0260ff60801b19939092166001600160801b031990941693909317919091161790558515612e59576040805180820182526001600160a01b03878116825261ffff8781166020808501918252600b5463ffffffff9081168e01166000908152600a909152949094209251835494516001600160a01b031990951692169190911761ffff60a01b1916600160a01b93909116929092029190911790556001909601955b8886868686604051602001612e72959493929190614fb2565b604051602081830303815290604052805190602001209850602788019750505050505050612d00565b838314612eba5760405162461bcd60e51b815260040161023890615272565b600b5463ffffffff828116600160201b9092041614612f2457600b546040517fc4faeb4e73f28a46e4a5fa2db5b89c39698816488534ab7f0717c46f0852c36691612f1b9163ffffffff808316600160201b90930416820191850190615430565b60405180910390a15b600b805463ffffffff909216600160201b0267ffffffff000000001990921691909117905550505050565b60a01b61ffff60a01b166001600160a01b03919091161760501b90565b606081830184511015612f915760405162461bcd60e51b815260040161023890615162565b6060826040519080825280601f01601f191660200182016040528015612fbe576020820181803883390190505b5090508215612ff157602081018381016020860187015b81831015612fed578051835260209283019201612fd5565b5050505b949350505050565b613001613cb8565b600061300d8382613816565b63ffffffff1683529050613021838261382f565b61ffff1660208401529050613036838261383f565b6001600160801b031660408401529050613050838261384f565b6001600160a01b031660608401529050602a81146130805760405162461bcd60e51b815260040161023890615332565b50919050565b806020015161ffff16816000015163ffffffff168363ffffffff167fc4e73a5b67a0594d06ea2b5c311c2aa44aa340dd4dd9ec5a1a718dc391b64470846060015185604001516040516130da929190614eee565b60405180910390a45050565b6001600160401b0381166000908152601160209081526040918290208054600191820180548551600261010095831615959095026000190190911693909304601f810185900485028401850190955284835260ff909116936060938301828280156131925780601f1061316757610100808354040283529160200191613192565b820191906000526020600020905b81548152906001019060200180831161317557829003601f168201915b505050505090508360000151600b8111156131a957fe5b82600b8111156131b557fe5b146131d25760405162461bcd60e51b815260040161023890615292565b60018451600b8111156131e157fe5b1415613216576131f581856020015161385f565b6132115760405162461bcd60e51b815260040161023890615282565b6132ac565b60068451600b81111561322557fe5b14156132555761323981856020015161389e565b6132115760405162461bcd60e51b8152600401610238906150a2565b60088451600b81111561326457fe5b1415613294576132788185602001516138c7565b6132115760405162461bcd60e51b8152600401610238906151e2565b60405162461bcd60e51b8152600401610238906150d2565b50505050565b6132ba613cf7565b600482016132c8848261384f565b6001600160a01b0316604084015290506132e2848261382f565b61ffff16835290506132f4848261383f565b6001600160801b0316602084015250909392505050565b613313613cb8565b600061331f8382613816565b63ffffffff1683529050613333838261384f565b6001600160a01b03166020840152905061334d838261382f565b61ffff1660408401529050613362838261383f565b6001600160801b031660608401529050602a81146130805760405162461bcd60e51b8152600401610238906150b2565b806040015161ffff16816000015163ffffffff168363ffffffff167f66fc63d751ecbefca61d4e2e7c534e4f29c61aed8ece23ed635277a7ea6f9bc4846020015185606001516040516130da929190614eee565b6133ee613cb8565b816133f98482613816565b63ffffffff168352905061340d84826138e9565b6bffffffffffffffffffffffff19166020840152905061342d848261384f565b6001600160a01b0316604084015290506134478482613816565b63ffffffff16606084015250909392505050565b60006060613487866040516020016134739190614e02565b6040516020818303038152906040526138f9565b613498613493876139a3565b6138f9565b6134a4613493866139a3565b6040516020016134b693929190614e56565b604051602081830303815290604052905060006134d388836139b6565b6001600160a01b03868116911614925050505b95945050505050565b6134f7613d17565b60006135038382613816565b63ffffffff1683529050613517838261382f565b61ffff166020840152905061352c838261382f565b61ffff1660408401529050613541838261382f565b61ffff1660608401529050613556838261384f565b6001600160a01b031660808401529050601e81146130805760405162461bcd60e51b8152600401610238906152f2565b806060015161ffff16816000015163ffffffff168363ffffffff167f20c5fd01ebdff8049629c84c58f7230432fc2bfcb1c6393ef01c4d53fd3756a98460200151856040015186608001516040516130da939291906153d9565b60008060028763ffffffff168763ffffffff16604051602001613604929190614e17565b60408051601f198184030181529082905261361e91614e4a565b602060405180830381855afa15801561363b573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525061365e919081019061400e565b90506002818660001c604051602001613678929190614e17565b60408051601f198184030181529082905261369291614e4a565b602060405180830381855afa1580156136af573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052506136d2919081019061400e565b90506002818560001c6040516020016136ec929190614e17565b60408051601f198184030181529082905261370691614e4a565b602060405180830381855afa158015613723573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250613746919081019061400e565b90506040518351828552602082602083018760025afa81865280801561376b5761376d565bfe5b5050905198975050505050505050565b6000816001600160401b0316836001600160401b031610612caa5781612cac565b6000808080846137ae8782613a7d565b955090506137bc878261384f565b945090506137ca878261382f565b935090506137d8878261383f565b9598949750929550505050565b60008282016001600160801b038085169082161015612cac5760405162461bcd60e51b8152600401610238906150f2565b6004810160006138268484613aa9565b90509250929050565b6002810160006138268484613ade565b6010810160006138268484613b08565b6014810160006138268484613b32565b600060606138708460046026612f6c565b905060606138818460046026612f6c565b905080805190602001208280519060200120149250505092915050565b6000806138ac84601a613b5c565b905060006138bb84601a613b5c565b91909114949350505050565b600060606138d8846004601a612f6c565b90506060613881846004601a612f6c565b6014810160006138268484613bb0565b60608082516002026040519080825280601f01601f19166020018201604052801561392b576020820181803883390190505b5090506020830183518101602083015b8183101561399957825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b60018301525060018301925060028101905061393b565b5091949350505050565b6060611a268263ffffffff166004613bdf565b600082516041146139d95760405162461bcd60e51b8152600401610238906151a2565b600080806139e78682613c4e565b935090506139f58682613c4e565b80935081925050506000868281518110613a0b57fe5b602001015160f81c60f81b60f81c90506001868051906020012082868660405160008152602001604052604051613a459493929190614ffe565b6020604051602081039080840390855afa158015613a67573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b600080826001019150838381518110613a9257fe5b0160200151919460f89290921c1515935090915050565b6000808260040190508084511015613ad35760405162461bcd60e51b815260040161023890615152565b929092015192915050565b6000808260020190508084511015613ad35760405162461bcd60e51b815260040161023890615122565b6000808260100190508084511015613ad35760405162461bcd60e51b815260040161023890615302565b6000808260140190508084511015613ad35760405162461bcd60e51b815260040161023890615362565b60006020821115613b7f5760405162461bcd60e51b815260040161023890615082565b8183511015613ba05760405162461bcd60e51b8152600401610238906152c2565b5060209182015191036008021c90565b60008160140183511015613bd65760405162461bcd60e51b8152600401610238906152b2565b50016020015190565b606060208260ff161115613c055760405162461bcd60e51b8152600401610238906150c2565b8160ff166040519080825280601f01601f191660200182016040528015613c33576020820181803883390190505b5060ff6008602094850302169390931b918301919091525090565b60208101600061382684846000808260200190508084511015613ad35760405162461bcd60e51b815260040161023890615142565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051808201909152600081526060602082015290565b604080516060810182526000808252602082018190529181019190915290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b50805460018160011615610100020316600290046000825580601f10613d6b5750613d89565b601f016020900490600052602060002090810190613d899190613d8c565b50565b6113a691905b808211156113a45760008155600101613d92565b8035611a68816155a9565b60008083601f840112613dc357600080fd5b5081356001600160401b03811115613dda57600080fd5b602083019150836020820283011115613df257600080fd5b9250929050565b8051611a68816155bd565b8035611a68816155c6565b8051611a68816155cf565b60008083601f840112613e2c57600080fd5b5081356001600160401b03811115613e4357600080fd5b602083019150836001820283011115613df257600080fd5b8035611a68816155d8565b8035611a68816155e1565b8035611a68816155ea565b600060208284031215613e8e57600080fd5b6000612ff18484613da6565b60008060408385031215613ead57600080fd5b6000613eb98585613da6565b9250506020613eca85828601613e5b565b9150509250929050565b60008060408385031215613ee757600080fd5b6000613ef38585613da6565b9250506020613eca85828601613e66565b6000806000806000806000806080898b031215613f2057600080fd5b88356001600160401b03811115613f3657600080fd5b613f428b828c01613db1565b985098505060208901356001600160401b03811115613f6057600080fd5b613f6c8b828c01613db1565b965096505060408901356001600160401b03811115613f8a57600080fd5b613f968b828c01613db1565b945094505060608901356001600160401b03811115613fb457600080fd5b613fc08b828c01613db1565b92509250509295985092959890939650565b600060208284031215613fe457600080fd5b6000612ff18484613df9565b60006020828403121561400257600080fd5b6000612ff18484613e04565b60006020828403121561402057600080fd5b6000612ff18484613e0f565b60008060006040848603121561404157600080fd5b83356001600160401b0381111561405757600080fd5b61406386828701613e1a565b9350935050602061407686828701613e66565b9150509250925092565b60006020828403121561409257600080fd5b6000612ff18484613e5b565b6000602082840312156140b057600080fd5b6000612ff18484613e66565b6000806000806000606086880312156140d457600080fd5b60006140e08888613e66565b95505060208601356001600160401b038111156140fc57600080fd5b61410888828901613db1565b945094505060408601356001600160401b0381111561412657600080fd5b61413288828901613e1a565b92509250509295509295909350565b6000806040838503121561415457600080fd5b6000613eb98585613e66565b6000806040838503121561417357600080fd5b6000613ef38585613e66565b60008060008060008060008060008060c08b8d03121561419e57600080fd5b60006141aa8d8d613e66565b9a505060206141bb8d828e01613e66565b99505060408b01356001600160401b038111156141d757600080fd5b6141e38d828e01613db1565b985098505060608b01356001600160401b0381111561420157600080fd5b61420d8d828e01613e1a565b965096505060808b01356001600160401b0381111561422b57600080fd5b6142378d828e01613e1a565b945094505060a08b01356001600160401b0381111561425557600080fd5b6142618d828e01613db1565b92509250509295989b9194979a5092959850565b6000806000806060858703121561428b57600080fd5b60006142978787613e66565b94505060206142a887828801613e66565b93505060408501356001600160401b038111156142c457600080fd5b6142d087828801613db1565b95989497509550505050565b60008060008060008060008060a0898b0312156142f857600080fd5b60006143048b8b613e66565b98505060206143158b828c01613e66565b97505060408901356001600160401b0381111561433157600080fd5b61433d8b828c01613db1565b965096505060608901356001600160401b0381111561435b57600080fd5b6143678b828c01613db1565b945094505060808901356001600160401b03811115613fb457600080fd5b60006020828403121561439757600080fd5b6000612ff18484613e71565b60006143af83836144d5565b505060200190565b60006143af8383614de7565b6143cc8161553c565b82525050565b6143cc816154c6565b60006143e783856154bd565b93506001600160fb1b038311156143fd57600080fd5b60208302925061440e83858461555d565b50500190565b600061441f826154b9565b61442981856154bd565b9350614434836154b3565b8060005b8381101561446257815161444c88826143a3565b9750614457836154b3565b925050600101614438565b509495945050505050565b6000614478826154b9565b61448281856154bd565b935061448d836154b3565b8060005b838110156144625781516144a588826143b7565b97506144b0836154b3565b925050600101614491565b6143cc816154d1565b6143cc6144d0826154d6565b6113a6565b6143cc816113a6565b6143cc6144d0826113a6565b60006144f683856154bd565b935061450383858461555d565b61450c83615595565b9093019392505050565b60006145228385611a29565b935061440e83858461555d565b600061453a826154b9565b6145448185611a29565b9350614554818560208601615569565b9290920192915050565b6000614569826154b9565b61457381856154bd565b9350614583818560208601615569565b61450c81615595565b6143cc81615547565b60006145a26005836154bd565b64666373313160d81b815260200192915050565b60006145c36005836154bd565b64667070313560d81b815260200192915050565b60006145e4600183611a29565b600560f91b815260010192915050565b60006146016005836154bd565b64074726d31360dc1b815260200192915050565b60006146226007836154bd565b666d6266766b313360c81b815260200192915050565b60006146456005836154bd565b641d9b9c0c4d60da1b815260200192915050565b60006146666005836154bd565b64072667031360dc1b815260200192915050565b60006146876005836154bd565b64627432313160d81b815260200192915050565b60006146a8601d83611a29565b7f19457468657265756d205369676e6564204d6573736167653a0a3135320000008152601d0192915050565b60006146e16005836154bd565b643b3738189b60d91b815260200192915050565b60006147026007836154bd565b666d6266766b313160c81b815260200192915050565b6000614725601b836154bd565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061475e6005836154bd565b64766273313160d81b815260200192915050565b600061477f6005836154bd565b64636362313160d81b815260200192915050565b60006147a06005836154bd565b64313a3a981960d91b815260200192915050565b60006147c16005836154bd565b64333838189b60d91b815260200192915050565b60006147e26005836154bd565b64313a31199960d91b815260200192915050565b60006148036005836154bd565b64189d1d4c0d60da1b815260200192915050565b60006148246005836154bd565b64627365313160d81b815260200192915050565b60006148456003836154bd565b6263773360e81b815260200192915050565b60006148646003836154bd565b6266623160e81b815260200192915050565b6000614883600983611a29565b680dcdedcc6ca744060f60bb1b815260090192915050565b60006148a86003836154bd565b6263773160e81b815260200192915050565b60006148c76005836154bd565b64076657331360dc1b815260200192915050565b60006148e86005836154bd565b643331b9989960d91b815260200192915050565b60006149096005836154bd565b6466726b313160d81b815260200192915050565b600061492a601f836154bd565b7f7a6b53796e6345786974416464726573732073686f756c642062652073657400815260200192915050565b60006149636005836154bd565b64766e70313560d81b815260200192915050565b60006149846005836154bd565b64706f77313160d81b815260200192915050565b60006149a56005836154bd565b641998dccc4d60da1b815260200192915050565b60006149c6600283611a29565b61050560f11b815260020192915050565b60006149e4602c83611a29565b7f4f6e6c79207369676e2074686973206d65737361676520666f7220612074727581526b7374656420636c69656e742160a01b6020820152602c0192915050565b6000614a326003836154bd565b6231bb9960e91b815260200192915050565b6000614a516004836154bd565b63706d733360e01b815260200192915050565b6000614a716005836154bd565b64061686631360dc1b815260200192915050565b6000614a926005836154bd565b64616866313160d81b815260200192915050565b6000614ab36005836154bd565b64666373313360d81b815260200192915050565b6000614ad46005836154bd565b6466636b313360d81b815260200192915050565b6000614af56005836154bd565b643837bb989960d91b815260200192915050565b6000614b16600e83611a29565b6d0c2c6c6deeadce840d2c8744060f60931b8152600e0192915050565b6000614b406005836154bd565b64766e70313360d81b815260200192915050565b6000614b616005836154bd565b64373b38189960d91b815260200192915050565b6000614b826005836154bd565b64666373313560d81b815260200192915050565b6000614ba36005836154bd565b64062746232360dc1b815260200192915050565b6000614bc46005836154bd565b6474726d313160d81b815260200192915050565b6000614be56005836154bd565b64726273313160d81b815260200192915050565b6000614c066005836154bd565b64706373323160d81b815260200192915050565b6000614c276005836154bd565b64072637031360dc1b815260200192915050565b6000614c486005836154bd565b64313a3a989b60d91b815260200192915050565b6000614c696005836154bd565b6466636b313160d81b815260200192915050565b6000614c8a6005836154bd565b64667265313160d81b815260200192915050565b6000614cab6005836154bd565b64072647031360dc1b815260200192915050565b6000614ccc6005836154bd565b64199c1c0c4d60da1b815260200192915050565b6000614ced601f836154bd565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00815260200192915050565b6000614d266005836154bd565b64627461313160d81b815260200192915050565b6000614d476005836154bd565b643331b9989b60d91b815260200192915050565b6000614d686004836154bd565b631c1b5ccd60e21b815260200192915050565b6000614d88601983611a29565b7f5265676973746572205a4b53776170207075626b65793a0a0a00000000000000815260190192915050565b6000614dc16005836154bd565b64063626231360dc1b815260200192915050565b6143cc81615502565b6143cc8161550e565b6143cc81615521565b6143cc8161552a565b6143cc81615536565b6000614e0e82846144c4565b50601401919050565b6000614e2382856144de565b602082019150614e3382846144de565b5060200192915050565b6000612ff1828486614516565b6000612cac828461452f565b6000614e618261469b565b9150614e6c82614d7b565b9150614e78828661452f565b9150614e83826145d7565b9150614e8e82614876565b9150614e9a828561452f565b9150614ea5826145d7565b9150614eb082614b09565b9150614ebc828461452f565b9150614ec7826149b9565b91506134e6826149d7565b60208101611a6882846143d2565b60208101611a6882846143c3565b60408101614efc82856143d2565b612cac6020830184614dd5565b60408101614f1782856143d2565b612cac6020830184614dde565b60a08082528101614f36818a8c6143db565b90508181036020830152614f4b81888a6143db565b90508181036040830152614f5f818761446d565b90508181036060830152614f738186614414565b90508181036080830152614f888184866143db565b9a9950505050505050505050565b60208101611a6882846144bb565b60208101611a6882846144d5565b60a08101614fc082886144d5565b614fcd60208301876144bb565b614fda60408301866143d2565b614fe76060830185614dde565b614ff46080830184614dd5565b9695505050505050565b6080810161500c82876144d5565b6150196020830186614df9565b61502660408301856144d5565b6134e660608301846144d5565b60608101615041828661458c565b8181036020830152615053818561455e565b9050612ff160408301846144d5565b60208082528101611a2681614595565b60208082528101611a26816145b6565b60208082528101611a26816145f4565b60208082528101611a2681614615565b60208082528101611a2681614638565b60208082528101611a2681614659565b60208082528101611a268161467a565b60208082528101611a26816146d4565b60208082528101611a26816146f5565b60208082528101611a2681614718565b60208082528101611a2681614751565b60208082528101611a2681614772565b60208082528101611a2681614793565b60208082528101611a26816147b4565b60208082528101611a26816147d5565b60208082528101611a26816147f6565b60208082528101611a2681614817565b60208082528101611a2681614838565b60208082528101611a2681614857565b60208082528101611a268161489b565b60208082528101611a26816148ba565b60208082528101611a26816148db565b60208082528101611a26816148fc565b60208082528101611a268161491d565b60208082528101611a2681614956565b60208082528101611a2681614977565b60208082528101611a2681614998565b60208082528101611a2681614a25565b60208082528101611a2681614a44565b60208082528101611a2681614a64565b60208082528101611a2681614a85565b60208082528101611a2681614aa6565b60208082528101611a2681614ac7565b60208082528101611a2681614ae8565b60208082528101611a2681614b33565b60208082528101611a2681614b54565b60208082528101611a2681614b75565b60208082528101611a2681614b96565b60208082528101611a2681614bb7565b60208082528101611a2681614bd8565b60208082528101611a2681614bf9565b60208082528101611a2681614c1a565b60208082528101611a2681614c3b565b60208082528101611a2681614c5c565b60208082528101611a2681614c7d565b60208082528101611a2681614c9e565b60208082528101611a2681614cbf565b60208082528101611a2681614ce0565b60208082528101611a2681614d19565b60208082528101611a2681614d3a565b60208082528101611a2681614d5b565b60208082528101611a2681614db4565b60208101611a688284614dd5565b604081016153be8285614dd5565b612cac6020830184614df9565b60208101611a688284614dde565b606081016153e78286614dde565b6153f46020830185614dde565b612ff160408301846143d2565b60208101611a688284614de7565b6040810161541d8286614de7565b81810360208301526134e68184866144ea565b6040810161543e8285614de7565b612cac6020830184614de7565b60c081016154598289614de7565b6154666020830188614df0565b6154736040830187614de7565b61548060608301866144d5565b61548d60808301856144d5565b61549a60a08301846144d5565b979650505050505050565b60208101611a688284614df0565b60200190565b5190565b90815260200190565b6000611a2682615515565b151590565b6bffffffffffffffffffffffff191690565b69ffffffffffffffffffff191690565b80611a298161559f565b6001600160801b031690565b61ffff1690565b6001600160a01b031690565b63ffffffff1690565b6001600160401b031690565b60ff1690565b6000611a2682615552565b6000611a26826154f8565b6000611a26826154c6565b82818337506000910152565b60005b8381101561558457818101518382015260200161556c565b838111156132ac5750506000910152565b601f01601f191690565b600c8110613d8957fe5b6155b2816154c6565b8114613d8957600080fd5b6155b2816154d1565b6155b2816154e8565b6155b2816113a6565b6155b28161550e565b6155b281615521565b6155b28161552a56fec5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4a365627a7a72315820e2d12ac9a23b5013fb0cda7f6a0ed023fb77d48a6c162cd292ea1c9d250c426a6c6578706572696d656e74616cf564736f6c63430005100040
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.