ETH Price: $3,873.60 (-2.32%)

Contract

0x070cB1270A4B2bA53c81CeF89d0FD584Ed4F430B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Deposit142030112022-02-14 7:46:261029 days ago1644824786IN
OMG Network V1: ERC-20 Vault
0 ETH0.0025305632
Deposit142030022022-02-14 7:44:161029 days ago1644824656IN
OMG Network V1: ERC-20 Vault
0 ETH0.0059025231
Deposit138461352021-12-21 3:27:421084 days ago1640057262IN
OMG Network V1: ERC-20 Vault
0 ETH0.0129466568
Deposit138390852021-12-20 1:27:461085 days ago1639963666IN
OMG Network V1: ERC-20 Vault
0 ETH0.0185868583
Deposit127908522021-07-09 3:47:071249 days ago1625802427IN
OMG Network V1: ERC-20 Vault
0 ETH0.0041444123
Deposit126185432021-06-12 8:13:501276 days ago1623485630IN
OMG Network V1: ERC-20 Vault
0 ETH0.0018956910
Deposit124778182021-05-21 12:56:241297 days ago1621601784IN
OMG Network V1: ERC-20 Vault
0 ETH0.0083410344
Deposit121242302021-03-27 23:49:001352 days ago1616888940IN
OMG Network V1: ERC-20 Vault
0 ETH0.0161505125
Deposit120882972021-03-22 11:15:491357 days ago1616411749IN
OMG Network V1: ERC-20 Vault
0 ETH0.01744868121
Deposit120703702021-03-19 16:45:451360 days ago1616172345IN
OMG Network V1: ERC-20 Vault
0 ETH0.0217748151
Deposit120507312021-03-16 16:30:171363 days ago1615912217IN
OMG Network V1: ERC-20 Vault
0 ETH0.03720153258
Deposit120506622021-03-16 16:15:591363 days ago1615911359IN
OMG Network V1: ERC-20 Vault
0 ETH0.04786947330
Deposit120445272021-03-15 17:30:221364 days ago1615829422IN
OMG Network V1: ERC-20 Vault
0 ETH0.03569315223
Deposit120442262021-03-15 16:28:011364 days ago1615825681IN
OMG Network V1: ERC-20 Vault
0 ETH0.02999193208
Deposit120363192021-03-14 11:08:211365 days ago1615720101IN
OMG Network V1: ERC-20 Vault
0 ETH0.01744868121
Deposit119963672021-03-08 6:58:231372 days ago1615186703IN
OMG Network V1: ERC-20 Vault
0 ETH0.0135540494
Deposit119825782021-03-06 4:06:451374 days ago1615003605IN
OMG Network V1: ERC-20 Vault
0 ETH0.0039437968
Deposit119825782021-03-06 4:06:451374 days ago1615003605IN
OMG Network V1: ERC-20 Vault
0 ETH0.0080106462
Deposit119625342021-03-03 2:09:101377 days ago1614737350IN
OMG Network V1: ERC-20 Vault
0 ETH0.0142761999
Deposit119623562021-03-03 1:25:461377 days ago1614734746IN
OMG Network V1: ERC-20 Vault
0 ETH0.01369816106
Deposit119569062021-03-02 5:25:571378 days ago1614662757IN
OMG Network V1: ERC-20 Vault
0 ETH0.0216625135
Deposit118527142021-02-14 4:45:031394 days ago1613277903IN
OMG Network V1: ERC-20 Vault
0 ETH0.01658208115
Deposit118446312021-02-12 22:37:051395 days ago1613169425IN
OMG Network V1: ERC-20 Vault
0 ETH0.02004268139
Deposit118364932021-02-11 16:59:411396 days ago1613062781IN
OMG Network V1: ERC-20 Vault
0 ETH0.02825928196
Deposit118309942021-02-10 20:45:591397 days ago1612989959IN
OMG Network V1: ERC-20 Vault
0 ETH0.00950757164
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Erc20Vault

Compiler Version
v0.5.11+commit.c082d0b4

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license
File 1 of 20 : Erc20Vault.sol
pragma solidity 0.5.11;

import "./Vault.sol";
import "./verifiers/IErc20DepositVerifier.sol";
import "../framework/PlasmaFramework.sol";

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";

contract Erc20Vault is Vault {
    using SafeERC20 for IERC20;

    event Erc20Withdrawn(
        address indexed receiver,
        address indexed token,
        uint256 amount
    );

    event DepositCreated(
        address indexed depositor,
        uint256 indexed blknum,
        address indexed token,
        uint256 amount
    );

    constructor(PlasmaFramework _framework) public Vault(_framework) {}

    /**
     * @notice Deposits approved amount of ERC20 token(s) into the contract
     * Once the deposit is recognized, the owner (depositor) can transact on the OmiseGO Network
     * The approve function of the ERC20 token contract must be called before calling this function
     * for at least the amount that is deposited into the contract
     * @param depositTx RLP-encoded transaction to act as the deposit
     */
    function deposit(bytes calldata depositTx) external {
        address depositVerifier = super.getEffectiveDepositVerifier();
        require(depositVerifier != address(0), "Deposit verifier has not been set");

        (address depositor, address token, uint256 amount) = IErc20DepositVerifier(depositVerifier)
            .verify(depositTx, msg.sender, address(this));

        IERC20(token).safeTransferFrom(depositor, address(this), amount);

        uint256 blknum = super.submitDepositBlock(depositTx);

        emit DepositCreated(msg.sender, blknum, token, amount);
    }

    /**
    * @notice Withdraw ERC20 tokens that have successfully exited from the OmiseGO Network
    * @param receiver Address of the recipient
    * @param token Address of ERC20 token contract
    * @param amount Amount to transfer
    */
    function withdraw(address payable receiver, address token, uint256 amount) external onlyFromNonQuarantinedExitGame {
        IERC20(token).safeTransfer(receiver, amount);
        emit Erc20Withdrawn(receiver, token, amount);
    }
}

File 2 of 20 : BlockController.sol
pragma solidity 0.5.11;

import "./models/BlockModel.sol";
import "./registries/VaultRegistry.sol";
import "../utils/OnlyFromAddress.sol";

