ETH Price: $1,975.16 (-1.86%)
Gas: 0.08 Gwei
 

More Info

Private Name Tags

Multichain Info

1 address found via
Transaction Hash
Method
Block
From
To
Process Rollup243245472026-01-27 7:02:4733 days ago1769497367IN
Aztec: Private Rollup Bridge
0 ETH0.001291092.53607245
Process Rollup240253302025-12-16 13:01:1175 days ago1765890071IN
Aztec: Private Rollup Bridge
0 ETH0.001296172.53379851
Process Rollup240253182025-12-16 12:58:4775 days ago1765889927IN
Aztec: Private Rollup Bridge
0 ETH0.001325382.53613497
Process Rollup240253042025-12-16 12:55:5975 days ago1765889759IN
Aztec: Private Rollup Bridge
0 ETH0.00125682.54283218
Process Rollup240252922025-12-16 12:53:3575 days ago1765889615IN
Aztec: Private Rollup Bridge
0 ETH0.001340312.54830852
Process Rollup240250392025-12-16 12:02:3575 days ago1765886555IN
Aztec: Private Rollup Bridge
0 ETH0.001297242.53576516
Process Rollup240250182025-12-16 11:58:2375 days ago1765886303IN
Aztec: Private Rollup Bridge
0 ETH0.001369452.53765726
Process Rollup240250062025-12-16 11:55:5975 days ago1765886159IN
Aztec: Private Rollup Bridge
0 ETH0.001269912.53911985
Process Rollup240249982025-12-16 11:54:2375 days ago1765886063IN
Aztec: Private Rollup Bridge
0 ETH0.001249252.53862731
Process Rollup240248832025-12-16 11:31:2375 days ago1765884683IN
Aztec: Private Rollup Bridge
0 ETH0.001249952.53969625
Process Rollup240248562025-12-16 11:25:5975 days ago1765884359IN
Aztec: Private Rollup Bridge
0 ETH0.001327482.53991493
Process Rollup240248442025-12-16 11:23:3575 days ago1765884215IN
Aztec: Private Rollup Bridge
0 ETH0.001328332.54200218
Process Rollup240248172025-12-16 11:18:1175 days ago1765883891IN
Aztec: Private Rollup Bridge
0 ETH0.001255762.54085957
Process Rollup240248132025-12-16 11:17:1175 days ago1765883831IN
Aztec: Private Rollup Bridge
0 ETH0.001249582.53793152
Process Rollup239442022025-12-05 3:49:5986 days ago1764906599IN
Aztec: Private Rollup Bridge
0 ETH0.001281472.52476175
Process Rollup239441692025-12-05 3:43:2386 days ago1764906203IN
Aztec: Private Rollup Bridge
0 ETH0.00123852.52623153
Process Rollup239441632025-12-05 3:42:1186 days ago1764906131IN
Aztec: Private Rollup Bridge
0 ETH0.001231612.52309726
Process Rollup234979792025-10-03 14:54:35149 days ago1759503275IN
Aztec: Private Rollup Bridge
0 ETH0.001990793.91219103
Process Rollup234976142025-10-03 13:41:11149 days ago1759498871IN
Aztec: Private Rollup Bridge
0 ETH0.001563813.07298257
Process Rollup234973252025-10-03 12:42:47149 days ago1759495367IN
Aztec: Private Rollup Bridge
0 ETH0.001489962.79081035
Process Rollup234968722025-10-03 11:11:23149 days ago1759489883IN
Aztec: Private Rollup Bridge
0 ETH0.001377872.70765764
Process Rollup234900762025-10-02 12:23:47150 days ago1759407827IN
Aztec: Private Rollup Bridge
0 ETH0.001615843.02680679
0x68747470224208112025-05-05 23:28:47300 days ago1746487727IN
Aztec: Private Rollup Bridge
0 ETH0.000017220.75
0x68747470224204982025-05-05 22:25:47300 days ago1746483947IN
Aztec: Private Rollup Bridge
0 ETH0.000017220.75
0x68747470224201892025-05-05 21:23:23300 days ago1746480203IN
Aztec: Private Rollup Bridge
0 ETH0.000017220.75
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Transfer243245472026-01-27 7:02:4733 days ago1769497367
Aztec: Private Rollup Bridge
1 ETH
Transfer240253302025-12-16 13:01:1175 days ago1765890071
Aztec: Private Rollup Bridge
0.01 ETH
Transfer240250392025-12-16 12:02:3575 days ago1765886555
Aztec: Private Rollup Bridge
0.201 ETH
Transfer239442022025-12-05 3:49:5986 days ago1764906599
Aztec: Private Rollup Bridge
0.1 ETH
Transfer234979792025-10-03 14:54:35149 days ago1759503275
Aztec: Private Rollup Bridge
13.043429 ETH
Transfer234976142025-10-03 13:41:11149 days ago1759498871
Aztec: Private Rollup Bridge
6 ETH
Transfer234973252025-10-03 12:42:47149 days ago1759495367
Aztec: Private Rollup Bridge
0.3 ETH
Transfer234968722025-10-03 11:11:23149 days ago1759489883
Aztec: Private Rollup Bridge
0.1 ETH
Transfer234900762025-10-02 12:23:47150 days ago1759407827
Aztec: Private Rollup Bridge
0.1 ETH
Transfer212044712024-11-17 2:33:59469 days ago1731810839
Aztec: Private Rollup Bridge
0.19879 ETH
Transfer206788562024-09-04 17:57:11543 days ago1725472631
Aztec: Private Rollup Bridge
0.010015 ETH
Transfer206654932024-09-02 21:12:35545 days ago1725311555
Aztec: Private Rollup Bridge
0.01 ETH
Transfer206654522024-09-02 21:03:59545 days ago1725311039
Aztec: Private Rollup Bridge
0.01092 ETH
Transfer206654152024-09-02 20:56:35545 days ago1725310595
Aztec: Private Rollup Bridge
0.01724 ETH
Transfer206653782024-09-02 20:49:11545 days ago1725310151
Aztec: Private Rollup Bridge
0.02223 ETH
Transfer206653222024-09-02 20:37:59545 days ago1725309479
Aztec: Private Rollup Bridge
0.01 ETH
Transfer206652772024-09-02 20:28:59545 days ago1725308939
Aztec: Private Rollup Bridge
0.01 ETH
Transfer206631602024-09-02 13:24:23545 days ago1725283463
Aztec: Private Rollup Bridge
0.1 ETH
Transfer206351412024-08-29 15:29:47549 days ago1724945387
Aztec: Private Rollup Bridge
0.02092 ETH
Transfer206350942024-08-29 15:20:23549 days ago1724944823
Aztec: Private Rollup Bridge
0.01 ETH
Transfer206350422024-08-29 15:09:59549 days ago1724944199
Aztec: Private Rollup Bridge
0.05 ETH
Transfer206349902024-08-29 14:59:35549 days ago1724943575
Aztec: Private Rollup Bridge
0.01 ETH
Transfer206349032024-08-29 14:42:11549 days ago1724942531
Aztec: Private Rollup Bridge
0.011146 ETH
Transfer206347812024-08-29 14:17:47549 days ago1724941067
Aztec: Private Rollup Bridge
0.06613 ETH
Transfer206347232024-08-29 14:06:11549 days ago1724940371
Aztec: Private Rollup Bridge
0.05 ETH
View All Internal Transactions
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RollupProcessor

Compiler Version
v0.6.10+commit.00c0fcaf

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd.
pragma solidity >=0.6.10 <0.8.0;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {Pausable} from '@openzeppelin/contracts/utils/Pausable.sol';
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';

import {IVerifier} from './interfaces/IVerifier.sol';
import {IRollupProcessor} from './interfaces/IRollupProcessor.sol';
import {IFeeDistributor} from './interfaces/IFeeDistributor.sol';
import {IERC20Permit} from './interfaces/IERC20Permit.sol';
import {Decoder} from './Decoder.sol';
import './libraries/RollupProcessorLibrary.sol';

/**
 * @title Rollup Processor
 * @dev Smart contract responsible for processing Aztec zkRollups, including relaying them to a verifier
 * contract for validation and performing all relevant ERC20 token transfers
 */