/**
* @notice Controls the logic and functions for block submissions in PlasmaFramework
* @dev There are two types of blocks: child block and deposit block
*      Each child block has an interval of 'childBlockInterval'
*      The interval is preserved for deposits. Each deposit results in one deposit block.
*      For instance, a child block would be in block 1000 and the next deposit would result in block 1001.
*
*      Only the authority address can perform a block submission.
*      Details on limitations for the authority address can be found here: https://github.com/omisego/elixir-omg#managing-the-operator-address
*/
contract BlockController is OnlyFromAddress, VaultRegistry {
    address public authority;
    uint256 public childBlockInterval;
    uint256 public nextChildBlock;
    uint256 public nextDeposit;
    bool public isChildChainActivated;

    mapping (uint256 => BlockModel.Block) public blocks; // block number => Block data

    event BlockSubmitted(
        uint256 blknum
    );

    event ChildChainActivated(
        address authority
    );

    constructor(
        uint256 _interval,
        uint256 _minExitPeriod,
        uint256 _initialImmuneVaults,
        address _authority
    )
        public
        VaultRegistry(_minExitPeriod, _initialImmuneVaults)
    {
        authority = _authority;
        childBlockInterval = _interval;
        nextChildBlock = childBlockInterval;
        nextDeposit = 1;
        isChildChainActivated = false;
    }

    /**
     * @notice Activates the child chain so that child chain can start to submit child blocks to root chain
     * @notice Can only be called once by the authority.
     * @notice Sets isChildChainActivated to true and emits the ChildChainActivated event.
     * @dev This is a preserved action for authority account to start its nonce with 1.
     *      Child chain rely ethereum nonce to protect re-org: https://git.io/JecDG
     *      see discussion: https://git.io/JenaT, https://git.io/JecDO
     */
    function activateChildChain() external onlyFrom(authority) {
        require(isChildChainActivated == false, "Child chain already activated");
        isChildChainActivated = true;
        emit ChildChainActivated(authority);
    }

    /**
     * @notice Allows the authority to submit the Merkle root of a Plasma block
     * @dev emit BlockSubmitted event
     * @dev Block number jumps 'childBlockInterval' per submission
     * @dev See discussion in https://github.com/omisego/plasma-contracts/issues/233
     * @param _blockRoot Merkle root of the Plasma block
     */
    function submitBlock(bytes32 _blockRoot) external onlyFrom(authority) {
        require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
        uint256 submittedBlockNumber = nextChildBlock;

        blocks[submittedBlockNumber] = BlockModel.Block({
            root: _blockRoot,
            timestamp: block.timestamp
        });

        nextChildBlock += childBlockInterval;
        nextDeposit = 1;

        emit BlockSubmitted(submittedBlockNumber);
    }

    /**
     * @notice Submits a block for deposit
     * @dev Block number adds 1 per submission; it's possible to have at most 'childBlockInterval' deposit blocks between two child chain blocks
     * @param _blockRoot Merkle root of the Plasma block
     * @return The deposit block number
     */
    function submitDepositBlock(bytes32 _blockRoot) public onlyFromNonQuarantinedVault returns (uint256) {
        require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
        require(nextDeposit < childBlockInterval, "Exceeded limit of deposits per child block interval");

        uint256 blknum = nextDepositBlock();
        blocks[blknum] = BlockModel.Block({
            root : _blockRoot,
            timestamp : block.timestamp
        });

        nextDeposit++;
        return blknum;
    }

    function nextDepositBlock() public view returns (uint256) {
        return nextChildBlock - childBlockInterval + nextDeposit;
    }

    function isDeposit(uint256 blockNum) public view returns (bool) {
        require(blocks[blockNum].timestamp != 0, "Block does not exist");
        return blockNum % childBlockInterval != 0;
    }
}

File 3 of 20 : ExitGameController.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./interfaces/IExitProcessor.sol";
import "./registries/ExitGameRegistry.sol";
import "./utils/PriorityQueue.sol";
import "./utils/ExitPriority.sol";
import "../utils/PosLib.sol";

/**
 * @notice Controls the logic and functions for ExitGame to interact with the PlasmaFramework
 *         Plasma M(ore)VP relies on exit priority to secure the user from invalid transactions
 *         The priority queue ensures the exit is processed with the exit priority
 *         For details, see the Plasma MVP spec: https://ethresear.ch/t/minimal-viable-plasma/426
 */
contract ExitGameController is ExitGameRegistry {
    // exit hashed (priority, vault id, token) => IExitProcessor
    mapping (bytes32 => IExitProcessor) public delegations;
    // hashed (vault id, token) => PriorityQueue
    mapping (bytes32 => PriorityQueue) public exitsQueues;
    // outputId => exitId
    mapping (bytes32 => uint160) public outputsFinalizations;
    bool private mutex = false;

    event ExitQueueAdded(
        uint256 vaultId,
        address token
    );

    event ProcessedExitsNum(
        uint256 processedNum,
        uint256 vaultId,
        address token
    );

    event ExitQueued(
        uint160 indexed exitId,
        uint256 priority
    );

    constructor(uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
        ExitGameRegistry(_minExitPeriod, _initialImmuneExitGames)
    {
    }

    /**
     * @dev Prevents reentrant calls by using a mutex.
     */
    modifier nonReentrant() {
        require(!mutex, "Reentrant call");
        mutex = true;
        _;
        assert(mutex);
        mutex = false;
    }

    /**
     * @notice Activates non reentrancy mode
     *         Guards against reentering into publicly accessible code that modifies state related to exits
     * @dev Accessible only from non quarantined exit games, uses a mutex
     */
    function activateNonReentrant() external onlyFromNonQuarantinedExitGame() {
        require(!mutex, "Reentrant call");
        mutex = true;
    }

    /**
     * @notice Deactivates non reentrancy mode
     * @dev Accessible only from non quarantined exit games, uses a mutex
     */
    function deactivateNonReentrant() external onlyFromNonQuarantinedExitGame() {
        assert(mutex);
        mutex = false;
    }

    /**
     * @notice Checks if the queue for a specified token was created
     * @param vaultId ID of the vault that handles the token
     * @param token Address of the token
     * @return bool Defines whether the queue for a token was created
     */
    function hasExitQueue(uint256 vaultId, address token) public view returns (bool) {
        bytes32 key = exitQueueKey(vaultId, token);
        return hasExitQueue(key);
    }

    /**
     * @notice Adds queue to the Plasma framework
     * @dev The queue is created as a new contract instance
     * @param vaultId ID of the vault
     * @param token Address of the token
     */
    function addExitQueue(uint256 vaultId, address token) external {
        require(vaultId != 0, "Vault ID must not be 0");
        bytes32 key = exitQueueKey(vaultId, token);
        require(!hasExitQueue(key), "Exit queue exists");
        exitsQueues[key] = new PriorityQueue();
        emit ExitQueueAdded(vaultId, token);
    }

    /**
     * @notice Enqueue exits from exit game contracts is a function that places the exit into the
     *         priority queue to enforce the priority of exit during 'processExits'
     * @dev emits ExitQueued event, which can be used to back trace the priority inside the queue
     * @dev Caller of this function should add "pragma experimental ABIEncoderV2;" on top of file
     * @dev Priority (exitableAt, txPos, exitId) must be unique per queue. Do not enqueue when the same priority is already in the queue.
     * @param vaultId Vault ID of the vault that stores exiting funds
     * @param token Token for the exit
     * @param exitableAt The earliest time a specified exit can be processed
     * @param txPos Transaction position for the exit priority. For SE it should be the exit tx, for IFE it should be the youngest input tx position.
     * @param exitId ID used by the exit processor contract to determine how to process the exit
     * @param exitProcessor The exit processor contract, called during "processExits"
     * @return A unique priority number computed for the exit
     */
    function enqueue(
        uint256 vaultId,
        address token,
        uint64 exitableAt,
        PosLib.Position calldata txPos,
        uint160 exitId,
        IExitProcessor exitProcessor
    )
        external
        onlyFromNonQuarantinedExitGame
        returns (uint256)
    {
        bytes32 key = exitQueueKey(vaultId, token);
        require(hasExitQueue(key), "The queue for the (vaultId, token) pair is not yet added to the Plasma framework");
        PriorityQueue queue = exitsQueues[key];

        uint256 priority = ExitPriority.computePriority(exitableAt, txPos, exitId);

        queue.insert(priority);

        bytes32 delegationKey = getDelegationKey(priority, vaultId, token);
        require(address(delegations[delegationKey]) == address(0), "The same priority is already enqueued");
        delegations[delegationKey] = exitProcessor;

        emit ExitQueued(exitId, priority);
        return priority;
    }

    /**
     * @notice Processes any exits that have completed the challenge period. Exits are processed according to the exit priority.
     * @dev Emits ProcessedExitsNum event
     * @param vaultId Vault ID of the vault that stores exiting funds
     * @param token The token type to process
     * @param topExitId Unique identifier for prioritizing the first exit to process. Set to zero to skip this check.
     * @param maxExitsToProcess Maximum number of exits to process
     * @return Total number of processed exits
     */
    function processExits(uint256 vaultId, address token, uint160 topExitId, uint256 maxExitsToProcess) external nonReentrant {
        bytes32 key = exitQueueKey(vaultId, token);
        require(hasExitQueue(key), "The token is not yet added to the Plasma framework");
        PriorityQueue queue = exitsQueues[key];
        require(queue.currentSize() > 0, "Exit queue is empty");

        uint256 uniquePriority = queue.getMin();
        uint160 exitId = ExitPriority.parseExitId(uniquePriority);
        require(topExitId == 0 || exitId == topExitId,
            "Top exit ID of the queue is different to the one specified");

        bytes32 delegationKey = getDelegationKey(uniquePriority, vaultId, token);
        IExitProcessor processor = delegations[delegationKey];
        uint256 processedNum = 0;

        while (processedNum < maxExitsToProcess && ExitPriority.parseExitableAt(uniquePriority) < block.timestamp) {
            delete delegations[delegationKey];
            queue.delMin();
            processedNum++;

            processor.processExit(exitId, vaultId, token);

            if (queue.currentSize() == 0) {
                break;
            }

            uniquePriority = queue.getMin();
            delegationKey = getDelegationKey(uniquePriority, vaultId, token);
            exitId = ExitPriority.parseExitId(uniquePriority);
            processor = delegations[delegationKey];
        }

        emit ProcessedExitsNum(processedNum, vaultId, token);
    }

    /**
     * @notice Checks whether any of the output with the given outputIds is already spent
     * @param _outputIds Output IDs to check
     */
    function isAnyInputFinalizedByOtherExit(bytes32[] calldata _outputIds, uint160 exitId) external view returns (bool) {
        for (uint i = 0; i < _outputIds.length; i++) {
            uint160 finalizedExitId = outputsFinalizations[_outputIds[i]];
            if (finalizedExitId != 0 && finalizedExitId != exitId) {
                return true;
            }
        }
        return false;
    }

    /**
     * @notice Batch flags already spent outputs (only not already spent)
     * @param outputIds Output IDs to flag
     */
    function batchFlagOutputsFinalized(bytes32[] calldata outputIds, uint160 exitId) external onlyFromNonQuarantinedExitGame {
        for (uint i = 0; i < outputIds.length; i++) {
            require(outputIds[i] != bytes32(""), "Should not flag with empty outputId");
            if (outputsFinalizations[outputIds[i]] == 0) {
                outputsFinalizations[outputIds[i]] = exitId;
            }
        }
    }

    /**
     * @notice Flags a single output as spent if it is not flagged already
     * @param outputId The output ID to flag as spent
     */
    function flagOutputFinalized(bytes32 outputId, uint160 exitId) external onlyFromNonQuarantinedExitGame {
        require(outputId != bytes32(""), "Should not flag with empty outputId");
        if (outputsFinalizations[outputId] == 0) {
            outputsFinalizations[outputId] = exitId;
        }
    }

     /**
     * @notice Checks whether output with a given outputId is finalized
     * @param outputId Output ID to check
     */
    function isOutputFinalized(bytes32 outputId) external view returns (bool) {
        return outputsFinalizations[outputId] != 0;
    }

    function getNextExit(uint256 vaultId, address token) external view returns (uint256) {
        bytes32 key = exitQueueKey(vaultId, token);
        return exitsQueues[key].getMin();
    }

    function exitQueueKey(uint256 vaultId, address token) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(vaultId, token));
    }

    function hasExitQueue(bytes32 queueKey) private view returns (bool) {
        return address(exitsQueues[queueKey]) != address(0);
    }

    function getDelegationKey(uint256 priority, uint256 vaultId, address token) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(priority, vaultId, token));
    }
}

File 4 of 20 : PlasmaFramework.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./BlockController.sol";
import "./ExitGameController.sol";
import "./registries/VaultRegistry.sol";
import "./registries/ExitGameRegistry.sol";

contract PlasmaFramework is VaultRegistry, ExitGameRegistry, ExitGameController, BlockController {
    uint256 public constant CHILD_BLOCK_INTERVAL = 1000;

    /**
     * The minimum finalization period is the Plasma guarantee that all exits are safe provided the user takes action within the specified time period
     * When the child chain is rogue, user should start their exit and challenge any invalid exit within this period
     * An exit can be processed/finalized after minimum two finalization periods from its inclusion position, unless it is an exit for a deposit,
     * which would use one finalization period, instead of two
     *
     * For the Abstract Layer Design, OmiseGO also uses some multitude of this period to update its framework
     * See also ExitGameRegistry.sol, VaultRegistry.sol, and Vault.sol for more information on the update waiting time (the quarantined period)
     *
     * MVP: https://ethresear.ch/t/minimal-viable-plasma/426
     * MoreVP: https://github.com/omisego/elixir-omg/blob/master/docs/morevp.md#timeline
     * Special period for deposit: https://git.io/JecCV
     */
    uint256 public minExitPeriod;
    address private maintainer;
    string public version;

    constructor(
        uint256 _minExitPeriod,
        uint256 _initialImmuneVaults,
        uint256 _initialImmuneExitGames,
        address _authority,
        address _maintainer
    )
        public
        BlockController(CHILD_BLOCK_INTERVAL, _minExitPeriod, _initialImmuneVaults, _authority)
        ExitGameController(_minExitPeriod, _initialImmuneExitGames)
    {
        minExitPeriod = _minExitPeriod;
        maintainer = _maintainer;
    }

    function getMaintainer() public view returns (address) {
        return maintainer;
    }

    /**
     * @notice Gets the semantic version of the current deployed contracts
    */
    function getVersion() external view returns (string memory) {
        return version;
    }
    
    /**
     * @notice Sets the semantic version of the current deployed contracts
     * @param _version is semver string
     */
    function setVersion(string memory _version) public onlyFrom(getMaintainer()) {
        version = _version;
    }
}

File 5 of 20 : Protocol.sol
pragma solidity 0.5.11;

/**
 * @notice Protocols for the PlasmaFramework
 */
library Protocol {
    uint8 constant internal MVP_VALUE = 1;
    uint8 constant internal MORE_VP_VALUE = 2;

    // solhint-disable-next-line func-name-mixedcase
    function MVP() internal pure returns (uint8) {
        return MVP_VALUE;
    }

    // solhint-disable-next-line func-name-mixedcase
    function MORE_VP() internal pure returns (uint8) {
        return MORE_VP_VALUE;
    }

    function isValidProtocol(uint8 protocol) internal pure returns (bool) {
        return protocol == MVP_VALUE || protocol == MORE_VP_VALUE;
    }
}

File 6 of 20 : IExitProcessor.sol
pragma solidity 0.5.11;

/**
 * @dev An interface that allows custom logic to process exits for different requirements.
 *      This interface is used to dispatch to each custom processor when 'processExits' is called on PlasmaFramework.
 */
interface IExitProcessor {
    /**
     * @dev Function interface for processing exits.
     * @param exitId Unique ID for exit per tx type
     * @param vaultId ID of the vault that funds the exit
     * @param token Address of the token contract
     */
    function processExit(uint160 exitId, uint256 vaultId, address token) external;
}

File 7 of 20 : BlockModel.sol
pragma solidity 0.5.11;

library BlockModel {
    /**
     * @notice Block data structure that is stored in the contract
     * @param root The Merkle root block hash of the Plasma blocks
     * @param timestamp The timestamp, in seconds, when the block is saved
     */
    struct Block {
        bytes32 root;
        uint256 timestamp;
    }
}

File 8 of 20 : ExitGameRegistry.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/utils/Address.sol";

import "../Protocol.sol";
import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";