contract RollupProcessor is IRollupProcessor, Decoder, Ownable, Pausable {
    using SafeMath for uint256;

    bytes32 public dataRoot = 0x2708a627d38d74d478f645ec3b4e91afa325331acf1acebe9077891146b75e39;
    bytes32 public nullRoot = 0x2694dbe3c71a25d92213422d392479e7b8ef437add81e1e17244462e6edca9b1;
    bytes32 public rootRoot = 0x2d264e93dc455751a721aead9dba9ee2a9fef5460921aeede73f63f6210e6851;

    uint256 public dataSize;
    uint256 public nextRollupId;

    IVerifier public verifier;

    uint256 public constant numberOfAssets = 4;
    uint256 public constant txNumPubInputs = 12;
    uint256 public constant rollupNumPubInputs = 10 + numberOfAssets;
    uint256 public constant txPubInputLength = txNumPubInputs * 32; // public inputs length for of each inner proof tx
    uint256 public constant rollupPubInputLength = rollupNumPubInputs * 32;
    uint256 public constant ethAssetId = 0;
    uint256 public immutable escapeBlockLowerBound;
    uint256 public immutable escapeBlockUpperBound;

    event RollupProcessed(
        uint256 indexed rollupId,
        bytes32 dataRoot,
        bytes32 nullRoot,
        bytes32 rootRoot,
        uint256 dataSize
    );
    event Deposit(uint256 assetId, address depositorAddress, uint256 depositValue);
    event Withdraw(uint256 assetId, address withdrawAddress, uint256 withdrawValue);
    event WithdrawError(bytes errorReason);
    event AssetAdded(uint256 indexed assetId, address indexed assetAddress);
    event RollupProviderUpdated(address indexed providerAddress, bool valid);
    event VerifierUpdated(address indexed verifierAddress);

    // Array of supported ERC20 token address.
    address[] public supportedAssets;

    // Mapping which maps an asset address to a bool, determining whether it supports
    // permit as according to ERC-2612
    mapping(address => bool) assetPermitSupport;

    // Mapping from assetId to mapping of userAddress to public userBalance stored on this contract
    mapping(uint256 => mapping(address => uint256)) public userPendingDeposits;

    mapping(address => mapping(bytes32 => bool)) public depositProofApprovals;

    mapping(address => bool) public rollupProviders;

    address public override feeDistributor;

    // Metrics
    uint256[] public totalPendingDeposit;
    uint256[] public totalDeposited;
    uint256[] public totalWithdrawn;
    uint256[] public totalFees;

    constructor(
        address _verifierAddress,
        uint256 _escapeBlockLowerBound,
        uint256 _escapeBlockUpperBound,
        address _contractOwner
    ) public {
        verifier = IVerifier(_verifierAddress);
        escapeBlockLowerBound = _escapeBlockLowerBound;
        escapeBlockUpperBound = _escapeBlockUpperBound;
        rollupProviders[msg.sender] = true;
        totalPendingDeposit.push(0);
        totalDeposited.push(0);
        totalWithdrawn.push(0);
        totalFees.push(0);
        transferOwnership(_contractOwner);
    }

    function setRollupProvider(address providerAddress, bool valid) public override onlyOwner {
        rollupProviders[providerAddress] = valid;
        emit RollupProviderUpdated(providerAddress, valid);
    }

    function setVerifier(address _verifierAddress) public override onlyOwner {
        verifier = IVerifier(_verifierAddress);
        emit VerifierUpdated(_verifierAddress);
    }

    function setFeeDistributor(address feeDistributorAddress) public override onlyOwner {
        feeDistributor = feeDistributorAddress;
    }

    /**
     * @dev Approve a proofHash for spending a users deposited funds, this is one way and must be called by the owner of the funds
     * @param _proofHash - keccack256 hash of the inner proof public inputs
     */

    function approveProof(bytes32 _proofHash) public override whenNotPaused {
        depositProofApprovals[msg.sender][_proofHash] = true;
    }

    /**
     * @dev Get the ERC20 token address of a supported asset, for a given assetId
     * @param assetId - identifier used to denote a particular asset
     */
    function getSupportedAsset(uint256 assetId) public view override returns (address) {
        if (assetId == ethAssetId) {
            return address(0x0);
        }

        return supportedAssets[assetId - 1];
    }

    /**
     * @dev Get the addresses of all supported ERC20 tokens
     */
    function getSupportedAssets() external view override returns (address[] memory) {
        return supportedAssets;
    }

    function getTotalDeposited() external view override returns (uint256[] memory) {
        return totalDeposited;
    }

    function getTotalWithdrawn() external view override returns (uint256[] memory) {
        return totalWithdrawn;
    }

    function getTotalPendingDeposit() external view override returns (uint256[] memory) {
        return totalPendingDeposit;
    }

    function getTotalFees() external view override returns (uint256[] memory) {
        return totalFees;
    }

    /**
     * @dev Get the status of whether an asset supports the permit ERC-2612 approval flow
     * @param assetId - unique identifier of the supported asset
     */
    function getAssetPermitSupport(uint256 assetId) external view override returns (bool) {
        address assetAddress = getSupportedAsset(assetId);
        return assetPermitSupport[assetAddress];
    }

    /**
     * @dev Get the status of the escape hatch, specifically retrieve whether the
     * hatch is open and also the number of blocks until the hatch will switch from
     * open to closed or vice versa
     */
    function getEscapeHatchStatus() public view override returns (bool, uint256) {
        uint256 blockNum = block.number;

        bool isOpen = blockNum % escapeBlockUpperBound >= escapeBlockLowerBound;
        uint256 blocksRemaining = 0;
        if (isOpen) {
            // num blocks escape hatch will remain open for
            blocksRemaining = escapeBlockUpperBound - (blockNum % escapeBlockUpperBound);
        } else {
            // num blocks until escape hatch will be opened
            blocksRemaining = escapeBlockLowerBound - (blockNum % escapeBlockUpperBound);
        }
        return (isOpen, blocksRemaining);
    }

    /**
     * @dev Get the balance of a user, for a particular asset, held on the user's behalf
     * by this contract
     * @param assetId - unique identifier of the asset
     * @param userAddress - Ethereum address of the user who's balance is being queried
     */
    function getUserPendingDeposit(uint256 assetId, address userAddress) external view override returns (uint256) {
        return userPendingDeposits[assetId][userAddress];
    }

    /**
     * @dev Increase the userPendingDeposits mapping
     */
    function increasePendingDepositBalance(
        uint256 assetId,
        address depositorAddress,
        uint256 amount
    ) internal {
        userPendingDeposits[assetId][depositorAddress] = userPendingDeposits[assetId][depositorAddress].add(amount);
        totalPendingDeposit[assetId] = totalPendingDeposit[assetId].add(amount);
    }

    /**
     * @dev Decrease the userPendingDeposits mapping
     */
    function decreasePendingDepositBalance(
        uint256 assetId,
        address transferFromAddress,
        uint256 amount
    ) internal {
        uint256 userBalance = userPendingDeposits[assetId][transferFromAddress];
        require(userBalance >= amount, 'Rollup Processor: INSUFFICIENT_DEPOSIT');

        userPendingDeposits[assetId][transferFromAddress] = userBalance.sub(amount);
        totalPendingDeposit[assetId] = totalPendingDeposit[assetId].sub(amount);
        totalDeposited[assetId] = totalDeposited[assetId].add(amount);
    }

    /**
     * @dev Set the mapping between an assetId and the address of the linked asset.
     * Protected by onlyOwner
     * @param linkedToken - address of the asset
     * @param supportsPermit - bool determining whether this supports permit
     */
    function setSupportedAsset(address linkedToken, bool supportsPermit) external override onlyOwner {
        require(linkedToken != address(0x0), 'Rollup Processor: ZERO_ADDRESS');

        supportedAssets.push(linkedToken);
        assetPermitSupport[linkedToken] = supportsPermit;

        uint256 assetId = supportedAssets.length;
        require(assetId < numberOfAssets, 'Rollup Processor: MAX_ASSET_REACHED');

        totalPendingDeposit.push(0);
        totalDeposited.push(0);
        totalWithdrawn.push(0);
        totalFees.push(0);

        emit AssetAdded(assetId, linkedToken);
    }

    /**
     * @dev Update the value indicating whether a linked asset supports permit.
     * Protected by onlyOwner
     * @param assetId - unique ID of the asset
     * @param supportsPermit - bool determining whether this supports permit
     */
    function setAssetPermitSupport(uint256 assetId, bool supportsPermit) external override onlyOwner {
        address assetAddress = getSupportedAsset(assetId);
        require(assetAddress != address(0x0), 'Rollup Processor: TOKEN_ASSET_NOT_LINKED');

        assetPermitSupport[assetAddress] = supportsPermit;
    }

    /**
     * @dev Deposit funds as part of the first stage of the two stage deposit. Non-permit flow
     * @param assetId - unique ID of the asset
     * @param amount - number of tokens being deposited
     * @param depositorAddress - address from which funds are being transferred to the contract
     */
    function depositPendingFunds(
        uint256 assetId,
        uint256 amount,
        address depositorAddress
    ) external payable override whenNotPaused {
        if (assetId == ethAssetId) {
            require(msg.value == amount, 'Rollup Processor: WRONG_AMOUNT');

            increasePendingDepositBalance(assetId, depositorAddress, amount);
        } else {
            require(msg.value == 0, 'Rollup Processor: WRONG_PAYMENT_TYPE');

            address assetAddress = getSupportedAsset(assetId);
            internalDeposit(assetId, assetAddress, depositorAddress, amount);
        }
    }

    /**
     * @dev Deposit funds as part of the first stage of the two stage deposit. Permit flow
     * @param assetId - unique ID of the asset
     * @param amount - number of tokens being deposited
     * @param depositorAddress - address from which funds are being transferred to the contract
     * @param spender - address being granted approval to spend the funds
     * @param permitApprovalAmount - amount permit signature is approving
     * @param deadline - when the permit signature expires
     * @param v - ECDSA sig param
     * @param r - ECDSA sig param
     * @param s - ECDSA sig param
     */
    function depositPendingFundsPermit(
        uint256 assetId,
        uint256 amount,
        address depositorAddress,
        address spender,
        uint256 permitApprovalAmount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external override whenNotPaused {
        address assetAddress = getSupportedAsset(assetId);
        IERC20Permit(assetAddress).permit(depositorAddress, spender, permitApprovalAmount, deadline, v, r, s);
        internalDeposit(assetId, assetAddress, depositorAddress, amount);
    }

    /**
     * @dev Deposit funds as part of the first stage of the two stage deposit. Non-permit flow
     * @param assetId - unique ID of the asset
     * @param assetAddress - address of the ERC20 asset
     * @param depositorAddress - address from which funds are being transferred to the contract
     * @param amount - amount being deposited
     */
    function internalDeposit(
        uint256 assetId,
        address assetAddress,
        address depositorAddress,
        uint256 amount
    ) internal {
        // check user approved contract to transfer funds, so can throw helpful error to user
        uint256 rollupAllowance = IERC20(assetAddress).allowance(depositorAddress, address(this));
        require(rollupAllowance >= amount, 'Rollup Processor: INSUFFICIENT_TOKEN_APPROVAL');

        IERC20(assetAddress).transferFrom(depositorAddress, address(this), amount);
        increasePendingDepositBalance(assetId, depositorAddress, amount);

        emit Deposit(assetId, depositorAddress, amount);
    }

    /**
     * @dev Process a rollup - decode the rollup, update relevant state variables and
     * verify the proof
     * @param proofData - cryptographic proof data associated with a rollup
     * @param signatures - bytes array of secp256k1 ECDSA signatures, authorising a transfer of tokens
     * from the publicOwner for the particular inner proof in question. There is a signature for each
     * inner proof.
     *
     * Structure of each signature in the bytes array is:
     * 0x00 - 0x20 : r
     * 0x20 - 0x40 : s
     * 0x40 - 0x60 : v (in form: 0x0000....0001b for example)
     *
     * @param viewingKeys - viewingKeys for the notes submitted in the rollup. Note: not used in the logic
     * of the rollupProcessor contract, but called here as a convenient to place data on chain
     */
    function escapeHatch(
        bytes calldata proofData,
        bytes calldata signatures,
        bytes calldata viewingKeys
    ) external override whenNotPaused {
        (bool isOpen, ) = getEscapeHatchStatus();
        require(isOpen, 'Rollup Processor: ESCAPE_BLOCK_RANGE_INCORRECT');

        processRollupProof(proofData, signatures, viewingKeys);
    }

    function processRollup(
        bytes calldata proofData,
        bytes calldata signatures,
        bytes calldata viewingKeys,
        bytes calldata providerSignature,
        address provider,
        address payable feeReceiver,
        uint256 feeLimit
    ) external override whenNotPaused {
        uint256 initialGas = gasleft();

        require(rollupProviders[provider], 'Rollup Processor: UNKNOWN_PROVIDER');
        bytes memory sigData =
            abi.encodePacked(proofData[0:rollupPubInputLength], feeReceiver, feeLimit, feeDistributor);
        RollupProcessorLibrary.validateSignature(keccak256(sigData), providerSignature, provider);

        processRollupProof(proofData, signatures, viewingKeys);

        transferFee(proofData);

        (bool success, ) =
            feeDistributor.call(
                abi.encodeWithSignature(
                    'reimburseGas(uint256,uint256,address)',
                    initialGas - gasleft(),
                    feeLimit,
                    feeReceiver
                )
            );
        require(success, 'Rollup Processor: REIMBURSE_GAS_FAILED');
    }

    function processRollupProof(
        bytes memory proofData,
        bytes memory signatures,
        bytes calldata /*viewingKeys*/
    ) internal {
        uint256 numTxs = verifyProofAndUpdateState(proofData);
        processDepositsAndWithdrawals(proofData, numTxs, signatures);
    }

    /**
     * @dev Verify the zk proof and update the contract state variables with those provided by the rollup.
     * @param proofData - cryptographic zk proof data. Passed to the verifier for verification.
     */
    function verifyProofAndUpdateState(bytes memory proofData) internal returns (uint256) {
        (
            bytes32 newDataRoot,
            bytes32 newNullRoot,
            uint256 rollupId,
            uint256 rollupSize,
            bytes32 newRootRoot,
            uint256 numTxs,
            uint256 newDataSize
        ) = validateMerkleRoots(proofData);

        // Verify the rollup proof.
        //
        // We manually call the verifier contract via assembly. This is to prevent a
        // redundant copy of `proofData` into memory, which costs between 100,000 to 1,000,000 gas
        // depending on the rollup size!
        bool proof_verified = false;
        address verifierAddress;
        uint256 temp1;
        uint256 temp2;
        uint256 temp3;
        assembly {
            // Step 1: we need to insert 68 bytes of verifier 'calldata' just prior to proofData
            // Start by defining the start of our 'calldata'. Also grab the verifier contract address from storage
            let inputPtr := sub(proofData, 0x44)
            verifierAddress := sload(verifier_slot)

            // Step 2: we need to overwrite the memory between `inputPtr` and `inputPtr + 68`
            // we load the existing 68 bytes of memory into stack variables temp1, temp2, temp3
            // Once we have called the verifier contract, we will write this data back into memory
            temp1 := mload(inputPtr)
            temp2 := mload(add(inputPtr, 0x20))
            temp3 := mload(add(inputPtr, 0x40))

            // Step 3: insert our calldata into memory
            // We call the function `verify(bytes,uint256)`
            // The function signature is 0xac318c5d
            // Calldata map is:
            // 0x00 - 0x04 : 0xac318c5d
            // 0x04 - 0x24 : 0x40 (number of bytes between 0x04 and the start of the `proofData` array at 0x44)
            // 0x24 - 0x44 : rollupSize
            // 0x44 - .... : proofData (already present in memory)
            mstore8(inputPtr, 0xac)
            mstore8(add(inputPtr, 0x01), 0x31)
            mstore8(add(inputPtr, 0x02), 0x8c)
            mstore8(add(inputPtr, 0x03), 0x5d)
            mstore(add(inputPtr, 0x04), 0x40)
            mstore(add(inputPtr, 0x24), rollupSize)

            // Total calldata size is proofData.length + 96 bytes (the 66 bytes we just wrote, plus the 32 byte 'length' field of proofData)
            let callSize := add(mload(proofData), 0x64)

            // Step 4: Call our verifier contract. If does not return any values, but will throw an error if the proof is not valid
            // i.e. verified == false if proof is not valid
            proof_verified := staticcall(gas(), verifierAddress, inputPtr, callSize, 0x00, 0x00)

            // Step 5: Restore the memory we overwrote with our 'calldata'
            mstore(inputPtr, temp1)
            mstore(add(inputPtr, 0x20), temp2)
            mstore(add(inputPtr, 0x40), temp3)
        }

        // Check the proof is valid!
        require(proof_verified, 'proof verification failed');

        // Update state variables.
        dataRoot = newDataRoot;
        nullRoot = newNullRoot;
        nextRollupId = rollupId.add(1);
        rootRoot = newRootRoot;
        dataSize = newDataSize;

        emit RollupProcessed(rollupId, dataRoot, nullRoot, rootRoot, dataSize);
        return numTxs;
    }

    /**
     * @dev Extract public inputs and validate they are inline with current contract state.
     * @param proofData - Rollup proof data.
     */
    function validateMerkleRoots(bytes memory proofData)
        internal
        view
        returns (
            bytes32,
            bytes32,
            uint256,
            uint256,
            bytes32,
            uint256,
            uint256
        )
    {
        (
            // Stack to deep workaround:
            // 0: rollupId
            // 1: rollupSize
            // 2: dataStartIndex
            // 3: numTxs
            uint256[4] memory nums,
            bytes32 oldDataRoot,
            bytes32 newDataRoot,
            bytes32 oldNullRoot,
            bytes32 newNullRoot,
            bytes32 oldRootRoot,
            bytes32 newRootRoot
        ) = decodeProof(proofData, numberOfAssets);

        // Escape hatch denominated by a rollup size of 0, which means inserting 2 new entries.
        nums[3] = nums[1] == 0 ? 1 : nums[1];

        // Ensure we are inserting at the next subtree boundary.
        uint256 toInsert = nums[3].mul(2);
        if (dataSize % toInsert == 0) {
            require(nums[2] == dataSize, 'Rollup Processor: INCORRECT_DATA_START_INDEX');
        } else {
            uint256 expected = dataSize + toInsert - (dataSize % toInsert);
            require(nums[2] == expected, 'Rollup Processor: INCORRECT_DATA_START_INDEX');
        }

        // Data validation checks.
        require(oldDataRoot == dataRoot, 'Rollup Processor: INCORRECT_DATA_ROOT');
        require(oldNullRoot == nullRoot, 'Rollup Processor: INCORRECT_NULL_ROOT');
        require(oldRootRoot == rootRoot, 'Rollup Processor: INCORRECT_ROOT_ROOT');
        require(nums[0] == nextRollupId, 'Rollup Processor: ID_NOT_SEQUENTIAL');

        return (newDataRoot, newNullRoot, nums[0], nums[1], newRootRoot, nums[3], nums[2] + toInsert);
    }

    /**
     * @dev Process deposits and withdrawls.
     * @param proofData - the proof data
     * @param numTxs - number of transactions rolled up in the proof
     * @param signatures - bytes array of secp256k1 ECDSA signatures, authorising a transfer of tokens
     */
    function processDepositsAndWithdrawals(
        bytes memory proofData,
        uint256 numTxs,
        bytes memory signatures
    ) internal {
        uint256 sigIndex = 0x00;
        uint256 proofDataPtr;
        assembly {
            proofDataPtr := add(proofData, 0x20) // add 0x20 to skip over 1st field in bytes array (the length field)
        }
        proofDataPtr += rollupPubInputLength; // update pointer to skip over rollup public inputs and point to inner tx public inputs
        uint256 end = proofDataPtr + (numTxs * txPubInputLength);
        uint256 stepSize = txPubInputLength;

        // This is a bit of a hot loop, we iterate over every tx to determine whether to process deposits or withdrawals.
        while (proofDataPtr < end) {
            // extract the minimum information we need to determine whether to skip this iteration
            uint256 proofId;
            uint256 publicInput;
            uint256 publicOutput;
            bool txNeedsProcessing;
            assembly {
                proofId := mload(proofDataPtr)
                publicInput := mload(add(proofDataPtr, 0x20))
                publicOutput := mload(add(proofDataPtr, 0x40))
                // only process deposits and withdrawals iff
                // the proofId == 0 (not an account proof) and publicInput > 0 OR publicOutput > 0
                txNeedsProcessing := and(iszero(proofId), or(not(iszero(publicInput)), not(iszero(publicOutput))))
            }

            if (txNeedsProcessing) {
                // extract asset Id
                uint256 assetId;
                assembly {
                    assetId := mload(add(proofDataPtr, 0x60))
                }

                if (publicInput > 0) {
                    // validate user has approved deposit
                    address inputOwner;
                    bytes32 digest;
                    assembly {
                        inputOwner := mload(add(proofDataPtr, 0x140))

                        // compute the message digest to check if user has approved tx
                        digest := keccak256(proofDataPtr, stepSize)
                    }
                    if (!depositProofApprovals[inputOwner][digest]) {
                        // extract and validate signature
                        // we can create a bytes memory container for the signature without allocating new memory,
                        // by overwriting the previous 32 bytes in the `signatures` array with the 'length' of our synthetic byte array (92)
                        // we store the memory we overwrite in `temp`, so that we can restore it
                        bytes memory signature;
                        uint256 temp;
                        assembly {
                            // set `signature` to point to 32 bytes less than the desired `r, s, v` values in `signatures`
                            signature := add(signatures, sigIndex)
                            // cache the memory we're about to overwrite
                            temp := mload(signature)
                            // write in a 92-byte 'length' parameter into the `signature` bytes array
                            mstore(signature, 0x60)
                        }
                        // validate the signature
                        RollupProcessorLibrary.validateUnpackedSignature(digest, signature, inputOwner);
                        // restore the memory we overwrote
                        assembly {
                            mstore(signature, temp)
                            sigIndex := add(sigIndex, 0x60)
                        }
                    }
                    decreasePendingDepositBalance(assetId, inputOwner, publicInput);
                }

                if (publicOutput > 0) {
                    address outputOwner;
                    assembly {
                        outputOwner := mload(add(proofDataPtr, 0x160))
                    }
                    withdraw(publicOutput, outputOwner, assetId);
                }
            }
            proofDataPtr += txPubInputLength;
        }
    }

    function transferFee(bytes memory proofData) internal {
        for (uint256 i = 0; i < numberOfAssets; ++i) {
            uint256 txFee = extractTotalTxFee(proofData, i);
            if (txFee > 0) {
                bool success;
                if (i == ethAssetId) {
                    (success, ) = payable(feeDistributor).call{value: txFee}('');
                } else {
                    address assetAddress = getSupportedAsset(i);
                    IERC20(assetAddress).approve(feeDistributor, txFee);
                    (success, ) = feeDistributor.call(abi.encodeWithSignature('deposit(uint256,uint256)', i, txFee));
                }
                require(success, 'Rollup Processor: DEPOSIT_TX_FEE_FAILED');
                totalFees[i] = totalFees[i].add(txFee);
            }
        }
    }

    /**
     * @dev Internal utility function to withdraw funds from the contract to a receiver address
     * @param withdrawValue - value being withdrawn from the contract
     * @param receiverAddress - address receiving public ERC20 tokens
     * @param assetId - ID of the asset for which a withdrawl is being performed
     */
    function withdraw(
        uint256 withdrawValue,
        address receiverAddress,
        uint256 assetId
    ) internal {
        require(receiverAddress != address(0), 'Rollup Processor: ZERO_ADDRESS');
        if (assetId == 0) {
            // We explicitly do not throw if this call fails, as this opens up the possiblity of
            // griefing attacks, as engineering a failed withdrawal will invalidate an entire rollup block
            payable(receiverAddress).call{gas: 30000, value: withdrawValue}('');
        } else {
            address assetAddress = getSupportedAsset(assetId);
            IERC20(assetAddress).transfer(receiverAddress, withdrawValue);
        }
        totalWithdrawn[assetId] = totalWithdrawn[assetId].add(withdrawValue);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * 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);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.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, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @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) {
        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, reverting 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) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * 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, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

interface IVerifier {
    function verify(bytes memory serialized_proof, uint256 _keyId) external;
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

interface IRollupProcessor {
    function feeDistributor() external view returns (address);

    function escapeHatch(
        bytes calldata proofData,
        bytes calldata signatures,
        bytes calldata viewingKeys
    ) external;

    function processRollup(
        bytes calldata proofData,
        bytes calldata signatures,
        bytes calldata viewingKeys,
        bytes calldata providerSignature,
        address provider,
        address payable feeReceiver,
        uint256 feeLimit
    ) external;

    function depositPendingFunds(
        uint256 assetId,
        uint256 amount,
        address owner
    ) external payable;

    function depositPendingFundsPermit(
        uint256 assetId,
        uint256 amount,
        address owner,
        address spender,
        uint256 permitApprovalAmount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function setRollupProvider(address provderAddress, bool valid) external;

    function approveProof(bytes32 _proofHash) external;

    function setFeeDistributor(address feeDistributorAddress) external;

    function setVerifier(address verifierAddress) external;

    function setSupportedAsset(address linkedToken, bool supportsPermit) external;

    function setAssetPermitSupport(uint256 assetId, bool supportsPermit) external;

    function getSupportedAsset(uint256 assetId) external view returns (address);

    function getSupportedAssets() external view returns (address[] memory);

    function getTotalDeposited() external view returns (uint256[] memory);

    function getTotalWithdrawn() external view returns (uint256[] memory);

    function getTotalPendingDeposit() external view returns (uint256[] memory);

    function getTotalFees() external view returns (uint256[] memory);

    function getAssetPermitSupport(uint256 assetId) external view returns (bool);

    function getEscapeHatchStatus() external view returns (bool, uint256);

    function getUserPendingDeposit(uint256 assetId, address userAddress) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

interface IFeeDistributor {
    event FeeReimbursed(address receiver, uint256 amount);

    function txFeeBalance(uint256 assetId) external view returns (uint256);

    function deposit(uint256 assetId, uint256 amount) external payable returns (uint256 depositedAmount);

    function reimburseGas(
        uint256 gasUsed,
        uint256 feeLimit,
        address payable feeReceiver
    ) external returns (uint256 reimbursement);
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IERC20Permit is IERC20 {
    function nonces(address user) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {Types} from './verifier/cryptography/Types.sol';
import {Bn254Crypto} from './verifier/cryptography/Bn254Crypto.sol';

contract Decoder {
    using SafeMath for uint256;

    /**
     * @dev Decode the public inputs component of proofData. Required to update state variables
     * @param proofData - cryptographic proofData associated with a rollup
     */
    function decodeProof(bytes memory proofData, uint256 numberOfAssets)
        internal
        pure
        returns (
            uint256[4] memory nums,
            bytes32 oldDataRoot,
            bytes32 newDataRoot,
            bytes32 oldNullRoot,
            bytes32 newNullRoot,
            bytes32 oldRootRoot,
            bytes32 newRootRoot
        )
    {
        uint256 rollupId;
        uint256 rollupSize;
        uint256 dataStartIndex;
        uint256 numTxs;
        assembly {
            let dataStart := add(proofData, 0x20) // jump over first word, it's length of data
            rollupId := mload(dataStart)
            rollupSize := mload(add(dataStart, 0x20))
            dataStartIndex := mload(add(dataStart, 0x40))
            oldDataRoot := mload(add(dataStart, 0x60))
            newDataRoot := mload(add(dataStart, 0x80))
            oldNullRoot := mload(add(dataStart, 0xa0))
            newNullRoot := mload(add(dataStart, 0xc0))
            oldRootRoot := mload(add(dataStart, 0xe0))
            newRootRoot := mload(add(dataStart, 0x100))
            numTxs := mload(add(add(dataStart, 0x120), mul(0x20, numberOfAssets)))
        }
        return (
            [rollupId, rollupSize, dataStartIndex, numTxs],
            oldDataRoot,
            newDataRoot,
            oldNullRoot,
            newNullRoot,
            oldRootRoot,
            newRootRoot
        );
    }

    function extractTotalTxFee(bytes memory proofData, uint256 assetId) internal pure returns (uint256) {
        uint256 totalTxFee;
        assembly {
            totalTxFee := mload(add(add(proofData, 0x140), mul(0x20, assetId)))
        }
        return totalTxFee;
    }
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.10 <0.8.0;

library RollupProcessorLibrary {

    /**
    * Extracts the address of the signer with ECDSA. Performs checks on `s` and `v` to
    * to prevent signature malleability based attacks
    * @param digest - Hashed data being signed over.
    * @param signature - ECDSA signature over the secp256k1 elliptic curve.
    * @param signer - Address that signs the signature.
    */
    function validateSignature(
        bytes32 digest,
        bytes memory signature,
        address signer
    ) internal view {
        bool result;
        address recoveredSigner = address(0x0);
        require(signer != address(0x0), 'validateSignature: ZERO_ADDRESS');


        // prepend "\x19Ethereum Signed Message:\n32" to the digest to create the signed message
        bytes32 message;
        assembly {
            mstore(0, "\x19Ethereum Signed Message:\n32")
            mstore(add(0, 28), digest)
            message := keccak256(0, 60)
        }
        assembly {
            let mPtr := mload(0x40)
            let byteLength := mload(signature)

            // store the signature digest
            mstore(mPtr, message)

            // load 'v' - we need it for a condition check
            // add 0x60 to jump over 3 words - length of bytes array, r and s
            let v := shr(248, mload(add(signature, 0x60))) // bitshifting, to resemble padLeft
            let s := mload(add(signature, 0x40))

            /**
            * Original memory map for input to precompile
            *
            * signature : signature + 0x20            message
            * signature + 0x20 : signature + 0x40     r
            * signature + 0x40 : signature + 0x60     s
            * signature + 0x60 : signature + 0x80     v
            * Desired memory map for input to precompile
            *
            * signature : signature + 0x20            message
            * signature + 0x20 : signature + 0x40     v
            * signature + 0x40 : signature + 0x60     r
            * signature + 0x60 : signature + 0x80     s
            */

            // store s
            mstore(add(mPtr, 0x60), s)
            // store r
            mstore(add(mPtr, 0x40), mload(add(signature, 0x20)))
            // store v
            mstore(add(mPtr, 0x20), v)
            result := and(
                and(
                    // validate s is in lower half order
                    lt(s, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A1),
                    and(
                        // validate signature length == 0x41
                        eq(byteLength, 0x41),
                        // validate v == 27 or v == 28
                        or(eq(v, 27), eq(v, 28))
                    )
                ),
                // validate call to ecrecover precompile succeeds
                staticcall(gas(), 0x01, mPtr, 0x80, mPtr, 0x20)
            )

            // save the recoveredSigner only if the first word in signature is not `message` anymore
            switch eq(message, mload(mPtr))
            case 0 {
                recoveredSigner := mload(mPtr)
            }
            mstore(mPtr, byteLength) // and put the byte length back where it belongs
        
            // validate that recoveredSigner is not address(0x00)
            result := and(result, not(iszero(recoveredSigner)))
        }

        require(result, 'validateSignature: signature recovery failed');
        require(recoveredSigner == signer, 'validateSignature: INVALID_SIGNATURE');
    }

    /**
    * Extracts the address of the signer with ECDSA. Performs checks on `s` and `v` to
    * to prevent signature malleability based attacks
    * This 'Unpacked' version expects 'signature' to be a 92-byte array.
    * i.e. the `v` parameter occupies a full 32 bytes of memory, not 1 byte 
    * @param digest - Hashed data being signed over.
    * @param signature - ECDSA signature over the secp256k1 elliptic curve.
    * @param signer - Address that signs the signature.
    */
    function validateUnpackedSignature(
        bytes32 digest,
        bytes memory signature,
        address signer
    ) internal view {
        bool result;
        address recoveredSigner = address(0x0);
        require(signer != address(0x0), 'validateSignature: ZERO_ADDRESS');


        // prepend "\x19Ethereum Signed Message:\n32" to the digest to create the signed message
        bytes32 message;
        assembly {
            mstore(0, "\x19Ethereum Signed Message:\n32")
            mstore(28, digest)
            message := keccak256(0, 60)
        }
        assembly {
            // There's a little trick we can pull. We expect `signature` to be a byte array, of length 0x60, with
            // 'v', 'r' and 's' located linearly in memory. Preceeding this is the length parameter of `signature`.
            // We *replace* the length param with the signature msg to get a memory block formatted for the precompile
            // load length as a temporary variable
            // N.B. we mutate the signature by re-ordering r, s, and v!
            let byteLength := mload(signature)

            // store the signature digest
            mstore(signature, message)

            // load 'v' - we need it for a condition check
            // add 0x60 to jump over 3 words - length of bytes array, r and s
            let v := mload(add(signature, 0x60))
            let s := mload(add(signature, 0x40))

            /**
            * Original memory map for input to precompile
            *
            * signature : signature + 0x20            message
            * signature + 0x20 : signature + 0x40     r
            * signature + 0x40 : signature + 0x60     s
            * signature + 0x60 : signature + 0x80     v
            * Desired memory map for input to precompile
            *
            * signature : signature + 0x20            message
            * signature + 0x20 : signature + 0x40     v
            * signature + 0x40 : signature + 0x60     r
            * signature + 0x60 : signature + 0x80     s
            */

            // move s to v position
            mstore(add(signature, 0x60), s)
            // move r to s position
            mstore(add(signature, 0x40), mload(add(signature, 0x20)))
            // move v to r position
            mstore(add(signature, 0x20), v)
            result := and(
                and(
                    // validate s is in lower half order
                    lt(s, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A1),
                    and(
                        // validate signature length == 0x60 (unpacked)
                        eq(byteLength, 0x60),
                        // validate v == 27 or v == 28
                        or(eq(v, 27), eq(v, 28))
                    )
                ),
                // validate call to ecrecover precompile succeeds
                staticcall(gas(), 0x01, signature, 0x80, signature, 0x20)
            )

            // save the recoveredSigner only if the first word in signature is not `message` anymore
            switch eq(message, mload(signature))
            case 0 {
                recoveredSigner := mload(signature)
            }
            mstore(signature, byteLength) // and put the byte length back where it belongs
        
            // validate that recoveredSigner is not address(0x00)
            result := and(result, not(iszero(recoveredSigner)))
        }

        require(result, 'validateSignature: signature recovery failed');
        require(recoveredSigner == signer, 'validateSignature: INVALID_SIGNATURE');
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 13 of 14 : Types.sol
// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd

pragma solidity >=0.6.0 <0.8.0;
pragma experimental ABIEncoderV2;

/**
 * @title Bn254Crypto library used for the fr, g1 and g2 point types
 * @dev Used to manipulate fr, g1, g2 types, perform modular arithmetic on them and call
 * the precompiles add, scalar mul and pairing
 *
 * Notes on optimisations
 * 1) Perform addmod, mulmod etc. in assembly - removes the check that Solidity performs to confirm that
 * the supplied modulus is not 0. This is safe as the modulus's used (r_mod, q_mod) are hard coded
 * inside the contract and not supplied by the user
 */
library Types {
    uint256 constant PROGRAM_WIDTH = 4;
    uint256 constant NUM_NU_CHALLENGES = 11;

    uint256 constant coset_generator0 = 0x0000000000000000000000000000000000000000000000000000000000000005;
    uint256 constant coset_generator1 = 0x0000000000000000000000000000000000000000000000000000000000000006;
    uint256 constant coset_generator2 = 0x0000000000000000000000000000000000000000000000000000000000000007;

    // TODO: add external_coset_generator() method to compute this
    uint256 constant coset_generator7 = 0x000000000000000000000000000000000000000000000000000000000000000c;

    struct G1Point {
        uint256 x;
        uint256 y;
    }

    // G2 group element where x \in Fq2 = x0 * z + x1
    struct G2Point {
        uint256 x0;
        uint256 x1;
        uint256 y0;
        uint256 y1;
    }

    // N>B. Do not re-order these fields! They must appear in the same order as they
    // appear in the proof data
    struct Proof {
        G1Point W1;
        G1Point W2;
        G1Point W3;
        G1Point W4;
        G1Point Z;
        G1Point T1;
        G1Point T2;
        G1Point T3;
        G1Point T4;
        uint256 w1;
        uint256 w2;
        uint256 w3;
        uint256 w4;
        uint256 sigma1;
        uint256 sigma2;
        uint256 sigma3;
        uint256 q_arith;
        uint256 q_ecc;
        uint256 q_c;
        uint256 linearization_polynomial;
        uint256 grand_product_at_z_omega;
        uint256 w1_omega;
        uint256 w2_omega;
        uint256 w3_omega;
        uint256 w4_omega;
        G1Point PI_Z;
        G1Point PI_Z_OMEGA;
        G1Point recursive_P1;
        G1Point recursive_P2;
        uint256 quotient_polynomial_eval;
    }

    struct ChallengeTranscript {
        uint256 alpha_base;
        uint256 alpha;
        uint256 zeta;
        uint256 beta;
        uint256 gamma;
        uint256 u;
        uint256 v0;
        uint256 v1;
        uint256 v2;
        uint256 v3;
        uint256 v4;
        uint256 v5;
        uint256 v6;
        uint256 v7;
        uint256 v8;
        uint256 v9;
        uint256 v10;
    }

    struct VerificationKey {
        uint256 circuit_size;
        uint256 num_inputs;
        uint256 work_root;
        uint256 domain_inverse;
        uint256 work_root_inverse;
        G1Point Q1;
        G1Point Q2;
        G1Point Q3;
        G1Point Q4;
        G1Point Q5;
        G1Point QM;
        G1Point QC;
        G1Point QARITH;
        G1Point QECC;
        G1Point QRANGE;
        G1Point QLOGIC;
        G1Point SIGMA1;
        G1Point SIGMA2;
        G1Point SIGMA3;
        G1Point SIGMA4;
        bool contains_recursive_proof;
        uint256 recursive_proof_indices;
        G2Point g2_x;

        // zeta challenge raised to the power of the circuit size.
        // Not actually part of the verification key, but we put it here to prevent stack depth errors
        uint256 zeta_pow_n;
    }
}

// SPDX-License-Identifier: GPL-2.0-only
// Copyright 2020 Spilsbury Holdings Ltd
pragma solidity >=0.6.0 <0.8.0;
pragma experimental ABIEncoderV2;

import {Types} from "./Types.sol";

/**
 * @title Bn254 elliptic curve crypto
 * @dev Provides some basic methods to compute bilinear pairings, construct group elements and misc numerical methods
 */
library Bn254Crypto {
    uint256 constant p_mod = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    uint256 constant r_mod = 21888242871839275222246405745257275088548364400416034343698204186575808495617;

    // Perform a modular exponentiation. This method is ideal for small exponents (~64 bits or less), as
    // it is cheaper than using the pow precompile
    function pow_small(
        uint256 base,
        uint256 exponent,
        uint256 modulus
    ) internal pure returns (uint256) {
        uint256 result = 1;
        uint256 input = base;
        uint256 count = 1;

        assembly {
            let endpoint := add(exponent, 0x01)
            for {} lt(count, endpoint) { count := add(count, count) }
            {
                if and(exponent, count) {
                    result := mulmod(result, input, modulus)
                }
                input := mulmod(input, input, modulus)
            }
        }

        return result;
    }

    function invert(uint256 fr) internal view returns (uint256)
    {
        uint256 output;
        bool success;
        uint256 p = r_mod;
        assembly {
            let mPtr := mload(0x40)
            mstore(mPtr, 0x20)
            mstore(add(mPtr, 0x20), 0x20)
            mstore(add(mPtr, 0x40), 0x20)
            mstore(add(mPtr, 0x60), fr)
            mstore(add(mPtr, 0x80), sub(p, 2))
            mstore(add(mPtr, 0xa0), p)
            success := staticcall(gas(), 0x05, mPtr, 0xc0, 0x00, 0x20)
            output := mload(0x00)
        }
        require(success, "pow precompile call failed!");
        return output;
    }

    function new_g1(uint256 x, uint256 y)
        internal
        pure
        returns (Types.G1Point memory)
    {
        uint256 xValue;
        uint256 yValue;
        assembly {
            xValue := mod(x, r_mod)
            yValue := mod(y, r_mod)
        }
        return Types.G1Point(xValue, yValue);
    }

    function new_g2(uint256 x0, uint256 x1, uint256 y0, uint256 y1)
        internal
        pure
        returns (Types.G2Point memory)
    {
        return Types.G2Point(x0, x1, y0, y1);
    }

    function P1() internal pure returns (Types.G1Point memory) {
        return Types.G1Point(1, 2);
    }

    function P2() internal pure returns (Types.G2Point memory) {
        return Types.G2Point({
            x0: 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2,
            x1: 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed,
            y0: 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b,
            y1: 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa
        });
    }


    /// Evaluate the following pairing product:
    /// e(a1, a2).e(-b1, b2) == 1
    function pairingProd2(
        Types.G1Point memory a1,
        Types.G2Point memory a2,
        Types.G1Point memory b1,
        Types.G2Point memory b2
    ) internal view returns (bool) {
        validateG1Point(a1);
        validateG1Point(b1);
        bool success;
        uint256 out;
        assembly {
            let mPtr := mload(0x40)
            mstore(mPtr, mload(a1))
            mstore(add(mPtr, 0x20), mload(add(a1, 0x20)))
            mstore(add(mPtr, 0x40), mload(a2))
            mstore(add(mPtr, 0x60), mload(add(a2, 0x20)))
            mstore(add(mPtr, 0x80), mload(add(a2, 0x40)))
            mstore(add(mPtr, 0xa0), mload(add(a2, 0x60)))

            mstore(add(mPtr, 0xc0), mload(b1))
            mstore(add(mPtr, 0xe0), mload(add(b1, 0x20)))
            mstore(add(mPtr, 0x100), mload(b2))
            mstore(add(mPtr, 0x120), mload(add(b2, 0x20)))
            mstore(add(mPtr, 0x140), mload(add(b2, 0x40)))
            mstore(add(mPtr, 0x160), mload(add(b2, 0x60)))
            success := staticcall(
                gas(),
                8,
                mPtr,
                0x180,
                0x00,
                0x20
            )
            out := mload(0x00)
        }
        require(success, "Pairing check failed!");
        return (out != 0);
    }

    /**
    * validate the following:
    *   x != 0
    *   y != 0
    *   x < p
    *   y < p
    *   y^2 = x^3 + 3 mod p
    */
    function validateG1Point(Types.G1Point memory point) internal pure {
        bool is_well_formed;
        uint256 p = p_mod;
        assembly {
            let x := mload(point)
            let y := mload(add(point, 0x20))

            is_well_formed := and(
                and(
                    and(lt(x, p), lt(y, p)),
                    not(or(iszero(x), iszero(y)))
                ),
                eq(mulmod(y, y, p), addmod(mulmod(x, mulmod(x, x, p), p), 3, p))
            )
        }
        require(is_well_formed, "Bn254: G1 point not on curve, or is malformed");
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"},{"internalType":"uint256","name":"_escapeBlockLowerBound","type":"uint256"},{"internalType":"uint256","name":"_escapeBlockUpperBound","type":"uint256"},{"internalType":"address","name":"_contractOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"}],"name":"AssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"address","name":"depositorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositValue","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rollupId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"dataRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"nullRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"rootRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"dataSize","type":"uint256"}],"name":"RollupProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"providerAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"valid","type":"bool"}],"name":"RollupProviderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"verifierAddress","type":"address"}],"name":"VerifierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetId","type":"uint256"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawValue","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"errorReason","type":"bytes"}],"name":"WithdrawError","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_proofHash","type":"bytes32"}],"name":"approveProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dataRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"depositorAddress","type":"address"}],"name":"depositPendingFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"depositorAddress","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"permitApprovalAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"depositPendingFundsPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositProofApprovals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"escapeBlockLowerBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"escapeBlockUpperBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"proofData","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"internalType":"bytes","name":"viewingKeys","type":"bytes"}],"name":"escapeHatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethAssetId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"getAssetPermitSupport","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEscapeHatchStatus","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"}],"name":"getSupportedAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedAssets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDeposited","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalFees","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPendingDeposit","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalWithdrawn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"}],"name":"getUserPendingDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextRollupId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nullRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"proofData","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"internalType":"bytes","name":"viewingKeys","type":"bytes"},{"internalType":"bytes","name":"providerSignature","type":"bytes"},{"internalType":"address","name":"provider","type":"address"},{"internalType":"address payable","name":"feeReceiver","type":"address"},{"internalType":"uint256","name":"feeLimit","type":"uint256"}],"name":"processRollup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollupNumPubInputs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rollupProviders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rollupPubInputLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"bool","name":"supportsPermit","type":"bool"}],"name":"setAssetPermitSupport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeDistributorAddress","type":"address"}],"name":"setFeeDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"providerAddress","type":"address"},{"internalType":"bool","name":"valid","type":"bool"}],"name":"setRollupProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"linkedToken","type":"address"},{"internalType":"bool","name":"supportsPermit","type":"bool"}],"name":"setSupportedAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifierAddress","type":"address"}],"name":"setVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedAssets","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalPendingDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"txNumPubInputs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"txPubInputLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userPendingDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract IVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c06040527f2708a627d38d74d478f645ec3b4e91afa325331acf1acebe9077891146b75e396001557f2694dbe3c71a25d92213422d392479e7b8ef437add81e1e17244462e6edca9b16002557f2d264e93dc455751a721aead9dba9ee2a9fef5460921aeede73f63f6210e68516003553480156200007d57600080fd5b50604051620036763803806200367683398181016040526080811015620000a357600080fd5b50805160208201516040830151606090930151919290916000620000cf6001600160e01b036200022416565b600080546001600160a01b0319166001600160a01b03831690811782556040519293509160008051602062003656833981519152908290a3506000805460ff60a01b19168155600680546001600160a01b0319166001600160a01b038716179055608084905260a0839052338152600b60205260408120805460ff19166001908117909155600d80548083019091557fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb501829055600e80548083019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01829055600f80548083019091557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020182905560108054918201815582527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae67201556200021a8162000228565b5050505062000353565b3390565b6200023b6001600160e01b036200022416565b6001600160a01b0316620002576001600160e01b036200034416565b6001600160a01b031614620002b3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116620002fa5760405162461bcd60e51b8152600401808060200182810382526026815260200180620036306026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206200365683398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031690565b60805160a05161329b6200039560003980611651528061168752806116b152806116da5280611a4f5250806115b152806116305280611704525061329b6000f3fe60806040526004361061027d5760003560e01c806394401d751161014f578063d1d2d95e116100c1578063e5406dbf1161007a578063e5406dbf14610b13578063e70626e614610b28578063edf49c0914610b3d578063ef76e2ee14610b52578063f0e7e29b14610b8d578063f2fde38b14610ba25761027d565b8063d1d2d95e14610a39578063d28bbda514610a6b578063d6ae328414610a95578063d8ba363714610abf578063e059d80714610ad4578063e393635514610ae95761027d565b8063b68ef55911610113578063b68ef55914610852578063be71f8a414610867578063c68dbb3714610897578063c6c62390146108c1578063ccfc2e8d146108eb578063d1c652641461091e5761027d565b806394401d75146107b0578063a009f7e4146107c5578063a3d205f4146107ef578063ae35bfc214610828578063b045009c1461083d5761027d565b80635437988d116101f35780636dff3584116101ac5780636dff3584146106e8578063715018a6146106fd578063781e04321461071257806389404a791461074b5780638da5cb5b1461076057806391dfe78f146107755761027d565b80635437988d146106055780635ad1def3146106385780635c975abb1461067f57806360a8b18a14610694578063626e1ae7146106be57806366535f30146106d35761027d565b806336ce0a921161024557806336ce0a92146104e1578063408ccbdf1461051a57806344c5125214610544578063479b3d951461055957806347a695a71461058b57806349ce468d146105f05761027d565b8063018892ac1461028257806306011a46146102f05780630d43e8ad146104745780632b7ac3f3146104a55780633248295f146104ba575b600080fd5b34801561028e57600080fd5b506102ee60048036036101208110156102a657600080fd5b508035906020810135906001600160a01b03604082013581169160608101359091169060808101359060a08101359060ff60c0820135169060e0810135906101000135610bd5565b005b3480156102fc57600080fd5b506102ee600480360360e081101561031357600080fd5b810190602081018135600160201b81111561032d57600080fd5b82018360208201111561033f57600080fd5b803590602001918460018302840111600160201b8311171561036057600080fd5b919390929091602081019035600160201b81111561037d57600080fd5b82018360208201111561038f57600080fd5b803590602001918460018302840111600160201b831117156103b057600080fd5b919390929091602081019035600160201b8111156103cd57600080fd5b8201836020820111156103df57600080fd5b803590602001918460018302840111600160201b8311171561040057600080fd5b919390929091602081019035600160201b81111561041d57600080fd5b82018360208201111561042f57600080fd5b803590602001918460018302840111600160201b8311171561045057600080fd5b91935091506001600160a01b03813581169160208101359091169060400135610cd8565b34801561048057600080fd5b5061048961106c565b604080516001600160a01b039092168252519081900360200190f35b3480156104b157600080fd5b5061048961107b565b3480156104c657600080fd5b506104cf61108a565b60408051918252519081900360200190f35b3480156104ed57600080fd5b506104cf6004803603604081101561050457600080fd5b50803590602001356001600160a01b0316611090565b34801561052657600080fd5b506104cf6004803603602081101561053d57600080fd5b50356110ad565b34801561055057600080fd5b506104cf6110cb565b34801561056557600080fd5b506102ee6004803603604081101561057c57600080fd5b508035906020013515156110d0565b34801561059757600080fd5b506105a06111ad565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105dc5781810151838201526020016105c4565b505050509050019250505060405180910390f35b3480156105fc57600080fd5b506104cf611205565b34801561061157600080fd5b506102ee6004803603602081101561062857600080fd5b50356001600160a01b031661120b565b34801561064457600080fd5b5061066b6004803603602081101561065b57600080fd5b50356001600160a01b03166112b7565b604080519115158252519081900360200190f35b34801561068b57600080fd5b5061066b6112cc565b3480156106a057600080fd5b50610489600480360360208110156106b757600080fd5b50356112dc565b3480156106ca57600080fd5b506105a0611318565b3480156106df57600080fd5b506104cf61136e565b3480156106f457600080fd5b506104cf611374565b34801561070957600080fd5b506102ee61137a565b34801561071e57600080fd5b5061066b6004803603604081101561073557600080fd5b506001600160a01b038135169060200135611426565b34801561075757600080fd5b506105a0611446565b34801561076c57600080fd5b5061048961149c565b34801561078157600080fd5b506102ee6004803603604081101561079857600080fd5b506001600160a01b03813516906020013515156114ab565b3480156107bc57600080fd5b506104cf61156d565b3480156107d157600080fd5b506104cf600480360360208110156107e857600080fd5b5035611573565b3480156107fb57600080fd5b506104cf6004803603604081101561081257600080fd5b50803590602001356001600160a01b0316611580565b34801561083457600080fd5b506104cf6115aa565b34801561084957600080fd5b506104cf6115af565b34801561085e57600080fd5b506105a06115d3565b34801561087357600080fd5b5061087c611629565b60408051921515835260208301919091528051918290030190f35b3480156108a357600080fd5b50610489600480360360208110156108ba57600080fd5b5035611731565b3480156108cd57600080fd5b506104cf600480360360208110156108e457600080fd5b5035611758565b3480156108f757600080fd5b506102ee6004803603602081101561090e57600080fd5b50356001600160a01b0316611765565b34801561092a57600080fd5b506102ee6004803603606081101561094157600080fd5b810190602081018135600160201b81111561095b57600080fd5b82018360208201111561096d57600080fd5b803590602001918460018302840111600160201b8311171561098e57600080fd5b919390929091602081019035600160201b8111156109ab57600080fd5b8201836020820111156109bd57600080fd5b803590602001918460018302840111600160201b831117156109de57600080fd5b919390929091602081019035600160201b8111156109fb57600080fd5b820183602082011115610a0d57600080fd5b803590602001918460018302840111600160201b83111715610a2e57600080fd5b5090925090506117e9565b6102ee60048036036060811015610a4f57600080fd5b50803590602081013590604001356001600160a01b03166118ff565b348015610a7757600080fd5b5061066b60048036036020811015610a8e57600080fd5b5035611a12565b348015610aa157600080fd5b506104cf60048036036020811015610ab857600080fd5b5035611a40565b348015610acb57600080fd5b506104cf611a4d565b348015610ae057600080fd5b506104cf611a71565b348015610af557600080fd5b506102ee60048036036020811015610b0c57600080fd5b5035611a77565b348015610b1f57600080fd5b506105a0611aea565b348015610b3457600080fd5b506104cf611b4b565b348015610b4957600080fd5b506104cf611b50565b348015610b5e57600080fd5b506102ee60048036036040811015610b7557600080fd5b506001600160a01b0381351690602001351515611b55565b348015610b9957600080fd5b506104cf611db2565b348015610bae57600080fd5b506102ee60048036036020811015610bc557600080fd5b50356001600160a01b0316611db8565b610bdd6112cc565b15610c22576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000610c2d8a6112dc565b6040805163d505accf60e01b81526001600160a01b038b811660048301528a81166024830152604482018a90526064820189905260ff8816608483015260a4820187905260c4820186905291519293509083169163d505accf9160e48082019260009290919082900301818387803b158015610ca857600080fd5b505af1158015610cbc573d6000803e3d6000fd5b50505050610ccc8a828a8c611eba565b50505050505050505050565b610ce06112cc565b15610d25576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b60005a6001600160a01b0385166000908152600b602052604090205490915060ff16610d825760405162461bcd60e51b815260040180806020018281038252602281526020018061302f6022913960400191505060405180910390fd5b60608c8c6000906004600a0160200292610d9e93929190612f69565b600c54604051879187916001600160a01b03909116906020018086868082843780830192505050846001600160a01b03166001600160a01b031660601b8152601401838152602001826001600160a01b03166001600160a01b031660601b8152601401955050505050506040516020818303038152906040529050610e62818051906020012088888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612058915050565b610eea8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d91506122019050565b610f298d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061222092505050565b600c546000906001600160a01b03165a604080519186036024830152604482018790526001600160a01b03881660648084019190915281518084039091018152608490920181526020820180516001600160e01b03166356aa719960e01b17815290518251909182918083835b60208310610fb55780518252601f199092019160209182019101610f96565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611017576040519150601f19603f3d011682016040523d82523d6000602084013e61101c565b606091505b505090508061105c5760405162461bcd60e51b8152600401808060200182810382526026815260200180612fe66026913960400191505060405180910390fd5b5050505050505050505050505050565b600c546001600160a01b031681565b6006546001600160a01b031681565b60035481565b600960209081526000928352604080842090915290825290205481565b601081815481106110ba57fe5b600091825260209091200154905081565b600e81565b6110d86124ab565b6001600160a01b03166110e961149c565b6001600160a01b031614611132576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600061113d836112dc565b90506001600160a01b0381166111845760405162461bcd60e51b81526004018080602001828103825260288152602001806130a96028913960400191505060405180910390fd5b6001600160a01b03166000908152600860205260409020805460ff191691151591909117905550565b6060600d8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020905b8154815260200190600101908083116111e7575b5050505050905090565b60045481565b6112136124ab565b6001600160a01b031661122461149c565b6001600160a01b03161461126d576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040517fd24015cc99cc1700cafca3042840a1d8ac1e3964fd2e0e37ea29c654056ee32790600090a250565b600b6020526000908152604090205460ff1681565b600054600160a01b900460ff1690565b6000816112eb57506000611313565b600760018303815481106112fb57fe5b6000918252602090912001546001600160a01b031690505b919050565b606060108054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b61018081565b60015481565b6113826124ab565b6001600160a01b031661139361149c565b6001600160a01b0316146113dc576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600a60209081526000928352604080842090915290825290205460ff1681565b6060600f8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b6000546001600160a01b031690565b6114b36124ab565b6001600160a01b03166114c461149c565b6001600160a01b03161461150d576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b0382166000818152600b6020908152604091829020805460ff1916851515908117909155825190815291517f46359ce9dbb6c7f9a375b44072210287916d3de725fc8927a8e762047e4a84249281900390910190a25050565b60025481565b600f81815481106110ba57fe5b60008281526009602090815260408083206001600160a01b03851684529091529020545b92915050565b600c81565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060600e8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b60008043817f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000838161167857fe5b0610801591506000906116d8577f000000000000000000000000000000000000000000000000000000000000000083816116ae57fe5b067f0000000000000000000000000000000000000000000000000000000000000000039050611727565b7f0000000000000000000000000000000000000000000000000000000000000000838161170157fe5b067f00000000000000000000000000000000000000000000000000000000000000000390505b9093509150509091565b6007818154811061173e57fe5b6000918252602090912001546001600160a01b0316905081565b600e81815481106110ba57fe5b61176d6124ab565b6001600160a01b031661177e61149c565b6001600160a01b0316146117c7576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6117f16112cc565b15611836576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000611840611629565b5090508061187f5760405162461bcd60e51b815260040180806020018281038252602e815260200180612fb8602e913960400191505060405180910390fd5b6118f687878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152508892508791506122019050565b50505050505050565b6119076112cc565b1561194c576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b826119b5578134146119a5576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a2057524f4e475f414d4f554e540000604482015290519081900360640190fd5b6119b08382846124af565b611a0d565b34156119f25760405162461bcd60e51b81526004018080602001828103825260248152602001806132426024913960400191505060405180910390fd5b60006119fd846112dc565b9050611a0b84828486611eba565b505b505050565b600080611a1e836112dc565b6001600160a01b031660009081526008602052604090205460ff169392505050565b600d81815481106110ba57fe5b7f000000000000000000000000000000000000000000000000000000000000000081565b60055481565b611a7f6112cc565b15611ac4576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b336000908152600a6020908152604080832093835292905220805460ff19166001179055565b606060078054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b24575050505050905090565b600081565b600481565b611b5d6124ab565b6001600160a01b0316611b6e61149c565b6001600160a01b031614611bb7576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b038216611c12576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a205a45524f5f414444524553530000604482015290519081900360640190fd5b600780546001810182557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319166001600160a01b0385169081179091556000908152600860205260409020805460ff19168315151790555460048110611cb45760405162461bcd60e51b81526004018080602001828103825260238152602001806131a76023913960400191505060405180910390fd5b600d8054600181810190925560007fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5909101819055600e80548084019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01819055600f80548084019091557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020181905560108054928301815581527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6729091018190556040516001600160a01b0385169183917fc53536963369dbfa4c398238ebb9b09fce3943a140928bd25d3052a8a9cacdaf9190a3505050565b6101c081565b611dc06124ab565b6001600160a01b0316611dd161149c565b6001600160a01b031614611e1a576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b038116611e5f5760405162461bcd60e51b8152600401808060200182810382526026815260200180612f926026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60408051636eb1769f60e11b81526001600160a01b038481166004830152306024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b158015611f0b57600080fd5b505afa158015611f1f573d6000803e3d6000fd5b505050506040513d6020811015611f3557600080fd5b5051905081811015611f785760405162461bcd60e51b815260040180806020018281038252602d8152602001806131ef602d913960400191505060405180910390fd5b604080516323b872dd60e01b81526001600160a01b038581166004830152306024830152604482018590529151918616916323b872dd916064808201926020929091908290030181600087803b158015611fd157600080fd5b505af1158015611fe5573d6000803e3d6000fd5b505050506040513d6020811015611ffb57600080fd5b5061200990508584846124af565b604080518681526001600160a01b038516602082015280820184905290517feaa18152488ce5959073c9c79c88ca90b3d96c00de1f118cfaad664c3dab06b99181900360600190a15050505050565b6000806001600160a01b0383166120b6576040805162461bcd60e51b815260206004820152601f60248201527f76616c69646174655369676e61747572653a205a45524f5f4144445245535300604482015290519081900360640190fd5b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005285601c60000152603c60002090506040518551828252606087015160f81c60408801518060608501526020890151604085015281602085015260208460808660015afa601c8314601b84141760418514166fa2a8918ca85bafe22016d0b997e4df5f600160ff1b038310161696505050815183146000811461215d57612162565b825194505b5090528115199290921691826121a95760405162461bcd60e51b815260040180806020018281038252602c815260200180613051602c913960400191505060405180910390fd5b836001600160a01b0316826001600160a01b0316146121f95760405162461bcd60e51b815260040180806020018281038252602481526020018061315e6024913960400191505060405180910390fd5b505050505050565b600061220c85612537565b90506122198582866126a2565b5050505050565b60005b60048110156124a75760006122388383612773565b9050801561249e576000826122a457600c546040516001600160a01b03909116908390600081818185875af1925050503d8060008114612294576040519150601f19603f3d011682016040523d82523d6000602084013e612299565b606091505b50508091505061241d565b60006122af846112dc565b600c546040805163095ea7b360e01b81526001600160a01b0392831660048201526024810187905290519293509083169163095ea7b3916044808201926020929091908290030181600087803b15801561230857600080fd5b505af115801561231c573d6000803e3d6000fd5b505050506040513d602081101561233257600080fd5b5050600c546040805160248101879052604480820187905282518083039091018152606490910182526020810180516001600160e01b0316631c57762b60e31b178152915181516001600160a01b0390941693919290918291908083835b602083106123af5780518252601f199092019160209182019101612390565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612411576040519150601f19603f3d011682016040523d82523d6000602084013e612416565b606091505b5090925050505b806124595760405162461bcd60e51b81526004018080602001828103825260278152602001806131376027913960400191505060405180910390fd5b612483826010858154811061246a57fe5b906000526020600020015461278490919063ffffffff16565b6010848154811061249057fe5b600091825260209091200155505b50600101612223565b5050565b3390565b60008381526009602090815260408083206001600160a01b03861684529091529020546124e2908263ffffffff61278416565b60008481526009602090815260408083206001600160a01b0387168452909152902055600d80546125199183918690811061246a57fe5b600d848154811061252657fe5b600091825260209091200155505050565b60008060008060008060008061254c896127e5565b9650965096509650965096509650600080905060008060008060448e03600654945080519350602081015192506040810151915060ac815360316001820153608c6002820153605d60038201536040600482015289602482015260648f51016000808284895afa9650508381528260208201528160408201525084612618576040805162461bcd60e51b815260206004820152601960248201527f70726f6f6620766572696669636174696f6e206661696c656400000000000000604482015290519081900360640190fd5b60018c815560028c9055612633908b9063ffffffff61278416565b600555600388905560048690556001546002546040805192835260208301919091528181018a905260608201889052518b917ff1034928243e3365c0bf101598066f51439bb2a8763ec84cf7902d8917fb974f919081900360800190a250949c9b505050505050505050505050565b60006101e0808501906101808581028701909101905b818310156118f6578251602084015160408501518215821519821519171680156127625760608701518315612747576101408801518689206001600160a01b0382166000908152600a6020908152604080832084845290915290205460ff16612739578b8b0180516060825261272f838386612a5c565b905260609a909a01995b612744838388612ba4565b50505b82156127605761016088015161275e848284612cb1565b505b505b5050506101809390930192506126b8565b602081028201610140015192915050565b6000828201838110156127de576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008060008060008060006127f8612f4b565b60008060008060008061280c8f6004612e25565b96509650965096509650965096508660016004811061282757fe5b60200201511561283b57602087015161283e565b60015b60608801819052600090612853906002612e95565b9050806004548161286057fe5b066128ae576004546040890151146128a95760405162461bcd60e51b815260040180806020018281038252602c81526020018061307d602c913960400191505060405180910390fd5b612915565b600081600454816128bb57fe5b06826004540103905080896002600481106128d257fe5b6020020151146129135760405162461bcd60e51b815260040180806020018281038252602c81526020018061307d602c913960400191505060405180910390fd5b505b60015487146129555760405162461bcd60e51b81526004018080602001828103825260258152602001806131ca6025913960400191505060405180910390fd5b60025485146129955760405162461bcd60e51b81526004018080602001828103825260258152602001806131826025913960400191505060405180910390fd5b60035483146129d55760405162461bcd60e51b81526004018080602001828103825260258152602001806130d16025913960400191505060405180910390fd5b600554885114612a165760405162461bcd60e51b815260040180806020018281038252602381526020018061300c6023913960400191505060405180910390fd5b858489600060200201518a60016020020151858c60036020020151868e60026020020151019e509e509e509e509e509e509e505050505050505050919395979092949650565b6000806001600160a01b038316612aba576040805162461bcd60e51b815260206004820152601f60248201527f76616c69646174655369676e61747572653a205a45524f5f4144445245535300604482015290519081900360640190fd5b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005285601c52603c60002090508451818652606086015160408701518060608901526020880151604089015281602089015260208860808a60015afa601c8314601b84141760608514166fa2a8918ca85bafe22016d0b997e4df5f600160ff1b0383101616955050508551821460008114612b5857612b5d565b865193505b5085528115199290921691826121a95760405162461bcd60e51b815260040180806020018281038252602c815260200180613051602c913960400191505060405180910390fd5b60008381526009602090815260408083206001600160a01b038616845290915290205481811015612c065760405162461bcd60e51b815260040180806020018281038252602681526020018061321c6026913960400191505060405180910390fd5b612c16818363ffffffff612eee16565b60008581526009602090815260408083206001600160a01b0388168452909152902055600d8054612c6691849187908110612c4d57fe5b9060005260206000200154612eee90919063ffffffff16565b600d8581548110612c7357fe5b9060005260206000200181905550612c9282600e868154811061246a57fe5b600e8581548110612c9f57fe5b60009182526020909120015550505050565b6001600160a01b038216612d0c576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a205a45524f5f414444524553530000604482015290519081900360640190fd5b80612d6c576040516001600160a01b038316906175309085906000818181858888f193505050503d8060008114612d5f576040519150601f19603f3d011682016040523d82523d6000602084013e612d64565b606091505b505050612e07565b6000612d77826112dc565b9050806001600160a01b031663a9059cbb84866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612dd957600080fd5b505af1158015612ded573d6000803e3d6000fd5b505050506040513d6020811015612e0357600080fd5b5050505b612e1883600f838154811061246a57fe5b600f828154811061252657fe5b612e2d612f4b565b5060208281015160408085015160608087015160808089015160a08a015160c08b015160e08c01516101008d01516101208e01519c8c02909d01610140015189519586018a529985529984019690965295820192909252918201949094529692959194909392565b600082612ea4575060006115a4565b82820282848281612eb157fe5b04146127de5760405162461bcd60e51b81526004018080602001828103825260218152602001806130f66021913960400191505060405180910390fd5b600082821115612f45576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60405180608001604052806004906020820280368337509192915050565b60008085851115612f78578182fd5b83861115612f84578182fd5b505082019391909203915056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373526f6c6c75702050726f636573736f723a204553434150455f424c4f434b5f52414e47455f494e434f5252454354526f6c6c75702050726f636573736f723a205245494d42555253455f4741535f4641494c4544526f6c6c75702050726f636573736f723a2049445f4e4f545f53455155454e5449414c526f6c6c75702050726f636573736f723a20554e4b4e4f574e5f50524f564944455276616c69646174655369676e61747572653a207369676e6174757265207265636f76657279206661696c6564526f6c6c75702050726f636573736f723a20494e434f52524543545f444154415f53544152545f494e444558526f6c6c75702050726f636573736f723a20544f4b454e5f41535345545f4e4f545f4c494e4b4544526f6c6c75702050726f636573736f723a20494e434f52524543545f524f4f545f524f4f54536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572526f6c6c75702050726f636573736f723a204445504f5349545f54585f4645455f4641494c454476616c69646174655369676e61747572653a20494e56414c49445f5349474e4154555245526f6c6c75702050726f636573736f723a20494e434f52524543545f4e554c4c5f524f4f54526f6c6c75702050726f636573736f723a204d41585f41535345545f52454143484544526f6c6c75702050726f636573736f723a20494e434f52524543545f444154415f524f4f54526f6c6c75702050726f636573736f723a20494e53554646494349454e545f544f4b454e5f415050524f56414c526f6c6c75702050726f636573736f723a20494e53554646494349454e545f4445504f534954526f6c6c75702050726f636573736f723a2057524f4e475f5041594d454e545f54595045a26469706673582212202fd47ddc29f53f6efddfd5689a51af7ae006998ca8597c21d3ffbbc3cd7da41f64736f6c634300060a00334f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573738be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000dcc80db987bf63f01b7bafced6230de5002ef87400000000000000000000000000000000000000000000000000000000000011d000000000000000000000000000000000000000000000000000000000000012c0000000000000000000000000fcf75295f242c4e87203abb5d7c9bbeda90a8895