contract ExitGameRegistry is OnlyFromAddress {
    using Quarantine for Quarantine.Data;

    mapping(uint256 => address) private _exitGames; // txType => exit game contract address
    mapping(address => uint256) private _exitGameToTxType; // exit game contract address => tx type
    mapping(uint256 => uint8) private _protocols; // tx type => protocol (MVP/MORE_VP)
    Quarantine.Data private _exitGameQuarantine;

    event ExitGameRegistered(
        uint256 txType,
        address exitGameAddress,
        uint8 protocol
    );

    /**
     * @dev It takes at least 3 * minExitPeriod before each new exit game contract is able to start protecting existing transactions
     *      see: https://github.com/omisego/plasma-contracts/issues/172
     *           https://github.com/omisego/plasma-contracts/issues/197
     */
    constructor (uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
    {
        _exitGameQuarantine.quarantinePeriod = 4 * _minExitPeriod;
        _exitGameQuarantine.immunitiesRemaining = _initialImmuneExitGames;
    }

    /**
     * @notice A modifier to verify that the call is from a non-quarantined exit game
     */
    modifier onlyFromNonQuarantinedExitGame() {
        require(_exitGameToTxType[msg.sender] != 0, "The call is not from a registered exit game contract");
        require(!_exitGameQuarantine.isQuarantined(msg.sender), "ExitGame is quarantined");
        _;
    }

    /**
     * @notice interface to get the 'maintainer' address.
     * @dev see discussion here: https://git.io/Je8is
     */
    function getMaintainer() public view returns (address);

    /**
     * @notice Checks whether the contract is safe to use and is not under quarantine
     * @dev Exposes information about exit games quarantine
     * @param _contract Address of the exit game contract
     * @return boolean Whether the contract is safe to use and is not under quarantine
     */
    function isExitGameSafeToUse(address _contract) public view returns (bool) {
        return _exitGameToTxType[_contract] != 0 && !_exitGameQuarantine.isQuarantined(_contract);
    }

    /**
     * @notice Registers an exit game within the PlasmaFramework. Only the maintainer can call the function.
     * @dev Emits ExitGameRegistered event to notify clients
     * @param _txType The tx type where the exit game wants to register
     * @param _contract Address of the exit game contract
     * @param _protocol The transaction protocol, either 1 for MVP or 2 for MoreVP
     */
    function registerExitGame(uint256 _txType, address _contract, uint8 _protocol) public onlyFrom(getMaintainer()) {
        require(_txType != 0, "Should not register with tx type 0");
        require(Address.isContract(_contract), "Should not register with a non-contract address");
        require(_exitGames[_txType] == address(0), "The tx type is already registered");
        require(_exitGameToTxType[_contract] == 0, "The exit game contract is already registered");
        require(Protocol.isValidProtocol(_protocol), "Invalid protocol value");

        _exitGames[_txType] = _contract;
        _exitGameToTxType[_contract] = _txType;
        _protocols[_txType] = _protocol;
        _exitGameQuarantine.quarantine(_contract);

        emit ExitGameRegistered(_txType, _contract, _protocol);
    }

    /**
     * @notice Public getter for retrieving protocol with tx type
     */
    function protocols(uint256 _txType) public view returns (uint8) {
        return _protocols[_txType];
    }

    /**
     * @notice Public getter for retrieving exit game address with tx type
     */
    function exitGames(uint256 _txType) public view returns (address) {
        return _exitGames[_txType];
    }

    /**
     * @notice Public getter for retrieving tx type with exit game address
     */
    function exitGameToTxType(address _exitGame) public view returns (uint256) {
        return _exitGameToTxType[_exitGame];
    }
}

File 9 of 20 : VaultRegistry.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/utils/Address.sol";

import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";

contract VaultRegistry is OnlyFromAddress {
    using Quarantine for Quarantine.Data;

    mapping(uint256 => address) private _vaults; // vault id => vault address
    mapping(address => uint256) private _vaultToId; // vault address => vault id
    Quarantine.Data private _vaultQuarantine;

    event VaultRegistered(
        uint256 vaultId,
        address vaultAddress
    );

    /**
     * @dev It takes at least 2 minExitPeriod for each new vault contract to start.
     *      This is to protect deposit transactions already in mempool,
     *      and also make sure user only needs to SE within first week when invalid vault is registered.
     *      see: https://github.com/omisego/plasma-contracts/issues/412
     *           https://github.com/omisego/plasma-contracts/issues/173
     */
    constructor(uint256 _minExitPeriod, uint256 _initialImmuneVaults)
        public
    {
        _vaultQuarantine.quarantinePeriod = 2 * _minExitPeriod;
        _vaultQuarantine.immunitiesRemaining = _initialImmuneVaults;
    }

    /**
     * @notice interface to get the 'maintainer' address.
     * @dev see discussion here: https://git.io/Je8is
     */
    function getMaintainer() public view returns (address);

    /**
     * @notice A modifier to check that the call is from a non-quarantined vault
     */
    modifier onlyFromNonQuarantinedVault() {
        require(_vaultToId[msg.sender] > 0, "The call is not from a registered vault");
        require(!_vaultQuarantine.isQuarantined(msg.sender), "Vault is quarantined");
        _;
    }

    /**
     * @notice Register a vault within the PlasmaFramework. Only a maintainer can make the call.
     * @dev emits VaultRegistered event to notify clients
     * @param _vaultId The ID for the vault contract to register
     * @param _vaultAddress Address of the vault contract
     */
    function registerVault(uint256 _vaultId, address _vaultAddress) public onlyFrom(getMaintainer()) {
        require(_vaultId != 0, "Should not register with vault ID 0");
        require(Address.isContract(_vaultAddress), "Should not register with a non-contract address");
        require(_vaults[_vaultId] == address(0), "The vault ID is already registered");
        require(_vaultToId[_vaultAddress] == 0, "The vault contract is already registered");

        _vaults[_vaultId] = _vaultAddress;
        _vaultToId[_vaultAddress] = _vaultId;
        _vaultQuarantine.quarantine(_vaultAddress);

        emit VaultRegistered(_vaultId, _vaultAddress);
    }

    /**
     * @notice Public getter for retrieving vault address with vault ID
     */
    function vaults(uint256 _vaultId) public view returns (address) {
        return _vaults[_vaultId];
    }

    /**
     * @notice Public getter for retrieving vault ID with vault address
     */
    function vaultToId(address _vaultAddress) public view returns (uint256) {
        return _vaultToId[_vaultAddress];
    }
}

File 10 of 20 : ExitPriority.sol
pragma solidity 0.5.11;

import "../../utils/PosLib.sol";

library ExitPriority {

    using PosLib for PosLib.Position;

    /**
     * @dev Returns an exit priority for a given UTXO position and a unique ID.
     * The priority for Plasma M(ore)VP protocol is a combination of 'exitableAt' and 'txPos'.
     * Since 'exitableAt' only provides granularity of block, add 'txPos' to provide priority for a transaction.
     * @notice Detailed explanation on field lengths can be found at https://github.com/omisego/plasma-contracts/pull/303#discussion_r328850572
     * @param exitId Unique exit identifier
     * @return An exit priority
     *   Anatomy of returned value, most significant bits first
     *   42 bits  - timestamp in seconds (exitable_at); we can represent dates until year 141431
     *   54 bits  - blocknum * 10^5 + txindex; 54 bits represent all transactions for 85 years. Be aware that child chain block number jumps with the interval of CHILD_BLOCK_INTERVAL, which would be 1000 in production.
     *   160 bits - exit id
     */
    function computePriority(uint64 exitableAt, PosLib.Position memory txPos, uint160 exitId)
        internal
        pure
        returns (uint256)
    {
        return (uint256(exitableAt) << 214) | (txPos.getTxPositionForExitPriority() << 160) | uint256(exitId);
    }

    function parseExitableAt(uint256 priority) internal pure returns (uint64) {
        return uint64(priority >> 214);
    }

    function parseExitId(uint256 priority) internal pure returns (uint160) {
        // Exit ID uses only 160 least significant bits
        return uint160(priority);
    }
}

File 11 of 20 : PriorityQueue.sol
pragma solidity 0.5.11;

import "../../utils/OnlyFromAddress.sol";

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @title PriorityQueue
 * @dev Min-heap priority queue implementation
 */
contract PriorityQueue is OnlyFromAddress {
    using SafeMath for uint256;

    struct Queue {
        uint256[] heapList;
        uint256 currentSize;
    }

    Queue public queue;
    address public framework;

    constructor() public {
        queue.heapList = [0];
        queue.currentSize = 0;

        // it is expected that this should be called by PlasmaFramework
        // and only PlasmaFramework contract can add things to the queue
        framework = msg.sender;
    }

    /**
     * @notice Gets num of elements in the queue
     */
    function currentSize() external view returns (uint256) {
        return queue.currentSize;
    }

    /**
     * @notice Gets all elements in the queue
     */
    function heapList() external view returns (uint256[] memory) {
        return queue.heapList;
    }

    /**
     * @notice Inserts an element into the queue by the framework
     * @dev Does not perform deduplication
     */
    function insert(uint256 _element) external onlyFrom(framework) {
        queue.heapList.push(_element);
        queue.currentSize = queue.currentSize.add(1);
        percUp(queue, queue.currentSize);
    }

    /**
     * @notice Deletes the smallest element from the queue by the framework
     * @dev Fails when queue is empty
     * @return The smallest element in the priority queue
     */
    function delMin() external onlyFrom(framework) returns (uint256) {
        require(queue.currentSize > 0, "Queue is empty");
        uint256 retVal = queue.heapList[1];
        queue.heapList[1] = queue.heapList[queue.currentSize];
        delete queue.heapList[queue.currentSize];
        queue.currentSize = queue.currentSize.sub(1);
        percDown(queue, 1);
        queue.heapList.length = queue.heapList.length.sub(1);
        return retVal;
    }

    /**
     * @notice Returns the smallest element from the queue
     * @dev Fails when queue is empty
     * @return The smallest element in the priority queue
     */
    function getMin() external view returns (uint256) {
        require(queue.currentSize > 0, "Queue is empty");
        return queue.heapList[1];
    }

    function percUp(Queue storage self, uint256 pointer) private {
        uint256 i = pointer;
        uint256 j = i;
        uint256 newVal = self.heapList[i];
        while (newVal < self.heapList[i.div(2)]) {
            self.heapList[i] = self.heapList[i.div(2)];
            i = i.div(2);
        }
        if (i != j) {
            self.heapList[i] = newVal;
        }
    }

    function percDown(Queue storage self, uint256 pointer) private {
        uint256 i = pointer;
        uint256 j = i;
        uint256 newVal = self.heapList[i];
        uint256 mc = minChild(self, i);
        while (mc <= self.currentSize && newVal > self.heapList[mc]) {
            self.heapList[i] = self.heapList[mc];
            i = mc;
            mc = minChild(self, i);
        }
        if (i != j) {
            self.heapList[i] = newVal;
        }
    }

    function minChild(Queue storage self, uint256 i) private view returns (uint256) {
        if (i.mul(2).add(1) > self.currentSize) {
            return i.mul(2);
        } else {
            if (self.heapList[i.mul(2)] < self.heapList[i.mul(2).add(1)]) {
                return i.mul(2);
            } else {
                return i.mul(2).add(1);
            }
        }
    }
}

File 12 of 20 : Quarantine.sol
pragma solidity 0.5.11;

/**
 * @notice Provides a way to quarantine (disable) contracts for a specified period of time
 * @dev The immunitiesRemaining member allows deployment to the platform with some
 * pre-verified contracts that don't get quarantined
 */
library Quarantine {
    struct Data {
        mapping(address => uint256) store;
        uint256 quarantinePeriod;
        uint256 immunitiesRemaining;
    }

    /**
     * @notice Checks whether a contract is quarantined
     */
    function isQuarantined(Data storage _self, address _contractAddress) internal view returns (bool) {
        return block.timestamp < _self.store[_contractAddress];
    }

    /**
     * @notice Places a contract into quarantine
     * @param _contractAddress The address of the contract
     */
    function quarantine(Data storage _self, address _contractAddress) internal {
        require(_contractAddress != address(0), "An empty address cannot be quarantined");
        require(_self.store[_contractAddress] == 0, "The contract is already quarantined");

        if (_self.immunitiesRemaining == 0) {
            _self.store[_contractAddress] = block.timestamp + _self.quarantinePeriod;
        } else {
            _self.immunitiesRemaining--;
        }
    }
}

File 13 of 20 : OnlyFromAddress.sol
pragma solidity 0.5.11;

contract OnlyFromAddress {

    modifier onlyFrom(address caller) {
        require(msg.sender == caller, "Caller address is unauthorized");
        _;
    }
}

File 14 of 20 : PosLib.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @dev UTXO position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET + outputIndex).
 * TX position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET)
 */
library PosLib {
    struct Position {
        uint64 blockNum;
        uint16 txIndex;
        uint16 outputIndex;
    }

    uint256 constant internal BLOCK_OFFSET = 1000000000;
    uint256 constant internal TX_OFFSET = 10000;
    
    uint256 constant internal MAX_OUTPUT_INDEX = TX_OFFSET - 1;
    // since we are using merkle tree of depth 16, max tx index size is 2^16 - 1
    uint256 constant internal MAX_TX_INDEX = 2 ** 16 - 1;
    // in ExitPriority, only 54 bits are reserved for both blockNum and txIndex
    uint256 constant internal MAX_BLOCK_NUM = ((2 ** 54 - 1) - MAX_TX_INDEX) / (BLOCK_OFFSET / TX_OFFSET);

    /**
     * @notice Returns transaction position which is an utxo position of zero index output
     * @param pos UTXO position of the output
     * @return Position of a transaction
     */
    function toStrictTxPos(Position memory pos)
        internal
        pure
        returns (Position memory)
    {
        return Position(pos.blockNum, pos.txIndex, 0);
    }

    /**
     * @notice Used for calculating exit priority
     * @param pos UTXO position for the output
     * @return Identifier of the transaction
     */
    function getTxPositionForExitPriority(Position memory pos)
        internal
        pure
        returns (uint256)
    {
        return encode(pos) / TX_OFFSET;
    }

    /**
     * @notice Encodes a position
     * @param pos Position
     * @return Position encoded as an integer
     */
    function encode(Position memory pos) internal pure returns (uint256) {
        require(pos.outputIndex <= MAX_OUTPUT_INDEX, "Invalid output index");
        require(pos.blockNum <= MAX_BLOCK_NUM, "Invalid block number");

        return pos.blockNum * BLOCK_OFFSET + pos.txIndex * TX_OFFSET + pos.outputIndex;
    }

    /**
     * @notice Decodes a position from an integer value
     * @param pos Encoded position
     * @return Position
     */
    function decode(uint256 pos) internal pure returns (Position memory) {
        uint256 blockNum = pos / BLOCK_OFFSET;
        uint256 txIndex = (pos % BLOCK_OFFSET) / TX_OFFSET;
        uint16 outputIndex = uint16(pos % TX_OFFSET);

        require(blockNum <= MAX_BLOCK_NUM, "blockNum exceeds max size allowed in PlasmaFramework");
        require(txIndex <= MAX_TX_INDEX, "txIndex exceeds the size of uint16");
        return Position(uint64(blockNum), uint16(txIndex), outputIndex);
    }
}

File 15 of 20 : Vault.sol
pragma solidity 0.5.11;

import "../framework/PlasmaFramework.sol";
import "../utils/OnlyFromAddress.sol";

/**
 * @notice Base contract for vault implementation
 * @dev This is the functionality to swap "deposit verifier"
 *      Setting a new deposit verifier allows an upgrade to a new deposit tx type without upgrading the vault
 */