Deployed Bytecode

0x60806040526004361061027d5760003560e01c806394401d751161014f578063d1d2d95e116100c1578063e5406dbf1161007a578063e5406dbf14610b13578063e70626e614610b28578063edf49c0914610b3d578063ef76e2ee14610b52578063f0e7e29b14610b8d578063f2fde38b14610ba25761027d565b8063d1d2d95e14610a39578063d28bbda514610a6b578063d6ae328414610a95578063d8ba363714610abf578063e059d80714610ad4578063e393635514610ae95761027d565b8063b68ef55911610113578063b68ef55914610852578063be71f8a414610867578063c68dbb3714610897578063c6c62390146108c1578063ccfc2e8d146108eb578063d1c652641461091e5761027d565b806394401d75146107b0578063a009f7e4146107c5578063a3d205f4146107ef578063ae35bfc214610828578063b045009c1461083d5761027d565b80635437988d116101f35780636dff3584116101ac5780636dff3584146106e8578063715018a6146106fd578063781e04321461071257806389404a791461074b5780638da5cb5b1461076057806391dfe78f146107755761027d565b80635437988d146106055780635ad1def3146106385780635c975abb1461067f57806360a8b18a14610694578063626e1ae7146106be57806366535f30146106d35761027d565b806336ce0a921161024557806336ce0a92146104e1578063408ccbdf1461051a57806344c5125214610544578063479b3d951461055957806347a695a71461058b57806349ce468d146105f05761027d565b8063018892ac1461028257806306011a46146102f05780630d43e8ad146104745780632b7ac3f3146104a55780633248295f146104ba575b600080fd5b34801561028e57600080fd5b506102ee60048036036101208110156102a657600080fd5b508035906020810135906001600160a01b03604082013581169160608101359091169060808101359060a08101359060ff60c0820135169060e0810135906101000135610bd5565b005b3480156102fc57600080fd5b506102ee600480360360e081101561031357600080fd5b810190602081018135600160201b81111561032d57600080fd5b82018360208201111561033f57600080fd5b803590602001918460018302840111600160201b8311171561036057600080fd5b919390929091602081019035600160201b81111561037d57600080fd5b82018360208201111561038f57600080fd5b803590602001918460018302840111600160201b831117156103b057600080fd5b919390929091602081019035600160201b8111156103cd57600080fd5b8201836020820111156103df57600080fd5b803590602001918460018302840111600160201b8311171561040057600080fd5b919390929091602081019035600160201b81111561041d57600080fd5b82018360208201111561042f57600080fd5b803590602001918460018302840111600160201b8311171561045057600080fd5b91935091506001600160a01b03813581169160208101359091169060400135610cd8565b34801561048057600080fd5b5061048961106c565b604080516001600160a01b039092168252519081900360200190f35b3480156104b157600080fd5b5061048961107b565b3480156104c657600080fd5b506104cf61108a565b60408051918252519081900360200190f35b3480156104ed57600080fd5b506104cf6004803603604081101561050457600080fd5b50803590602001356001600160a01b0316611090565b34801561052657600080fd5b506104cf6004803603602081101561053d57600080fd5b50356110ad565b34801561055057600080fd5b506104cf6110cb565b34801561056557600080fd5b506102ee6004803603604081101561057c57600080fd5b508035906020013515156110d0565b34801561059757600080fd5b506105a06111ad565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105dc5781810151838201526020016105c4565b505050509050019250505060405180910390f35b3480156105fc57600080fd5b506104cf611205565b34801561061157600080fd5b506102ee6004803603602081101561062857600080fd5b50356001600160a01b031661120b565b34801561064457600080fd5b5061066b6004803603602081101561065b57600080fd5b50356001600160a01b03166112b7565b604080519115158252519081900360200190f35b34801561068b57600080fd5b5061066b6112cc565b3480156106a057600080fd5b50610489600480360360208110156106b757600080fd5b50356112dc565b3480156106ca57600080fd5b506105a0611318565b3480156106df57600080fd5b506104cf61136e565b3480156106f457600080fd5b506104cf611374565b34801561070957600080fd5b506102ee61137a565b34801561071e57600080fd5b5061066b6004803603604081101561073557600080fd5b506001600160a01b038135169060200135611426565b34801561075757600080fd5b506105a0611446565b34801561076c57600080fd5b5061048961149c565b34801561078157600080fd5b506102ee6004803603604081101561079857600080fd5b506001600160a01b03813516906020013515156114ab565b3480156107bc57600080fd5b506104cf61156d565b3480156107d157600080fd5b506104cf600480360360208110156107e857600080fd5b5035611573565b3480156107fb57600080fd5b506104cf6004803603604081101561081257600080fd5b50803590602001356001600160a01b0316611580565b34801561083457600080fd5b506104cf6115aa565b34801561084957600080fd5b506104cf6115af565b34801561085e57600080fd5b506105a06115d3565b34801561087357600080fd5b5061087c611629565b60408051921515835260208301919091528051918290030190f35b3480156108a357600080fd5b50610489600480360360208110156108ba57600080fd5b5035611731565b3480156108cd57600080fd5b506104cf600480360360208110156108e457600080fd5b5035611758565b3480156108f757600080fd5b506102ee6004803603602081101561090e57600080fd5b50356001600160a01b0316611765565b34801561092a57600080fd5b506102ee6004803603606081101561094157600080fd5b810190602081018135600160201b81111561095b57600080fd5b82018360208201111561096d57600080fd5b803590602001918460018302840111600160201b8311171561098e57600080fd5b919390929091602081019035600160201b8111156109ab57600080fd5b8201836020820111156109bd57600080fd5b803590602001918460018302840111600160201b831117156109de57600080fd5b919390929091602081019035600160201b8111156109fb57600080fd5b820183602082011115610a0d57600080fd5b803590602001918460018302840111600160201b83111715610a2e57600080fd5b5090925090506117e9565b6102ee60048036036060811015610a4f57600080fd5b50803590602081013590604001356001600160a01b03166118ff565b348015610a7757600080fd5b5061066b60048036036020811015610a8e57600080fd5b5035611a12565b348015610aa157600080fd5b506104cf60048036036020811015610ab857600080fd5b5035611a40565b348015610acb57600080fd5b506104cf611a4d565b348015610ae057600080fd5b506104cf611a71565b348015610af557600080fd5b506102ee60048036036020811015610b0c57600080fd5b5035611a77565b348015610b1f57600080fd5b506105a0611aea565b348015610b3457600080fd5b506104cf611b4b565b348015610b4957600080fd5b506104cf611b50565b348015610b5e57600080fd5b506102ee60048036036040811015610b7557600080fd5b506001600160a01b0381351690602001351515611b55565b348015610b9957600080fd5b506104cf611db2565b348015610bae57600080fd5b506102ee60048036036020811015610bc557600080fd5b50356001600160a01b0316611db8565b610bdd6112cc565b15610c22576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000610c2d8a6112dc565b6040805163d505accf60e01b81526001600160a01b038b811660048301528a81166024830152604482018a90526064820189905260ff8816608483015260a4820187905260c4820186905291519293509083169163d505accf9160e48082019260009290919082900301818387803b158015610ca857600080fd5b505af1158015610cbc573d6000803e3d6000fd5b50505050610ccc8a828a8c611eba565b50505050505050505050565b610ce06112cc565b15610d25576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b60005a6001600160a01b0385166000908152600b602052604090205490915060ff16610d825760405162461bcd60e51b815260040180806020018281038252602281526020018061302f6022913960400191505060405180910390fd5b60608c8c6000906004600a0160200292610d9e93929190612f69565b600c54604051879187916001600160a01b03909116906020018086868082843780830192505050846001600160a01b03166001600160a01b031660601b8152601401838152602001826001600160a01b03166001600160a01b031660601b8152601401955050505050506040516020818303038152906040529050610e62818051906020012088888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612058915050565b610eea8d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d91506122019050565b610f298d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061222092505050565b600c546000906001600160a01b03165a604080519186036024830152604482018790526001600160a01b03881660648084019190915281518084039091018152608490920181526020820180516001600160e01b03166356aa719960e01b17815290518251909182918083835b60208310610fb55780518252601f199092019160209182019101610f96565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611017576040519150601f19603f3d011682016040523d82523d6000602084013e61101c565b606091505b505090508061105c5760405162461bcd60e51b8152600401808060200182810382526026815260200180612fe66026913960400191505060405180910390fd5b5050505050505050505050505050565b600c546001600160a01b031681565b6006546001600160a01b031681565b60035481565b600960209081526000928352604080842090915290825290205481565b601081815481106110ba57fe5b600091825260209091200154905081565b600e81565b6110d86124ab565b6001600160a01b03166110e961149c565b6001600160a01b031614611132576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600061113d836112dc565b90506001600160a01b0381166111845760405162461bcd60e51b81526004018080602001828103825260288152602001806130a96028913960400191505060405180910390fd5b6001600160a01b03166000908152600860205260409020805460ff191691151591909117905550565b6060600d8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020905b8154815260200190600101908083116111e7575b5050505050905090565b60045481565b6112136124ab565b6001600160a01b031661122461149c565b6001600160a01b03161461126d576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040517fd24015cc99cc1700cafca3042840a1d8ac1e3964fd2e0e37ea29c654056ee32790600090a250565b600b6020526000908152604090205460ff1681565b600054600160a01b900460ff1690565b6000816112eb57506000611313565b600760018303815481106112fb57fe5b6000918252602090912001546001600160a01b031690505b919050565b606060108054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b61018081565b60015481565b6113826124ab565b6001600160a01b031661139361149c565b6001600160a01b0316146113dc576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600a60209081526000928352604080842090915290825290205460ff1681565b6060600f8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b6000546001600160a01b031690565b6114b36124ab565b6001600160a01b03166114c461149c565b6001600160a01b03161461150d576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b0382166000818152600b6020908152604091829020805460ff1916851515908117909155825190815291517f46359ce9dbb6c7f9a375b44072210287916d3de725fc8927a8e762047e4a84249281900390910190a25050565b60025481565b600f81815481106110ba57fe5b60008281526009602090815260408083206001600160a01b03851684529091529020545b92915050565b600c81565b7f00000000000000000000000000000000000000000000000000000000000011d081565b6060600e8054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020908154815260200190600101908083116111e7575050505050905090565b60008043817f00000000000000000000000000000000000000000000000000000000000011d07f00000000000000000000000000000000000000000000000000000000000012c0838161167857fe5b0610801591506000906116d8577f00000000000000000000000000000000000000000000000000000000000012c083816116ae57fe5b067f00000000000000000000000000000000000000000000000000000000000012c0039050611727565b7f00000000000000000000000000000000000000000000000000000000000012c0838161170157fe5b067f00000000000000000000000000000000000000000000000000000000000011d00390505b9093509150509091565b6007818154811061173e57fe5b6000918252602090912001546001600160a01b0316905081565b600e81815481106110ba57fe5b61176d6124ab565b6001600160a01b031661177e61149c565b6001600160a01b0316146117c7576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b6117f16112cc565b15611836576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b6000611840611629565b5090508061187f5760405162461bcd60e51b815260040180806020018281038252602e815260200180612fb8602e913960400191505060405180910390fd5b6118f687878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152508892508791506122019050565b50505050505050565b6119076112cc565b1561194c576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b826119b5578134146119a5576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a2057524f4e475f414d4f554e540000604482015290519081900360640190fd5b6119b08382846124af565b611a0d565b34156119f25760405162461bcd60e51b81526004018080602001828103825260248152602001806132426024913960400191505060405180910390fd5b60006119fd846112dc565b9050611a0b84828486611eba565b505b505050565b600080611a1e836112dc565b6001600160a01b031660009081526008602052604090205460ff169392505050565b600d81815481106110ba57fe5b7f00000000000000000000000000000000000000000000000000000000000012c081565b60055481565b611a7f6112cc565b15611ac4576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b336000908152600a6020908152604080832093835292905220805460ff19166001179055565b606060078054806020026020016040519081016040528092919081815260200182805480156111fb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611b24575050505050905090565b600081565b600481565b611b5d6124ab565b6001600160a01b0316611b6e61149c565b6001600160a01b031614611bb7576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b038216611c12576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a205a45524f5f414444524553530000604482015290519081900360640190fd5b600780546001810182557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319166001600160a01b0385169081179091556000908152600860205260409020805460ff19168315151790555460048110611cb45760405162461bcd60e51b81526004018080602001828103825260238152602001806131a76023913960400191505060405180910390fd5b600d8054600181810190925560007fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5909101819055600e80548084019091557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01819055600f80548084019091557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020181905560108054928301815581527f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6729091018190556040516001600160a01b0385169183917fc53536963369dbfa4c398238ebb9b09fce3943a140928bd25d3052a8a9cacdaf9190a3505050565b6101c081565b611dc06124ab565b6001600160a01b0316611dd161149c565b6001600160a01b031614611e1a576040805162461bcd60e51b81526020600482018190526024820152600080516020613117833981519152604482015290519081900360640190fd5b6001600160a01b038116611e5f5760405162461bcd60e51b8152600401808060200182810382526026815260200180612f926026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60408051636eb1769f60e11b81526001600160a01b038481166004830152306024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b158015611f0b57600080fd5b505afa158015611f1f573d6000803e3d6000fd5b505050506040513d6020811015611f3557600080fd5b5051905081811015611f785760405162461bcd60e51b815260040180806020018281038252602d8152602001806131ef602d913960400191505060405180910390fd5b604080516323b872dd60e01b81526001600160a01b038581166004830152306024830152604482018590529151918616916323b872dd916064808201926020929091908290030181600087803b158015611fd157600080fd5b505af1158015611fe5573d6000803e3d6000fd5b505050506040513d6020811015611ffb57600080fd5b5061200990508584846124af565b604080518681526001600160a01b038516602082015280820184905290517feaa18152488ce5959073c9c79c88ca90b3d96c00de1f118cfaad664c3dab06b99181900360600190a15050505050565b6000806001600160a01b0383166120b6576040805162461bcd60e51b815260206004820152601f60248201527f76616c69646174655369676e61747572653a205a45524f5f4144445245535300604482015290519081900360640190fd5b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005285601c60000152603c60002090506040518551828252606087015160f81c60408801518060608501526020890151604085015281602085015260208460808660015afa601c8314601b84141760418514166fa2a8918ca85bafe22016d0b997e4df5f600160ff1b038310161696505050815183146000811461215d57612162565b825194505b5090528115199290921691826121a95760405162461bcd60e51b815260040180806020018281038252602c815260200180613051602c913960400191505060405180910390fd5b836001600160a01b0316826001600160a01b0316146121f95760405162461bcd60e51b815260040180806020018281038252602481526020018061315e6024913960400191505060405180910390fd5b505050505050565b600061220c85612537565b90506122198582866126a2565b5050505050565b60005b60048110156124a75760006122388383612773565b9050801561249e576000826122a457600c546040516001600160a01b03909116908390600081818185875af1925050503d8060008114612294576040519150601f19603f3d011682016040523d82523d6000602084013e612299565b606091505b50508091505061241d565b60006122af846112dc565b600c546040805163095ea7b360e01b81526001600160a01b0392831660048201526024810187905290519293509083169163095ea7b3916044808201926020929091908290030181600087803b15801561230857600080fd5b505af115801561231c573d6000803e3d6000fd5b505050506040513d602081101561233257600080fd5b5050600c546040805160248101879052604480820187905282518083039091018152606490910182526020810180516001600160e01b0316631c57762b60e31b178152915181516001600160a01b0390941693919290918291908083835b602083106123af5780518252601f199092019160209182019101612390565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612411576040519150601f19603f3d011682016040523d82523d6000602084013e612416565b606091505b5090925050505b806124595760405162461bcd60e51b81526004018080602001828103825260278152602001806131376027913960400191505060405180910390fd5b612483826010858154811061246a57fe5b906000526020600020015461278490919063ffffffff16565b6010848154811061249057fe5b600091825260209091200155505b50600101612223565b5050565b3390565b60008381526009602090815260408083206001600160a01b03861684529091529020546124e2908263ffffffff61278416565b60008481526009602090815260408083206001600160a01b0387168452909152902055600d80546125199183918690811061246a57fe5b600d848154811061252657fe5b600091825260209091200155505050565b60008060008060008060008061254c896127e5565b9650965096509650965096509650600080905060008060008060448e03600654945080519350602081015192506040810151915060ac815360316001820153608c6002820153605d60038201536040600482015289602482015260648f51016000808284895afa9650508381528260208201528160408201525084612618576040805162461bcd60e51b815260206004820152601960248201527f70726f6f6620766572696669636174696f6e206661696c656400000000000000604482015290519081900360640190fd5b60018c815560028c9055612633908b9063ffffffff61278416565b600555600388905560048690556001546002546040805192835260208301919091528181018a905260608201889052518b917ff1034928243e3365c0bf101598066f51439bb2a8763ec84cf7902d8917fb974f919081900360800190a250949c9b505050505050505050505050565b60006101e0808501906101808581028701909101905b818310156118f6578251602084015160408501518215821519821519171680156127625760608701518315612747576101408801518689206001600160a01b0382166000908152600a6020908152604080832084845290915290205460ff16612739578b8b0180516060825261272f838386612a5c565b905260609a909a01995b612744838388612ba4565b50505b82156127605761016088015161275e848284612cb1565b505b505b5050506101809390930192506126b8565b602081028201610140015192915050565b6000828201838110156127de576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b60008060008060008060006127f8612f4b565b60008060008060008061280c8f6004612e25565b96509650965096509650965096508660016004811061282757fe5b60200201511561283b57602087015161283e565b60015b60608801819052600090612853906002612e95565b9050806004548161286057fe5b066128ae576004546040890151146128a95760405162461bcd60e51b815260040180806020018281038252602c81526020018061307d602c913960400191505060405180910390fd5b612915565b600081600454816128bb57fe5b06826004540103905080896002600481106128d257fe5b6020020151146129135760405162461bcd60e51b815260040180806020018281038252602c81526020018061307d602c913960400191505060405180910390fd5b505b60015487146129555760405162461bcd60e51b81526004018080602001828103825260258152602001806131ca6025913960400191505060405180910390fd5b60025485146129955760405162461bcd60e51b81526004018080602001828103825260258152602001806131826025913960400191505060405180910390fd5b60035483146129d55760405162461bcd60e51b81526004018080602001828103825260258152602001806130d16025913960400191505060405180910390fd5b600554885114612a165760405162461bcd60e51b815260040180806020018281038252602381526020018061300c6023913960400191505060405180910390fd5b858489600060200201518a60016020020151858c60036020020151868e60026020020151019e509e509e509e509e509e509e505050505050505050919395979092949650565b6000806001600160a01b038316612aba576040805162461bcd60e51b815260206004820152601f60248201527f76616c69646174655369676e61747572653a205a45524f5f4144445245535300604482015290519081900360640190fd5b60007f19457468657265756d205369676e6564204d6573736167653a0a33320000000060005285601c52603c60002090508451818652606086015160408701518060608901526020880151604089015281602089015260208860808a60015afa601c8314601b84141760608514166fa2a8918ca85bafe22016d0b997e4df5f600160ff1b0383101616955050508551821460008114612b5857612b5d565b865193505b5085528115199290921691826121a95760405162461bcd60e51b815260040180806020018281038252602c815260200180613051602c913960400191505060405180910390fd5b60008381526009602090815260408083206001600160a01b038616845290915290205481811015612c065760405162461bcd60e51b815260040180806020018281038252602681526020018061321c6026913960400191505060405180910390fd5b612c16818363ffffffff612eee16565b60008581526009602090815260408083206001600160a01b0388168452909152902055600d8054612c6691849187908110612c4d57fe5b9060005260206000200154612eee90919063ffffffff16565b600d8581548110612c7357fe5b9060005260206000200181905550612c9282600e868154811061246a57fe5b600e8581548110612c9f57fe5b60009182526020909120015550505050565b6001600160a01b038216612d0c576040805162461bcd60e51b815260206004820152601e60248201527f526f6c6c75702050726f636573736f723a205a45524f5f414444524553530000604482015290519081900360640190fd5b80612d6c576040516001600160a01b038316906175309085906000818181858888f193505050503d8060008114612d5f576040519150601f19603f3d011682016040523d82523d6000602084013e612d64565b606091505b505050612e07565b6000612d77826112dc565b9050806001600160a01b031663a9059cbb84866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015612dd957600080fd5b505af1158015612ded573d6000803e3d6000fd5b505050506040513d6020811015612e0357600080fd5b5050505b612e1883600f838154811061246a57fe5b600f828154811061252657fe5b612e2d612f4b565b5060208281015160408085015160608087015160808089015160a08a015160c08b015160e08c01516101008d01516101208e01519c8c02909d01610140015189519586018a529985529984019690965295820192909252918201949094529692959194909392565b600082612ea4575060006115a4565b82820282848281612eb157fe5b04146127de5760405162461bcd60e51b81526004018080602001828103825260218152602001806130f66021913960400191505060405180910390fd5b600082821115612f45576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60405180608001604052806004906020820280368337509192915050565b60008085851115612f78578182fd5b83861115612f84578182fd5b505082019391909203915056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373526f6c6c75702050726f636573736f723a204553434150455f424c4f434b5f52414e47455f494e434f5252454354526f6c6c75702050726f636573736f723a205245494d42555253455f4741535f4641494c4544526f6c6c75702050726f636573736f723a2049445f4e4f545f53455155454e5449414c526f6c6c75702050726f636573736f723a20554e4b4e4f574e5f50524f564944455276616c69646174655369676e61747572653a207369676e6174757265207265636f76657279206661696c6564526f6c6c75702050726f636573736f723a20494e434f52524543545f444154415f53544152545f494e444558526f6c6c75702050726f636573736f723a20544f4b454e5f41535345545f4e4f545f4c494e4b4544526f6c6c75702050726f636573736f723a20494e434f52524543545f524f4f545f524f4f54536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572526f6c6c75702050726f636573736f723a204445504f5349545f54585f4645455f4641494c454476616c69646174655369676e61747572653a20494e56414c49445f5349474e4154555245526f6c6c75702050726f636573736f723a20494e434f52524543545f4e554c4c5f524f4f54526f6c6c75702050726f636573736f723a204d41585f41535345545f52454143484544526f6c6c75702050726f636573736f723a20494e434f52524543545f444154415f524f4f54526f6c6c75702050726f636573736f723a20494e53554646494349454e545f544f4b454e5f415050524f56414c526f6c6c75702050726f636573736f723a20494e53554646494349454e545f4445504f534954526f6c6c75702050726f636573736f723a2057524f4e475f5041594d454e545f54595045a26469706673582212202fd47ddc29f53f6efddfd5689a51af7ae006998ca8597c21d3ffbbc3cd7da41f64736f6c634300060a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000dcc80db987bf63f01b7bafced6230de5002ef87400000000000000000000000000000000000000000000000000000000000011d000000000000000000000000000000000000000000000000000000000000012c0000000000000000000000000fcf75295f242c4e87203abb5d7c9bbeda90a8895

-----Decoded View---------------
Arg [0] : _verifierAddress (address): 0xDCC80dB987bf63f01b7bafCED6230DE5002eF874
Arg [1] : _escapeBlockLowerBound (uint256): 4560
Arg [2] : _escapeBlockUpperBound (uint256): 4800
Arg [3] : _contractOwner (address): 0xFcF75295f242C4E87203Abb5d7C9BbEda90a8895

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000dcc80db987bf63f01b7bafced6230de5002ef874
Arg [1] : 00000000000000000000000000000000000000000000000000000000000011d0
Arg [2] : 00000000000000000000000000000000000000000000000000000000000012c0
Arg [3] : 000000000000000000000000fcf75295f242c4e87203abb5d7c9bbeda90a8895


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
0x737901bea3eeb88459df9ef1BE8fF3Ae1B42A2ba
Loading...
Loading
[ Download: CSV Export  ]
[ 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.