contract Vault is OnlyFromAddress {

    byte private constant LEAF_SALT = 0x00;
    byte private constant NODE_SALT = 0x01;

    event SetDepositVerifierCalled(address nextDepositVerifier);
    PlasmaFramework internal framework;
    bytes32[16] internal zeroHashes; // Pre-computes zero hashes to be used for building merkle tree for deposit block

    /**
     * @notice Stores deposit verifier contract addresses; first contract address is effective until the
     *  `newDepositVerifierMaturityTimestamp`; second contract address becomes effective after that timestamp
    */
    address[2] public depositVerifiers;
    uint256 public newDepositVerifierMaturityTimestamp = 2 ** 255; // point far in the future

    constructor(PlasmaFramework _framework) public {
        framework = _framework;
        zeroHashes = getZeroHashes();
    }

    /**
     * @dev Pre-computes zero hashes to be used for building Merkle tree for deposit block
     */
    function getZeroHashes() private pure returns (bytes32[16] memory) {
        bytes32[16] memory hashes;
        bytes32 zeroHash = keccak256(abi.encodePacked(LEAF_SALT, uint256(0)));
        for (uint i = 0; i < 16; i++) {
            hashes[i] = zeroHash;
            zeroHash = keccak256(abi.encodePacked(NODE_SALT, zeroHash, zeroHash));
        }
        return hashes;
    }

    /**
     * @notice Checks whether the call originates from a non-quarantined exit game contract
    */
    modifier onlyFromNonQuarantinedExitGame() {
        require(
            ExitGameRegistry(framework).isExitGameSafeToUse(msg.sender),
            "Called from a non-registered or quarantined exit game contract"
        );
        _;
    }

    /**
     * @notice Sets the deposit verifier contract, which may be called only by the operator
     * @dev emit SetDepositVerifierCalled
     * @dev When one contract is already set, the next one is effective after 2 * MIN_EXIT_PERIOD.
     *      This is to protect deposit transactions already in mempool,
     *      and also make sure user only needs to SE within first week when invalid vault is registered.
     *
     *      see: https://github.com/omisego/plasma-contracts/issues/412
     *           https://github.com/omisego/plasma-contracts/issues/173
     *
     * @param _verifier Address of the verifier contract
     */
    function setDepositVerifier(address _verifier) public onlyFrom(framework.getMaintainer()) {
        require(_verifier != address(0), "Cannot set an empty address as deposit verifier");

        if (depositVerifiers[0] != address(0)) {
            depositVerifiers[0] = getEffectiveDepositVerifier();
            depositVerifiers[1] = _verifier;
            newDepositVerifierMaturityTimestamp = now + 2 * framework.minExitPeriod();
        } else {
            depositVerifiers[0] = _verifier;
        }

        emit SetDepositVerifierCalled(_verifier);
    }

    /**
     * @notice Retrieves the currently effective deposit verifier contract address
     * @return Contract address of the deposit verifier
     */
    function getEffectiveDepositVerifier() public view returns (address) {
        if (now < newDepositVerifierMaturityTimestamp) {
            return depositVerifiers[0];
        } else {
            return depositVerifiers[1];
        }
    }

    /**
     * @notice Generate and submit a deposit block root to the PlasmaFramework
     * @dev Designed to be called by the contract that inherits Vault
     */
    function submitDepositBlock(bytes memory depositTx) internal returns (uint256) {
        bytes32 root = getDepositBlockRoot(depositTx);

        uint256 depositBlkNum = framework.submitDepositBlock(root);
        return depositBlkNum;
    }

    function getDepositBlockRoot(bytes memory depositTx) private view returns (bytes32) {
        bytes32 root = keccak256(abi.encodePacked(LEAF_SALT, depositTx));
        for (uint i = 0; i < 16; i++) {
            root = keccak256(abi.encodePacked(NODE_SALT, root, zeroHashes[i]));
        }
        return root;
    }
}

File 16 of 20 : IErc20DepositVerifier.sol
pragma solidity 0.5.11;

interface IErc20DepositVerifier {
    /**
     * @notice Verifies a deposit transaction
     * @param depositTx The deposit transaction
     * @param sender The owner of the deposit transaction
     * @param vault The address of the Erc20Vault contract
     * @return Verified (owner, token, amount) of the deposit ERC20 token data
     */
    function verify(bytes calldata depositTx, address sender, address vault)
        external
        view
        returns (address owner, address token, uint256 amount);
}

File 17 of 20 : SafeMath.sol
pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

File 18 of 20 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through `transferFrom`. This is
     * zero by default.
     *
     * This value changes when `approve` or `transferFrom` are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * > 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);
}

File 19 of 20 : SafeERC20.sol
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 20 of 20 : Address.sol
pragma solidity ^0.5.0;

/**
 * @dev Collection of functions related to the address type,
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing a contract.
     *
     * > It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }
}

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

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositVerifiers","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"setDepositVerifier","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEffectiveDepositVerifier","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"depositTx","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"newDepositVerifierMaturityTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract PlasmaFramework","name":"_framework","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Erc20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"uint256","name":"blknum","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nextDepositVerifier","type":"address"}],"name":"SetDepositVerifierCalled","type":"event"}]

60806040527f800000000000000000000000000000000000000000000000000000000000000060135534801561003457600080fd5b5060405162000dc638038062000dc68339818101604052602081101561005957600080fd5b5051600080546001600160a01b0319166001600160a01b0383161790558061007f610095565b61008d90600190601061015b565b5050506101d2565b61009d610199565b6100a5610199565b6040805160006020808301829052602180840183905284518085039091018152604190930190935281519190920120905b601081101561015257818382601081106100ec57fe5b60209081029190910191909152604080517f010000000000000000000000000000000000000000000000000000000000000081840152602181018590526041808201959095528151808203909501855260610190528251920191909120906001016100d6565b50909150505b90565b8260108101928215610189579160200282015b8281111561018957825182559160200191906001019061016e565b506101959291506101b8565b5090565b6040518061020001604052806010906020820280388339509192915050565b61015891905b8082111561019557600081556001016101be565b610be480620001e26000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806302e9b07b146100675780632c6ce78b146100a057806352518b7f146100c857806398b1e06a146100d0578063a7e5994f14610140578063d9caed121461015a575b600080fd5b6100846004803603602081101561007d57600080fd5b5035610190565b604080516001600160a01b039092168252519081900360200190f35b6100c6600480360360208110156100b657600080fd5b50356001600160a01b03166101ad565b005b6100846103df565b6100c6600480360360208110156100e657600080fd5b81019060208101813564010000000081111561010157600080fd5b82018360208201111561011357600080fd5b8035906020019184600183028401116401000000008311171561013557600080fd5b50909250905061040e565b6101486105d7565b60408051918252519081900360200190f35b6100c66004803603606081101561017057600080fd5b506001600160a01b038135811691602081013590911690604001356105dd565b6011816002811061019d57fe5b01546001600160a01b0316905081565b6000809054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101fa57600080fd5b505afa15801561020e573d6000803e3d6000fd5b505050506040513d602081101561022457600080fd5b5051336001600160a01b03821614610283576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206164647265737320697320756e617574686f72697a65640000604482015290519081900360640190fd5b6001600160a01b0382166102c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610af8602f913960400191505060405180910390fd5b6011546001600160a01b031615610383576102e16103df565b601180546001600160a01b03199081166001600160a01b0393841617909155601280549091168483161790556000546040805163d4a2b4ef60e01b81529051919092169163d4a2b4ef916004808301926020929190829003018186803b15801561034a57600080fd5b505afa15801561035e573d6000803e3d6000fd5b505050506040513d602081101561037457600080fd5b5051600202420160135561039f565b601180546001600160a01b0319166001600160a01b0384161790555b604080516001600160a01b038416815290517f11e5a7570e0de4b31179f8c9cf5e8a1e6cfd23731ec7a5a06e3006d71dd321fd9181900360200190a15050565b600060135442101561040257601160005b01546001600160a01b0316905061040b565b601160016103f0565b90565b60006104186103df565b90506001600160a01b03811661045f5760405162461bcd60e51b8152600401808060200182810382526021815260200180610b276021913960400191505060405180910390fd5b604051635970e69f60e11b81523360248201819052306044830181905260606004840190815260648401869052600093849384936001600160a01b0388169363b2e1cd3e938b938b93909290918190608401868680828437600081840152601f19601f8201169050808301925050509550505050505060606040518083038186803b1580156104ed57600080fd5b505afa158015610501573d6000803e3d6000fd5b505050506040513d606081101561051757600080fd5b508051602082015160409092015190945090925090506105486001600160a01b03831684308463ffffffff6106f916565b600061058987878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061075992505050565b6040805184815290519192506001600160a01b03851691839133917f18569122d84f30025bb8dffb33563f1bdbfb9637f21552b11b8305686e9cb3079181900360200190a450505050505050565b60135481565b60005460408051632d0816d760e11b815233600482015290516001600160a01b0390921691635a102dae91602480820192602092909190829003018186803b15801561062857600080fd5b505afa15801561063c573d6000803e3d6000fd5b505050506040513d602081101561065257600080fd5b505161068f5760405162461bcd60e51b815260040180806020018281038252603e815260200180610b72603e913960400191505060405180910390fd5b6106a96001600160a01b038316848363ffffffff6107eb16565b816001600160a01b0316836001600160a01b03167fcd43b20ab5058a2a0a057681c9d3754aa8971fe74dacc8b6e4be0a49dae13101836040518082815260200191505060405180910390a3505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610753908590610842565b50505050565b600080610765836109fa565b60008054604080516317cb58d360e31b815260048101859052905193945091926001600160a01b039091169163be5ac69891602480830192602092919082900301818787803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d60208110156107e157600080fd5b5051949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261083d908490610842565b505050565b610854826001600160a01b0316610af1565b6108a5576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108e35780518252601f1990920191602091820191016108c4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610945576040519150601f19603f3d011682016040523d82523d6000602084013e61094a565b606091505b5091509150816109a1576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610753578080602001905160208110156109bd57600080fd5b50516107535760405162461bcd60e51b815260040180806020018281038252602a815260200180610b48602a913960400191505060405180910390fd5b60405160006020808301828152845192938493849387939260210191908401908083835b60208310610a3d5780518252601f199092019160209182019101610a1e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905060008090505b6010811015610aea57600160f81b8260018360108110610a9d57fe5b0154604080516001600160f81b0319909416602080860191909152602185019390935260418085019290925280518085039092018252606190930190925281519101209150600101610a81565b5092915050565b3b15159056fe43616e6e6f742073657420616e20656d7074792061646472657373206173206465706f7369742076657269666965724465706f73697420766572696669657220686173206e6f74206265656e207365745361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616c6c65642066726f6d2061206e6f6e2d72656769737465726564206f722071756172616e74696e656420657869742067616d6520636f6e7472616374a265627a7a72315820bd0d5bf30eb9c4359cd401c04e15380f4c2f6631d91a7548a31fa1ef85d18a5d64736f6c634300050b00320000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100625760003560e01c806302e9b07b146100675780632c6ce78b146100a057806352518b7f146100c857806398b1e06a146100d0578063a7e5994f14610140578063d9caed121461015a575b600080fd5b6100846004803603602081101561007d57600080fd5b5035610190565b604080516001600160a01b039092168252519081900360200190f35b6100c6600480360360208110156100b657600080fd5b50356001600160a01b03166101ad565b005b6100846103df565b6100c6600480360360208110156100e657600080fd5b81019060208101813564010000000081111561010157600080fd5b82018360208201111561011357600080fd5b8035906020019184600183028401116401000000008311171561013557600080fd5b50909250905061040e565b6101486105d7565b60408051918252519081900360200190f35b6100c66004803603606081101561017057600080fd5b506001600160a01b038135811691602081013590911690604001356105dd565b6011816002811061019d57fe5b01546001600160a01b0316905081565b6000809054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101fa57600080fd5b505afa15801561020e573d6000803e3d6000fd5b505050506040513d602081101561022457600080fd5b5051336001600160a01b03821614610283576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206164647265737320697320756e617574686f72697a65640000604482015290519081900360640190fd5b6001600160a01b0382166102c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610af8602f913960400191505060405180910390fd5b6011546001600160a01b031615610383576102e16103df565b601180546001600160a01b03199081166001600160a01b0393841617909155601280549091168483161790556000546040805163d4a2b4ef60e01b81529051919092169163d4a2b4ef916004808301926020929190829003018186803b15801561034a57600080fd5b505afa15801561035e573d6000803e3d6000fd5b505050506040513d602081101561037457600080fd5b5051600202420160135561039f565b601180546001600160a01b0319166001600160a01b0384161790555b604080516001600160a01b038416815290517f11e5a7570e0de4b31179f8c9cf5e8a1e6cfd23731ec7a5a06e3006d71dd321fd9181900360200190a15050565b600060135442101561040257601160005b01546001600160a01b0316905061040b565b601160016103f0565b90565b60006104186103df565b90506001600160a01b03811661045f5760405162461bcd60e51b8152600401808060200182810382526021815260200180610b276021913960400191505060405180910390fd5b604051635970e69f60e11b81523360248201819052306044830181905260606004840190815260648401869052600093849384936001600160a01b0388169363b2e1cd3e938b938b93909290918190608401868680828437600081840152601f19601f8201169050808301925050509550505050505060606040518083038186803b1580156104ed57600080fd5b505afa158015610501573d6000803e3d6000fd5b505050506040513d606081101561051757600080fd5b508051602082015160409092015190945090925090506105486001600160a01b03831684308463ffffffff6106f916565b600061058987878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061075992505050565b6040805184815290519192506001600160a01b03851691839133917f18569122d84f30025bb8dffb33563f1bdbfb9637f21552b11b8305686e9cb3079181900360200190a450505050505050565b60135481565b60005460408051632d0816d760e11b815233600482015290516001600160a01b0390921691635a102dae91602480820192602092909190829003018186803b15801561062857600080fd5b505afa15801561063c573d6000803e3d6000fd5b505050506040513d602081101561065257600080fd5b505161068f5760405162461bcd60e51b815260040180806020018281038252603e815260200180610b72603e913960400191505060405180910390fd5b6106a96001600160a01b038316848363ffffffff6107eb16565b816001600160a01b0316836001600160a01b03167fcd43b20ab5058a2a0a057681c9d3754aa8971fe74dacc8b6e4be0a49dae13101836040518082815260200191505060405180910390a3505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610753908590610842565b50505050565b600080610765836109fa565b60008054604080516317cb58d360e31b815260048101859052905193945091926001600160a01b039091169163be5ac69891602480830192602092919082900301818787803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d60208110156107e157600080fd5b5051949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261083d908490610842565b505050565b610854826001600160a01b0316610af1565b6108a5576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108e35780518252601f1990920191602091820191016108c4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610945576040519150601f19603f3d011682016040523d82523d6000602084013e61094a565b606091505b5091509150816109a1576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610753578080602001905160208110156109bd57600080fd5b50516107535760405162461bcd60e51b815260040180806020018281038252602a815260200180610b48602a913960400191505060405180910390fd5b60405160006020808301828152845192938493849387939260210191908401908083835b60208310610a3d5780518252601f199092019160209182019101610a1e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905060008090505b6010811015610aea57600160f81b8260018360108110610a9d57fe5b0154604080516001600160f81b0319909416602080860191909152602185019390935260418085019290925280518085039092018252606190930190925281519101209150600101610a81565b5092915050565b3b15159056fe43616e6e6f742073657420616e20656d7074792061646472657373206173206465706f7369742076657269666965724465706f73697420766572696669657220686173206e6f74206265656e207365745361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616c6c65642066726f6d2061206e6f6e2d72656769737465726564206f722071756172616e74696e656420657869742067616d6520636f6e7472616374a265627a7a72315820bd0d5bf30eb9c4359cd401c04e15380f4c2f6631d91a7548a31fa1ef85d18a5d64736f6c634300050b0032

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

0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac

-----Decoded View---------------
Arg [0] : _framework (address): 0x0D4C1222f5e839a911e2053860e45F18921D72ac

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac


Deployed Bytecode Sourcemap

273:1903:13:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;273:1903:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;922:34:14;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;922:34:14;;:::i;:::-;;;;-1:-1:-1;;;;;922:34:14;;;;;;;;;;;;;;2670:560;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2670:560:14;-1:-1:-1;;;;;2670:560:14;;:::i;:::-;;3391:240;;;:::i;1117:578:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1117:578:13;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;1117:578:13;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;1117:578:13;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;1117:578:13;;-1:-1:-1;1117:578:13;-1:-1:-1;1117:578:13;:::i;962:61:14:-;;;:::i;:::-;;;;;;;;;;;;;;;;1944:230:13;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;1944:230:13;;;;;;;;;;;;;;;;;:::i;922:34:14:-;;;;;;;;;;;;-1:-1:-1;;;;;922:34:14;;-1:-1:-1;922:34:14;:::o;2670:560::-;2733:9;;;;;;;;;-1:-1:-1;;;;;2733:9:14;-1:-1:-1;;;;;2733:23:14;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2733:25:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2733:25:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2733:25:14;109:10:11;-1:-1:-1;;;;;109:20:11;;;101:63;;;;;-1:-1:-1;;;101:63:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2778:23:14;;2770:83;;;;-1:-1:-1;;;2770:83:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2868:16;:19;-1:-1:-1;;;;;2868:19:14;:33;2864:309;;2939:29;:27;:29::i;:::-;2917:16;:51;;-1:-1:-1;;;;;;2917:51:14;;;-1:-1:-1;;;;;2917:51:14;;;;;;;2982:19;:31;;;;;;;;;;;-1:-1:-1;3075:9:14;:25;;;-1:-1:-1;;;3075:25:14;;;;:9;;;;;:23;;:25;;;;;;;;;;;;;;:9;:25;;;5:2:-1;;;;30:1;27;20:12;5:2;3075:25:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3075:25:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3075:25:14;3071:1;:29;3065:3;:35;3027;:73;2864:309;;;3131:16;:31;;-1:-1:-1;;;;;;3131:31:14;-1:-1:-1;;;;;3131:31:14;;;;;2864:309;3188:35;;;-1:-1:-1;;;;;3188:35:14;;;;;;;;;;;;;;;2670:560;;:::o;3391:240::-;3451:7;3480:35;;3474:3;:41;3470:155;;;3538:16;3555:1;3538:19;;;-1:-1:-1;;;;;3538:19:14;;-1:-1:-1;3531:26:14;;3470:155;3595:16;3612:1;3595:19;;3470:155;3391:240;:::o;1117:578:13:-;1179:23;1205:35;:33;:35::i;:::-;1179:61;-1:-1:-1;;;;;;1258:29:13;;1250:75;;;;-1:-1:-1;;;1250:75:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1389:96;;-1:-1:-1;;;1389:96:13;;1459:10;1389:96;;;;;;1479:4;1389:96;;;;;;;;;;;;;;;;;;;1337:17;;;;;;-1:-1:-1;;;;;1389:58:13;;;;;1448:9;;;;1459:10;;1479:4;;1389:96;;;;1448:9;;;;1389:96;1:33:-1;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;1389:96:13;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1389:96:13;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1389:96:13;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1389:96:13;;;;;;;;;;;;;-1:-1:-1;1389:96:13;;-1:-1:-1;1389:96:13;-1:-1:-1;1496:64:13;-1:-1:-1;;;;;1496:30:13;;1389:96;1546:4;1389:96;1496:64;:30;:64;:::i;:::-;1571:14;1588:35;1613:9;;1588:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;1588:24:13;;-1:-1:-1;;;1588:35:13:i;:::-;1639:49;;;;;;;;1571:52;;-1:-1:-1;;;;;;1639:49:13;;;1571:52;;1654:10;;1639:49;;;;;;;;;1117:578;;;;;;;:::o;962:61:14:-;;;;:::o;1944:230:13:-;1875:9:14;;1858:59;;;-1:-1:-1;;;1858:59:14;;1906:10;1858:59;;;;;;-1:-1:-1;;;;;1875:9:14;;;;1858:47;;:59;;;;;;;;;;;;;;;1875:9;1858:59;;;5:2:-1;;;;30:1;27;20:12;5:2;1858:59:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1858:59:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1858:59:14;1837:168;;;;-1:-1:-1;;;1837:168:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2069:44:13;-1:-1:-1;;;;;2069:26:13;;2096:8;2106:6;2069:44;:26;:44;:::i;:::-;2153:5;-1:-1:-1;;;;;2128:39:13;2143:8;-1:-1:-1;;;;;2128:39:13;;2160:6;2128:39;;;;;;;;;;;;;;;;;;1944:230;;;:::o;842:202:18:-;968:68;;;-1:-1:-1;;;;;968:68:18;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;968:68:18;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;942:95:18;;961:5;;942:18;:95::i;:::-;842:202;;;;:::o;3802:240:14:-;3872:7;3891:12;3906:30;3926:9;3906:19;:30::i;:::-;3947:21;3971:9;;:34;;;-1:-1:-1;;;3971:34:14;;;;;;;;;;3891:45;;-1:-1:-1;3947:21:14;;-1:-1:-1;;;;;3971:9:14;;;;:28;;:34;;;;;;;;;;;;;;3947:21;3971:9;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;3971:34:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3971:34:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3971:34:14;;3802:240;-1:-1:-1;;;;3802:240:14:o;662:174:18:-;770:58;;;-1:-1:-1;;;;;770:58:18;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;770:58:18;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;744:85:18;;763:5;;744:18;:85::i;:::-;662:174;;;:::o;2621:1095::-;3216:27;3224:5;-1:-1:-1;;;;;3216:25:18;;:27::i;:::-;3208:71;;;;;-1:-1:-1;;;3208:71:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;3350:12;3364:23;3399:5;-1:-1:-1;;;;;3391:19:18;3411:4;3391:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;3391:25:18;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;3349:67:18;;;;3434:7;3426:52;;;;;-1:-1:-1;;;3426:52:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3493:17;;:21;3489:221;;3633:10;3622:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3622:30:18;3614:85;;;;-1:-1:-1;;;3614:85:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4048:316:14;4167:38;;4123:7;4167:38;;;;;;;;;4123:7;;;;;;4195:9;;4167:38;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;4167:38:14;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4167:38:14;;;4157:49;;;;;;4142:64;;4221:6;4230:1;4221:10;;4216:121;4237:2;4233:1;:6;4216:121;;;-1:-1:-1;;;4305:4:14;456;4322:1;4311:13;;;;;;;;;4277:48;;;-1:-1:-1;;;;;;4277:48:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;4277:48:14;;;;;;;4267:59;;;;;;-1:-1:-1;4277:48:14;4241:3;4216:121;;;-1:-1:-1;4353:4:14;4048:316;-1:-1:-1;;4048:316:14:o;542:413:19:-;902:20;940:8;;;542:413::o

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

The vault containing ERC-20 deposited into the OMG Network.

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
ETH58.90%$18,341.4829$8,349.82
ETH13.34%$0.5310733,561.9712$1,891.67
ETH13.27%$98,1650.0192$1,880.8
ETH3.04%$0.03918311,000$431.01
ETH2.95%$92,9470.0045$418.26
ETH2.34%$0.0066350,000$331.51
ETH2.01%$284.841$284.84
ETH1.64%$1232.3158$232.55
ETH0.69%$0.980981100$98.1
ETH0.37%$153$53.16
ETH0.23%$2,797.660.0115$32.03
ETH0.21%$0.70127642$29.45
ETH0.18%$1.0325$25.65
ETH0.13%$0.18638898.7$18.4
ETH0.12%$25.240.7$17.67
ETH0.12%$0.30757855$16.92
ETH0.09%$0.64475120$12.9
ETH0.07%$0.28052335$9.82
ETH0.06%$19.11$9.12
ETH0.06%$0.00025530,576.8$7.81
ETH0.05%$0.11918760$7.15
ETH0.04%$0.024359235.3619$5.73
ETH0.03%$0.8908924.19$3.73
ETH0.03%$0.000023161,694.7709$3.69
ETH0.01%$0.7642052.7$2.06
ETH0.01%$3.570.5$1.79
ETH<0.01%$0.00091,000$0.90
ETH<0.01%$0.2509932$0.5019
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.