ETH Price: $3,307.18 (-5.22%)

Contract

0x9921810C710E7c3f7A7C6831e30929f19537a545
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Retrieve Rewards109155112020-09-23 0:23:161579 days ago1600820596IN
0x9921810C...19537a545
0 ETH0.0104281272
Retrieve Rewards109154822020-09-23 0:18:591579 days ago1600820339IN
0x9921810C...19537a545
0 ETH0.0069134173.5
Retrieve Rewards109154492020-09-23 0:12:011579 days ago1600819921IN
0x9921810C...19537a545
0 ETH0.00975772102
Retrieve Rewards109154472020-09-23 0:11:461579 days ago1600819906IN
0x9921810C...19537a545
0 ETH0.0218013100
Retrieve Rewards109154392020-09-23 0:09:401579 days ago1600819780IN
0x9921810C...19537a545
0 ETH0.0097967271
Retrieve Rewards109154042020-09-23 0:01:521579 days ago1600819312IN
0x9921810C...19537a545
0 ETH0.0105819672.51
Batch Reveal109151232020-09-22 23:03:171579 days ago1600815797IN
0x9921810C...19537a545
0 ETH0.01325218113
Batch Reveal109148842020-09-22 22:08:201579 days ago1600812500IN
0x9921810C...19537a545
0 ETH0.01332936110
Batch Reveal109141472020-09-22 19:22:421579 days ago1600802562IN
0x9921810C...19537a545
0 ETH0.01348674115
Batch Reveal109135432020-09-22 17:10:591579 days ago1600794659IN
0x9921810C...19537a545
0 ETH0.02666642220.02
Batch Reveal109134772020-09-22 16:55:161579 days ago1600793716IN
0x9921810C...19537a545
0 ETH0.031512260
Batch Reveal109126422020-09-22 13:43:161579 days ago1600782196IN
0x9921810C...19537a545
0 ETH0.0094993581
Batch Reveal109121412020-09-22 11:53:221579 days ago1600775602IN
0x9921810C...19537a545
0 ETH0.01539025123
Batch Reveal109119672020-09-22 11:15:001579 days ago1600773300IN
0x9921810C...19537a545
0 ETH0.01476463118
Batch Reveal109106712020-09-22 6:21:411579 days ago1600755701IN
0x9921810C...19537a545
0 ETH0.0106355485
Batch Reveal109101442020-09-22 4:30:061579 days ago1600749006IN
0x9921810C...19537a545
0 ETH0.00751033105
Batch Reveal109101382020-09-22 4:29:211579 days ago1600748961IN
0x9921810C...19537a545
0 ETH0.00751033105
Batch Reveal109099402020-09-22 3:42:251579 days ago1600746145IN
0x9921810C...19537a545
0 ETH0.0103252185.2
Batch Reveal109098882020-09-22 3:31:151579 days ago1600745475IN
0x9921810C...19537a545
0 ETH0.0156405125
Batch Reveal109093632020-09-22 1:38:261579 days ago1600738706IN
0x9921810C...19537a545
0 ETH0.011998899
Batch Reveal109092672020-09-22 1:13:041579 days ago1600737184IN
0x9921810C...19537a545
0 ETH0.0123872799
Batch Reveal109092572020-09-22 1:11:121579 days ago1600737072IN
0x9921810C...19537a545
0 ETH0.012011996
Batch Reveal109092272020-09-22 1:01:321579 days ago1600736492IN
0x9921810C...19537a545
0 ETH0.0112584996
Batch Reveal109091412020-09-22 0:43:011579 days ago1600735381IN
0x9921810C...19537a545
0 ETH0.0099332784.7
Batch Reveal109091392020-09-22 0:42:161579 days ago1600735336IN
0x9921810C...19537a545
0 ETH0.0117552397
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:
Voting

Compiler Version
v0.6.6+commit.6c089d02

Optimization Enabled:
Yes with 500 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity Multiple files format)

File 1 of 117: Voting.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./FixedPoint.sol";
import "./Testable.sol";
import "./FinderInterface.sol";
import "./OracleInterface.sol";
import "./VotingInterface.sol";
import "./IdentifierWhitelistInterface.sol";
import "./Registry.sol";
import "./ResultComputation.sol";
import "./VoteTiming.sol";
import "./VotingToken.sol";
import "./Constants.sol";

import "./Ownable.sol";
import "./SafeMath.sol";


/**
 * @title Voting system for Oracle.
 * @dev Handles receiving and resolving price requests via a commit-reveal voting scheme.
 */
contract Voting is Testable, Ownable, OracleInterface, VotingInterface {
    using FixedPoint for FixedPoint.Unsigned;
    using SafeMath for uint256;
    using VoteTiming for VoteTiming.Data;
    using ResultComputation for ResultComputation.Data;

    /****************************************
     *        VOTING DATA STRUCTURES        *
     ****************************************/

    // Identifies a unique price request for which the Oracle will always return the same value.
    // Tracks ongoing votes as well as the result of the vote.
    struct PriceRequest {
        bytes32 identifier;
        uint256 time;
        // A map containing all votes for this price in various rounds.
        mapping(uint256 => VoteInstance) voteInstances;
        // If in the past, this was the voting round where this price was resolved. If current or the upcoming round,
        // this is the voting round where this price will be voted on, but not necessarily resolved.
        uint256 lastVotingRound;
        // The index in the `pendingPriceRequests` that references this PriceRequest. A value of UINT_MAX means that
        // this PriceRequest is resolved and has been cleaned up from `pendingPriceRequests`.
        uint256 index;
    }

    struct VoteInstance {
        // Maps (voterAddress) to their submission.
        mapping(address => VoteSubmission) voteSubmissions;
        // The data structure containing the computed voting results.
        ResultComputation.Data resultComputation;
    }

    struct VoteSubmission {
        // A bytes32 of `0` indicates no commit or a commit that was already revealed.
        bytes32 commit;
        // The hash of the value that was revealed.
        // Note: this is only used for computation of rewards.
        bytes32 revealHash;
    }

    struct Round {
        uint256 snapshotId; // Voting token snapshot ID for this round.  0 if no snapshot has been taken.
        FixedPoint.Unsigned inflationRate; // Inflation rate set for this round.
        FixedPoint.Unsigned gatPercentage; // Gat rate set for this round.
        uint256 rewardsExpirationTime; // Time that rewards for this round can be claimed until.
    }

    // Represents the status a price request has.
    enum RequestStatus {
        NotRequested, // Was never requested.
        Active, // Is being voted on in the current round.
        Resolved, // Was resolved in a previous round.
        Future // Is scheduled to be voted on in a future round.
    }

    // Only used as a return value in view methods -- never stored in the contract.
    struct RequestState {
        RequestStatus status;
        uint256 lastVotingRound;
    }

    /****************************************
     *          INTERNAL TRACKING           *
     ****************************************/

    // Maps round numbers to the rounds.
    mapping(uint256 => Round) public rounds;

    // Maps price request IDs to the PriceRequest struct.
    mapping(bytes32 => PriceRequest) private priceRequests;

    // Price request ids for price requests that haven't yet been marked as resolved.
    // These requests may be for future rounds.
    bytes32[] internal pendingPriceRequests;

    VoteTiming.Data public voteTiming;

    // Percentage of the total token supply that must be used in a vote to
    // create a valid price resolution. 1 == 100%.
    FixedPoint.Unsigned public gatPercentage;

    // Global setting for the rate of inflation per vote. This is the percentage of the snapshotted total supply that
    // should be split among the correct voters.
    // Note: this value is used to set per-round inflation at the beginning of each round. 1 = 100%.
    FixedPoint.Unsigned public inflationRate;

    // Time in seconds from the end of the round in which a price request is
    // resolved that voters can still claim their rewards.
    uint256 public rewardsExpirationTimeout;

    // Reference to the voting token.
    VotingToken public votingToken;

    // Reference to the Finder.
    FinderInterface private finder;

    // If non-zero, this contract has been migrated to this address. All voters and
    // financial contracts should query the new address only.
    address public migratedAddress;

    // Max value of an unsigned integer.
    uint256 private constant UINT_MAX = ~uint256(0);

    /***************************************
     *                EVENTS                *
     ****************************************/

    event VoteCommitted(address indexed voter, uint256 indexed roundId, bytes32 indexed identifier, uint256 time);

    event EncryptedVote(
        address indexed voter,
        uint256 indexed roundId,
        bytes32 indexed identifier,
        uint256 time,
        bytes encryptedVote
    );

    event VoteRevealed(
        address indexed voter,
        uint256 indexed roundId,
        bytes32 indexed identifier,
        uint256 time,
        int256 price,
        uint256 numTokens
    );

    event RewardsRetrieved(
        address indexed voter,
        uint256 indexed roundId,
        bytes32 indexed identifier,
        uint256 time,
        uint256 numTokens
    );

    event PriceRequestAdded(uint256 indexed roundId, bytes32 indexed identifier, uint256 time);

    event PriceResolved(uint256 indexed roundId, bytes32 indexed identifier, uint256 time, int256 price);

    /**
     * @notice Construct the Voting contract.
     * @param _phaseLength length of the commit and reveal phases in seconds.
     * @param _gatPercentage of the total token supply that must be used in a vote to create a valid price resolution.
     * @param _inflationRate percentage inflation per round used to increase token supply of correct voters.
     * @param _rewardsExpirationTimeout timeout, in seconds, within which rewards must be claimed.
     * @param _votingToken address of the UMA token contract used to commit votes.
     * @param _finder keeps track of all contracts within the system based on their interfaceName.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        uint256 _phaseLength,
        FixedPoint.Unsigned memory _gatPercentage,
        FixedPoint.Unsigned memory _inflationRate,
        uint256 _rewardsExpirationTimeout,
        address _votingToken,
        address _finder,
        address _timerAddress
    ) public Testable(_timerAddress) {
        voteTiming.init(_phaseLength);
        require(_gatPercentage.isLessThanOrEqual(1), "GAT percentage must be <= 100%");
        gatPercentage = _gatPercentage;
        inflationRate = _inflationRate;
        votingToken = VotingToken(_votingToken);
        finder = FinderInterface(_finder);
        rewardsExpirationTimeout = _rewardsExpirationTimeout;
    }

    /***************************************
                    MODIFIERS
    ****************************************/

    modifier onlyRegisteredContract() {
        if (migratedAddress != address(0)) {
            require(msg.sender == migratedAddress, "Caller must be migrated address");
        } else {
            Registry registry = Registry(finder.getImplementationAddress(OracleInterfaces.Registry));
            require(registry.isContractRegistered(msg.sender), "Called must be registered");
        }
        _;
    }

    modifier onlyIfNotMigrated() {
        require(migratedAddress == address(0), "Only call this if not migrated");
        _;
    }

    /****************************************
     *  PRICE REQUEST AND ACCESS FUNCTIONS  *
     ****************************************/

    /**
     * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     */
    function requestPrice(bytes32 identifier, uint256 time) external override onlyRegisteredContract() {
        uint256 blockTime = getCurrentTime();
        require(time <= blockTime, "Can only request in past");
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier), "Unsupported identifier request");

        bytes32 priceRequestId = _encodePriceRequest(identifier, time);
        PriceRequest storage priceRequest = priceRequests[priceRequestId];
        uint256 currentRoundId = voteTiming.computeCurrentRoundId(blockTime);

        RequestStatus requestStatus = _getRequestStatus(priceRequest, currentRoundId);

        if (requestStatus == RequestStatus.NotRequested) {
            // Price has never been requested.
            // Price requests always go in the next round, so add 1 to the computed current round.
            uint256 nextRoundId = currentRoundId.add(1);

            priceRequests[priceRequestId] = PriceRequest({
                identifier: identifier,
                time: time,
                lastVotingRound: nextRoundId,
                index: pendingPriceRequests.length
            });
            pendingPriceRequests.push(priceRequestId);
            emit PriceRequestAdded(nextRoundId, identifier, time);
        }
    }

    /**
     * @notice Whether the price for `identifier` and `time` is available.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp of for the price request.
     * @return _hasPrice bool if the DVM has resolved to a price for the given identifier and timestamp.
     */
    function hasPrice(bytes32 identifier, uint256 time) external override view onlyRegisteredContract() returns (bool) {
        (bool _hasPrice, , ) = _getPriceOrError(identifier, time);
        return _hasPrice;
    }

    /**
     * @notice Gets the price for `identifier` and `time` if it has already been requested and resolved.
     * @dev If the price is not available, the method reverts.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp of for the price request.
     * @return int256 representing the resolved price for the given identifier and timestamp.
     */
    function getPrice(bytes32 identifier, uint256 time)
        external
        override
        view
        onlyRegisteredContract()
        returns (int256)
    {
        (bool _hasPrice, int256 price, string memory message) = _getPriceOrError(identifier, time);

        // If the price wasn't available, revert with the provided message.
        require(_hasPrice, message);
        return price;
    }

    /**
     * @notice Gets the status of a list of price requests, identified by their identifier and time.
     * @dev If the status for a particular request is NotRequested, the lastVotingRound will always be 0.
     * @param requests array of type PendingRequest which includes an identifier and timestamp for each request.
     * @return requestStates a list, in the same order as the input list, giving the status of each of the specified price requests.
     */
    function getPriceRequestStatuses(PendingRequest[] memory requests) public view returns (RequestState[] memory) {
        RequestState[] memory requestStates = new RequestState[](requests.length);
        uint256 currentRoundId = voteTiming.computeCurrentRoundId(getCurrentTime());
        for (uint256 i = 0; i < requests.length; i++) {
            PriceRequest storage priceRequest = _getPriceRequest(requests[i].identifier, requests[i].time);

            RequestStatus status = _getRequestStatus(priceRequest, currentRoundId);

            // If it's an active request, its true lastVotingRound is the current one, even if it hasn't been updated.
            if (status == RequestStatus.Active) {
                requestStates[i].lastVotingRound = currentRoundId;
            } else {
                requestStates[i].lastVotingRound = priceRequest.lastVotingRound;
            }
            requestStates[i].status = status;
        }
        return requestStates;
    }

    /****************************************
     *            VOTING FUNCTIONS          *
     ****************************************/

    /**
     * @notice Commit a vote for a price request for `identifier` at `time`.
     * @dev `identifier`, `time` must correspond to a price request that's currently in the commit phase.
     * Commits can be changed.
     * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s expected behavior,
     * voters should never reuse salts. If someone else is able to guess the voted price and knows that a salt will be reused, then
     * they can determine the vote pre-reveal.
     * @param identifier uniquely identifies the committed vote. EG BTC/USD price pair.
     * @param time unix timestamp of the price being voted on.
     * @param hash keccak256 hash of the `price`, `salt`, voter `address`, `time`, current `roundId`, and `identifier`.
     */
    function commitVote(
        bytes32 identifier,
        uint256 time,
        bytes32 hash
    ) public override onlyIfNotMigrated() {
        require(hash != bytes32(0), "Invalid provided hash");
        // Current time is required for all vote timing queries.
        uint256 blockTime = getCurrentTime();
        require(voteTiming.computeCurrentPhase(blockTime) == Phase.Commit, "Cannot commit in reveal phase");

        // At this point, the computed and last updated round ID should be equal.
        uint256 currentRoundId = voteTiming.computeCurrentRoundId(blockTime);

        PriceRequest storage priceRequest = _getPriceRequest(identifier, time);
        require(
            _getRequestStatus(priceRequest, currentRoundId) == RequestStatus.Active,
            "Cannot commit inactive request"
        );

        priceRequest.lastVotingRound = currentRoundId;
        VoteInstance storage voteInstance = priceRequest.voteInstances[currentRoundId];
        voteInstance.voteSubmissions[msg.sender].commit = hash;

        emit VoteCommitted(msg.sender, currentRoundId, identifier, time);
    }

    /**
     * @notice Snapshot the current round's token balances and lock in the inflation rate and GAT.
     * @dev This function can be called multiple times, but only the first call per round into this function or `revealVote`
     * will create the round snapshot. Any later calls will be a no-op. Will revert unless called during reveal period.
     */
    function snapshotCurrentRound() external override onlyIfNotMigrated() {
        uint256 blockTime = getCurrentTime();
        require(voteTiming.computeCurrentPhase(blockTime) == Phase.Reveal, "Only snapshot in reveal phase");

        uint256 roundId = voteTiming.computeCurrentRoundId(blockTime);
        _freezeRoundVariables(roundId);
    }

    /**
     * @notice Reveal a previously committed vote for `identifier` at `time`.
     * @dev The revealed `price`, `salt`, `time`, `address`, `roundId`, and `identifier`, must hash to the latest `hash`
     * that `commitVote()` was called with. Only the committer can reveal their vote.
     * @param identifier voted on in the commit phase. EG BTC/USD price pair.
     * @param time specifies the unix timestamp of the price being voted on.
     * @param price voted on during the commit phase.
     * @param salt value used to hide the commitment price during the commit phase.
     */
    function revealVote(
        bytes32 identifier,
        uint256 time,
        int256 price,
        int256 salt
    ) public override onlyIfNotMigrated() {
        uint256 blockTime = getCurrentTime();
        require(voteTiming.computeCurrentPhase(blockTime) == Phase.Reveal, "Cannot reveal in commit phase");
        // Note: computing the current round is required to disallow people from
        // revealing an old commit after the round is over.
        uint256 roundId = voteTiming.computeCurrentRoundId(blockTime);

        PriceRequest storage priceRequest = _getPriceRequest(identifier, time);
        VoteInstance storage voteInstance = priceRequest.voteInstances[roundId];
        VoteSubmission storage voteSubmission = voteInstance.voteSubmissions[msg.sender];

        // 0 hashes are disallowed in the commit phase, so they indicate a different error.
        // Cannot reveal an uncommitted or previously revealed hash
        require(voteSubmission.commit != bytes32(0), "Invalid hash reveal");
        require(
            keccak256(abi.encodePacked(price, salt, msg.sender, time, roundId, identifier)) == voteSubmission.commit,
            "Revealed data != commit hash"
        );
        delete voteSubmission.commit;

        // Lock in round variables including snapshotId and inflation rate. Not that this will only execute a snapshot
        // if the `snapshotCurrentRound` function was not already called for this round.
        _freezeRoundVariables(roundId);

        // Get the frozen snapshotId
        uint256 snapshotId = rounds[roundId].snapshotId;

        // Get the voter's snapshotted balance. Since balances are returned pre-scaled by 10**18, we can directly
        // initialize the Unsigned value with the returned uint.
        FixedPoint.Unsigned memory balance = FixedPoint.Unsigned(votingToken.balanceOfAt(msg.sender, snapshotId));

        // Set the voter's submission.
        voteSubmission.revealHash = keccak256(abi.encode(price));

        // Add vote to the results.
        voteInstance.resultComputation.addVote(price, balance);

        emit VoteRevealed(msg.sender, roundId, identifier, time, price, balance.rawValue);
    }

    /**
     * @notice commits a vote and logs an event with a data blob, typically an encrypted version of the vote
     * @dev An encrypted version of the vote is emitted in an event `EncryptedVote` to allow off-chain infrastructure to
     * retrieve the commit. The contents of `encryptedVote` are never used on chain: it is purely for convenience.
     * @param identifier unique price pair identifier. Eg: BTC/USD price pair.
     * @param time unix timestamp of for the price request.
     * @param hash keccak256 hash of the price you want to vote for and a `int256 salt`.
     * @param encryptedVote offchain encrypted blob containing the voters amount, time and salt.
     */
    function commitAndEmitEncryptedVote(
        bytes32 identifier,
        uint256 time,
        bytes32 hash,
        bytes memory encryptedVote
    ) public {
        commitVote(identifier, time, hash);

        uint256 roundId = voteTiming.computeCurrentRoundId(getCurrentTime());
        emit EncryptedVote(msg.sender, roundId, identifier, time, encryptedVote);
    }

    /**
     * @notice Submit a batch of commits in a single transaction.
     * @dev Using `encryptedVote` is optional. If included then commitment is emitted in an event.
     * Look at `project-root/common/Constants.js` for the tested maximum number of
     * commitments that can fit in one transaction.
     * @param commits struct to encapsulate an `identifier`, `time`, `hash` and optional `encryptedVote`.
     */
    function batchCommit(Commitment[] calldata commits) external override {
        for (uint256 i = 0; i < commits.length; i++) {
            if (commits[i].encryptedVote.length == 0) {
                commitVote(commits[i].identifier, commits[i].time, commits[i].hash);
            } else {
                commitAndEmitEncryptedVote(
                    commits[i].identifier,
                    commits[i].time,
                    commits[i].hash,
                    commits[i].encryptedVote
                );
            }
        }
    }

    /**
     * @notice Reveal multiple votes in a single transaction.
     * Look at `project-root/common/Constants.js` for the tested maximum number of reveals.
     * that can fit in one transaction.
     * @dev For more information on reveals, review the comment for `revealVote`.
     * @param reveals array of the Reveal struct which contains an identifier, time, price and salt.
     */
    function batchReveal(Reveal[] calldata reveals) external override {
        for (uint256 i = 0; i < reveals.length; i++) {
            revealVote(reveals[i].identifier, reveals[i].time, reveals[i].price, reveals[i].salt);
        }
    }

    /**
     * @notice Retrieves rewards owed for a set of resolved price requests.
     * @dev Can only retrieve rewards if calling for a valid round and if the
     * call is done within the timeout threshold (not expired).
     * @param voterAddress voter for which rewards will be retrieved. Does not have to be the caller.
     * @param roundId the round from which voting rewards will be retrieved from.
     * @param toRetrieve array of PendingRequests which rewards are retrieved from.
     * @return totalRewardToIssue total amount of rewards returned to the voter.
     */
    function retrieveRewards(
        address voterAddress,
        uint256 roundId,
        PendingRequest[] memory toRetrieve
    ) public override returns (FixedPoint.Unsigned memory totalRewardToIssue) {
        if (migratedAddress != address(0)) {
            require(msg.sender == migratedAddress, "Can only call from migrated");
        }
        uint256 blockTime = getCurrentTime();
        require(roundId < voteTiming.computeCurrentRoundId(blockTime), "Invalid roundId");

        Round storage round = rounds[roundId];
        bool isExpired = blockTime > round.rewardsExpirationTime;
        FixedPoint.Unsigned memory snapshotBalance = FixedPoint.Unsigned(
            votingToken.balanceOfAt(voterAddress, round.snapshotId)
        );

        // Compute the total amount of reward that will be issued for each of the votes in the round.
        FixedPoint.Unsigned memory snapshotTotalSupply = FixedPoint.Unsigned(
            votingToken.totalSupplyAt(round.snapshotId)
        );
        FixedPoint.Unsigned memory totalRewardPerVote = round.inflationRate.mul(snapshotTotalSupply);

        // Keep track of the voter's accumulated token reward.
        totalRewardToIssue = FixedPoint.Unsigned(0);

        for (uint256 i = 0; i < toRetrieve.length; i++) {
            PriceRequest storage priceRequest = _getPriceRequest(toRetrieve[i].identifier, toRetrieve[i].time);
            VoteInstance storage voteInstance = priceRequest.voteInstances[priceRequest.lastVotingRound];
            // Only retrieve rewards for votes resolved in same round
            require(priceRequest.lastVotingRound == roundId, "Retrieve for votes same round");

            _resolvePriceRequest(priceRequest, voteInstance);

            if (voteInstance.voteSubmissions[voterAddress].revealHash == 0) {
                continue;
            } else if (isExpired) {
                // Emit a 0 token retrieval on expired rewards.
                emit RewardsRetrieved(voterAddress, roundId, toRetrieve[i].identifier, toRetrieve[i].time, 0);
            } else if (
                voteInstance.resultComputation.wasVoteCorrect(voteInstance.voteSubmissions[voterAddress].revealHash)
            ) {
                // The price was successfully resolved during the voter's last voting round, the voter revealed
                // and was correct, so they are eligible for a reward.
                // Compute the reward and add to the cumulative reward.
                FixedPoint.Unsigned memory reward = snapshotBalance.mul(totalRewardPerVote).div(
                    voteInstance.resultComputation.getTotalCorrectlyVotedTokens()
                );
                totalRewardToIssue = totalRewardToIssue.add(reward);

                // Emit reward retrieval for this vote.
                emit RewardsRetrieved(
                    voterAddress,
                    roundId,
                    toRetrieve[i].identifier,
                    toRetrieve[i].time,
                    reward.rawValue
                );
            } else {
                // Emit a 0 token retrieval on incorrect votes.
                emit RewardsRetrieved(voterAddress, roundId, toRetrieve[i].identifier, toRetrieve[i].time, 0);
            }

            // Delete the submission to capture any refund and clean up storage.
            delete voteInstance.voteSubmissions[voterAddress].revealHash;
        }

        // Issue any accumulated rewards.
        if (totalRewardToIssue.isGreaterThan(0)) {
            require(votingToken.mint(voterAddress, totalRewardToIssue.rawValue), "Voting token issuance failed");
        }
    }

    /****************************************
     *        VOTING GETTER FUNCTIONS       *
     ****************************************/

    /**
     * @notice Gets the queries that are being voted on this round.
     * @return pendingRequests array containing identifiers of type `PendingRequest`.
     * and timestamps for all pending requests.
     */
    function getPendingRequests() external override view returns (PendingRequest[] memory) {
        uint256 blockTime = getCurrentTime();
        uint256 currentRoundId = voteTiming.computeCurrentRoundId(blockTime);

        // Solidity memory arrays aren't resizable (and reading storage is expensive). Hence this hackery to filter
        // `pendingPriceRequests` only to those requests that have an Active RequestStatus.
        PendingRequest[] memory unresolved = new PendingRequest[](pendingPriceRequests.length);
        uint256 numUnresolved = 0;

        for (uint256 i = 0; i < pendingPriceRequests.length; i++) {
            PriceRequest storage priceRequest = priceRequests[pendingPriceRequests[i]];
            if (_getRequestStatus(priceRequest, currentRoundId) == RequestStatus.Active) {
                unresolved[numUnresolved] = PendingRequest({
                    identifier: priceRequest.identifier,
                    time: priceRequest.time
                });
                numUnresolved++;
            }
        }

        PendingRequest[] memory pendingRequests = new PendingRequest[](numUnresolved);
        for (uint256 i = 0; i < numUnresolved; i++) {
            pendingRequests[i] = unresolved[i];
        }
        return pendingRequests;
    }

    /**
     * @notice Returns the current voting phase, as a function of the current time.
     * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES_PLACEHOLDER }.
     */
    function getVotePhase() external override view returns (Phase) {
        return voteTiming.computeCurrentPhase(getCurrentTime());
    }

    /**
     * @notice Returns the current round ID, as a function of the current time.
     * @return uint256 representing the unique round ID.
     */
    function getCurrentRoundId() external override view returns (uint256) {
        return voteTiming.computeCurrentRoundId(getCurrentTime());
    }

    /****************************************
     *        OWNER ADMIN FUNCTIONS         *
     ****************************************/

    /**
     * @notice Disables this Voting contract in favor of the migrated one.
     * @dev Can only be called by the contract owner.
     * @param newVotingAddress the newly migrated contract address.
     */
    function setMigrated(address newVotingAddress) external onlyOwner {
        migratedAddress = newVotingAddress;
    }

    /**
     * @notice Resets the inflation rate. Note: this change only applies to rounds that have not yet begun.
     * @dev This method is public because calldata structs are not currently supported by solidity.
     * @param newInflationRate sets the next round's inflation rate.
     */
    function setInflationRate(FixedPoint.Unsigned memory newInflationRate) public onlyOwner {
        inflationRate = newInflationRate;
    }

    /**
     * @notice Resets the Gat percentage. Note: this change only applies to rounds that have not yet begun.
     * @dev This method is public because calldata structs are not currently supported by solidity.
     * @param newGatPercentage sets the next round's Gat percentage.
     */
    function setGatPercentage(FixedPoint.Unsigned memory newGatPercentage) public onlyOwner {
        require(newGatPercentage.isLessThan(1), "GAT percentage must be < 100%");
        gatPercentage = newGatPercentage;
    }

    /**
     * @notice Resets the rewards expiration timeout.
     * @dev This change only applies to rounds that have not yet begun.
     * @param NewRewardsExpirationTimeout how long a caller can wait before choosing to withdraw their rewards.
     */
    function setRewardsExpirationTimeout(uint256 NewRewardsExpirationTimeout) public onlyOwner {
        rewardsExpirationTimeout = NewRewardsExpirationTimeout;
    }

    /****************************************
     *    PRIVATE AND INTERNAL FUNCTIONS    *
     ****************************************/

    // Returns the price for a given identifer. Three params are returns: bool if there was an error, int to represent
    // the resolved price and a string which is filled with an error message, if there was an error or "".
    function _getPriceOrError(bytes32 identifier, uint256 time)
        private
        view
        returns (
            bool,
            int256,
            string memory
        )
    {
        PriceRequest storage priceRequest = _getPriceRequest(identifier, time);
        uint256 currentRoundId = voteTiming.computeCurrentRoundId(getCurrentTime());

        RequestStatus requestStatus = _getRequestStatus(priceRequest, currentRoundId);
        if (requestStatus == RequestStatus.Active) {
            return (false, 0, "Current voting round not ended");
        } else if (requestStatus == RequestStatus.Resolved) {
            VoteInstance storage voteInstance = priceRequest.voteInstances[priceRequest.lastVotingRound];
            (, int256 resolvedPrice) = voteInstance.resultComputation.getResolvedPrice(
                _computeGat(priceRequest.lastVotingRound)
            );
            return (true, resolvedPrice, "");
        } else if (requestStatus == RequestStatus.Future) {
            return (false, 0, "Price is still to be voted on");
        } else {
            return (false, 0, "Price was never requested");
        }
    }

    function _getPriceRequest(bytes32 identifier, uint256 time) private view returns (PriceRequest storage) {
        return priceRequests[_encodePriceRequest(identifier, time)];
    }

    function _encodePriceRequest(bytes32 identifier, uint256 time) private pure returns (bytes32) {
        return keccak256(abi.encode(identifier, time));
    }

    function _freezeRoundVariables(uint256 roundId) private {
        Round storage round = rounds[roundId];
        // Only on the first reveal should the snapshot be captured for that round.
        if (round.snapshotId == 0) {
            // There is no snapshot ID set, so create one.
            round.snapshotId = votingToken.snapshot();

            // Set the round inflation rate to the current global inflation rate.
            rounds[roundId].inflationRate = inflationRate;

            // Set the round gat percentage to the current global gat rate.
            rounds[roundId].gatPercentage = gatPercentage;

            // Set the rewards expiration time based on end of time of this round and the current global timeout.
            rounds[roundId].rewardsExpirationTime = voteTiming.computeRoundEndTime(roundId).add(
                rewardsExpirationTimeout
            );
        }
    }

    function _resolvePriceRequest(PriceRequest storage priceRequest, VoteInstance storage voteInstance) private {
        if (priceRequest.index == UINT_MAX) {
            return;
        }
        (bool isResolved, int256 resolvedPrice) = voteInstance.resultComputation.getResolvedPrice(
            _computeGat(priceRequest.lastVotingRound)
        );
        require(isResolved, "Can't resolve unresolved request");

        // Delete the resolved price request from pendingPriceRequests.
        uint256 lastIndex = pendingPriceRequests.length - 1;
        PriceRequest storage lastPriceRequest = priceRequests[pendingPriceRequests[lastIndex]];
        lastPriceRequest.index = priceRequest.index;
        pendingPriceRequests[priceRequest.index] = pendingPriceRequests[lastIndex];
        pendingPriceRequests.pop();

        priceRequest.index = UINT_MAX;
        emit PriceResolved(priceRequest.lastVotingRound, priceRequest.identifier, priceRequest.time, resolvedPrice);
    }

    function _computeGat(uint256 roundId) private view returns (FixedPoint.Unsigned memory) {
        uint256 snapshotId = rounds[roundId].snapshotId;
        if (snapshotId == 0) {
            // No snapshot - return max value to err on the side of caution.
            return FixedPoint.Unsigned(UINT_MAX);
        }

        // Grab the snapshotted supply from the voting token. It's already scaled by 10**18, so we can directly
        // initialize the Unsigned value with the returned uint.
        FixedPoint.Unsigned memory snapshottedSupply = FixedPoint.Unsigned(votingToken.totalSupplyAt(snapshotId));

        // Multiply the total supply at the snapshot by the gatPercentage to get the GAT in number of tokens.
        return snapshottedSupply.mul(rounds[roundId].gatPercentage);
    }

    function _getRequestStatus(PriceRequest storage priceRequest, uint256 currentRoundId)
        private
        view
        returns (RequestStatus)
    {
        if (priceRequest.lastVotingRound == 0) {
            return RequestStatus.NotRequested;
        } else if (priceRequest.lastVotingRound < currentRoundId) {
            VoteInstance storage voteInstance = priceRequest.voteInstances[priceRequest.lastVotingRound];
            (bool isResolved, ) = voteInstance.resultComputation.getResolvedPrice(
                _computeGat(priceRequest.lastVotingRound)
            );
            return isResolved ? RequestStatus.Resolved : RequestStatus.Active;
        } else if (priceRequest.lastVotingRound == currentRoundId) {
            return RequestStatus.Active;
        } else {
            // Means than priceRequest.lastVotingRound > currentRoundId
            return RequestStatus.Future;
        }
    }

    function _getIdentifierWhitelist() private view returns (IdentifierWhitelistInterface supportedIdentifiers) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }
}

File 2 of 117: AccessControl.sol
pragma solidity ^0.6.0;

import "./EnumerableSet.sol";
import "./Address.sol";
import "./Context.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, _msgSender()));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 */
abstract contract AccessControl is Context {
    using EnumerableSet for EnumerableSet.AddressSet;
    using Address for address;

    struct RoleData {
        EnumerableSet.AddressSet members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view returns (bool) {
        return _roles[role].members.contains(account);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view returns (uint256) {
        return _roles[role].members.length();
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
        return _roles[role].members.at(index);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual {
        require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (_roles[role].members.add(account)) {
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (_roles[role].members.remove(account)) {
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 3 of 117: Address.sol
pragma solidity ^0.6.2;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
}

File 4 of 117: AddressWhitelist.sol
pragma solidity ^0.6.0;

import "./Ownable.sol";


/**
 * @title A contract to track a whitelist of addresses.
 */
contract AddressWhitelist is Ownable {
    enum Status { None, In, Out }
    mapping(address => Status) public whitelist;

    address[] public whitelistIndices;

    event AddedToWhitelist(address indexed addedAddress);
    event RemovedFromWhitelist(address indexed removedAddress);

    /**
     * @notice Adds an address to the whitelist.
     * @param newElement the new address to add.
     */
    function addToWhitelist(address newElement) external onlyOwner {
        // Ignore if address is already included
        if (whitelist[newElement] == Status.In) {
            return;
        }

        // Only append new addresses to the array, never a duplicate
        if (whitelist[newElement] == Status.None) {
            whitelistIndices.push(newElement);
        }

        whitelist[newElement] = Status.In;

        emit AddedToWhitelist(newElement);
    }

    /**
     * @notice Removes an address from the whitelist.
     * @param elementToRemove the existing address to remove.
     */
    function removeFromWhitelist(address elementToRemove) external onlyOwner {
        if (whitelist[elementToRemove] != Status.Out) {
            whitelist[elementToRemove] = Status.Out;
            emit RemovedFromWhitelist(elementToRemove);
        }
    }

    /**
     * @notice Checks whether an address is on the whitelist.
     * @param elementToCheck the address to check.
     * @return True if `elementToCheck` is on the whitelist, or False.
     */
    function isOnWhitelist(address elementToCheck) external view returns (bool) {
        return whitelist[elementToCheck] == Status.In;
    }

    /**
     * @notice Gets all addresses that are currently included in the whitelist.
     * @dev Note: This method skips over, but still iterates through addresses. It is possible for this call to run out
     * of gas if a large number of addresses have been removed. To reduce the likelihood of this unlikely scenario, we
     * can modify the implementation so that when addresses are removed, the last addresses in the array is moved to
     * the empty index.
     * @return activeWhitelist the list of addresses on the whitelist.
     */
    function getWhitelist() external view returns (address[] memory activeWhitelist) {
        // Determine size of whitelist first
        uint256 activeCount = 0;
        for (uint256 i = 0; i < whitelistIndices.length; i++) {
            if (whitelist[whitelistIndices[i]] == Status.In) {
                activeCount++;
            }
        }

        // Populate whitelist
        activeWhitelist = new address[](activeCount);
        activeCount = 0;
        for (uint256 i = 0; i < whitelistIndices.length; i++) {
            address addr = whitelistIndices[i];
            if (whitelist[addr] == Status.In) {
                activeWhitelist[activeCount] = addr;
                activeCount++;
            }
        }
    }
}

File 5 of 117: AdministrateeInterface.sol
pragma solidity ^0.6.0;


/**
 * @title Interface that all financial contracts expose to the admin.
 */
interface AdministrateeInterface {
    /**
     * @notice Initiates the shutdown process, in case of an emergency.
     */
    function emergencyShutdown() external;

    /**
     * @notice A core contract method called independently or as a part of other financial contract transactions.
     * @dev It pays fees and moves money between margin accounts to make sure they reflect the NAV of the contract.
     */
    function remargin() external;
}

File 6 of 117: Arrays.sol
pragma solidity ^0.6.0;

import "./Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
   /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

File 7 of 117: ConditionalEscrow.sol
pragma solidity ^0.6.0;

import "./Escrow.sol";

/**
 * @title ConditionalEscrow
 * @dev Base abstract escrow to only allow withdrawal if a condition is met.
 * @dev Intended usage: See {Escrow}. Same usage guidelines apply here.
 */
abstract contract ConditionalEscrow is Escrow {
    /**
     * @dev Returns whether an address is allowed to withdraw their funds. To be
     * implemented by derived contracts.
     * @param payee The destination address of the funds.
     */
    function withdrawalAllowed(address payee) public view virtual returns (bool);

    function withdraw(address payable payee) public virtual override {
        require(withdrawalAllowed(payee), "ConditionalEscrow: payee is not allowed to withdraw");
        super.withdraw(payee);
    }
}

File 8 of 117: Constants.sol
pragma solidity ^0.6.0;


/**
 * @title Stores common interface names used throughout the DVM by registration in the Finder.
 */
library OracleInterfaces {
    bytes32 public constant Oracle = "Oracle";
    bytes32 public constant IdentifierWhitelist = "IdentifierWhitelist";
    bytes32 public constant Store = "Store";
    bytes32 public constant FinancialContractsAdmin = "FinancialContractsAdmin";
    bytes32 public constant Registry = "Registry";
}

File 9 of 117: Context.sol
pragma solidity ^0.6.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.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }

    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 10 of 117: ContractCreator.sol
pragma solidity ^0.6.0;

import "./FinderInterface.sol";
import "./Registry.sol";


/**
 * @title Base contract for all financial contract creators
 */
abstract contract ContractCreator {
    address internal finderAddress;

    constructor(address _finderAddress) public {
        finderAddress = _finderAddress;
    }

    function _registerContract(address[] memory parties, address contractToRegister) internal {
        FinderInterface finder = FinderInterface(finderAddress);
        bytes32 registryInterface = "Registry";
        Registry registry = Registry(finder.getImplementationAddress(registryInterface));
        registry.registerContract(parties, contractToRegister);
    }
}

File 11 of 117: Counters.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
 * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
 * directly accessed.
 */
library Counters {
    using SafeMath for uint256;

    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        // The {SafeMath} overflow check can be skipped here, see the comment at the top
        counter._value += 1;
    }

    function decrement(Counter storage counter) internal {
        counter._value = counter._value.sub(1);
    }
}

File 12 of 117: Create2.sol
pragma solidity ^0.6.0;

/**
 * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
 * `CREATE2` can be used to compute in advance the address where a smart
 * contract will be deployed, which allows for interesting new mechanisms known
 * as 'counterfactual interactions'.
 *
 * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
 * information.
 */
library Create2 {
    /**
     * @dev Deploys a contract using `CREATE2`. The address where the contract
     * will be deployed can be known in advance via {computeAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already.
     * - the factory must have a balance of at least `amount`.
     * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
     */
    function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {
        address addr;
        require(address(this).balance >= amount, "Create2: insufficient balance");
        require(bytecode.length != 0, "Create2: bytecode length is zero");
        // solhint-disable-next-line no-inline-assembly
        assembly {
            addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
        }
        require(addr != address(0), "Create2: Failed on deploy");
        return addr;
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
     * `bytecodeHash` or `salt` will result in a new destination address.
     */
    function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
        return computeAddress(salt, bytecodeHash, address(this));
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
     * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
     */
    function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {
        bytes32 _data = keccak256(
            abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)
        );
        return address(bytes20(_data << 96));
    }
}

File 13 of 117: DesignatedVoting.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./MultiRole.sol";
import "./Withdrawable.sol";
import "./VotingInterface.sol";
import "./FinderInterface.sol";
import "./Constants.sol";


/**
 * @title Proxy to allow voting from another address.
 * @dev Allows a UMA token holder to designate another address to vote on their behalf.
 * Each voter must deploy their own instance of this contract.
 */
contract DesignatedVoting is Withdrawable {
    /****************************************
     *    INTERNAL VARIABLES AND STORAGE    *
     ****************************************/

    enum Roles {
        Owner, // Can set the Voter role. Is also permanently permissioned as the minter roll.
        Voter // Can vote through this contract.
    }

    // Reference to the UMA Finder contract, allowing Voting upgrades to be performed
    // without requiring any calls to this contract.
    FinderInterface private finder;

    /**
     * @notice Construct the DesignatedVoting contract.
     * @param finderAddress keeps track of all contracts within the system based on their interfaceName.
     * @param ownerAddress address of the owner of the DesignatedVoting contract.
     * @param voterAddress address to which the owner has delegated their voting power.
     */
    constructor(
        address finderAddress,
        address ownerAddress,
        address voterAddress
    ) public {
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), ownerAddress);
        _createExclusiveRole(uint256(Roles.Voter), uint256(Roles.Owner), voterAddress);
        _setWithdrawRole(uint256(Roles.Owner));

        finder = FinderInterface(finderAddress);
    }

    /****************************************
     *   VOTING AND REWARD FUNCTIONALITY    *
     ****************************************/

    /**
     * @notice Forwards a commit to Voting.
     * @param identifier uniquely identifies the feed for this vote. EG BTC/USD price pair.
     * @param time specifies the unix timestamp of the price being voted on.
     * @param hash the keccak256 hash of the price you want to vote for and a random integer salt value.
     */
    function commitVote(
        bytes32 identifier,
        uint256 time,
        bytes32 hash
    ) external onlyRoleHolder(uint256(Roles.Voter)) {
        _getVotingAddress().commitVote(identifier, time, hash);
    }

    /**
     * @notice Forwards a batch commit to Voting.
     * @param commits struct to encapsulate an `identifier`, `time`, `hash` and optional `encryptedVote`.
     */
    function batchCommit(VotingInterface.Commitment[] calldata commits) external onlyRoleHolder(uint256(Roles.Voter)) {
        _getVotingAddress().batchCommit(commits);
    }

    /**
     * @notice Forwards a reveal to Voting.
     * @param identifier voted on in the commit phase. EG BTC/USD price pair.
     * @param time specifies the unix timestamp of the price being voted on.
     * @param price used along with the `salt` to produce the `hash` during the commit phase.
     * @param salt used along with the `price` to produce the `hash` during the commit phase.
     */
    function revealVote(
        bytes32 identifier,
        uint256 time,
        int256 price,
        int256 salt
    ) external onlyRoleHolder(uint256(Roles.Voter)) {
        _getVotingAddress().revealVote(identifier, time, price, salt);
    }

    /**
     * @notice Forwards a batch reveal to Voting.
     * @param reveals is an array of the Reveal struct which contains an identifier, time, price and salt.
     */
    function batchReveal(VotingInterface.Reveal[] calldata reveals) external onlyRoleHolder(uint256(Roles.Voter)) {
        _getVotingAddress().batchReveal(reveals);
    }

    /**
     * @notice Forwards a reward retrieval to Voting.
     * @dev Rewards are added to the tokens already held by this contract.
     * @param roundId defines the round from which voting rewards will be retrieved from.
     * @param toRetrieve an array of PendingRequests which rewards are retrieved from.
     * @return amount of rewards that the user should receive.
     */
    function retrieveRewards(uint256 roundId, VotingInterface.PendingRequest[] memory toRetrieve)
        public
        onlyRoleHolder(uint256(Roles.Voter))
        returns (FixedPoint.Unsigned memory)
    {
        return _getVotingAddress().retrieveRewards(address(this), roundId, toRetrieve);
    }

    function _getVotingAddress() private view returns (VotingInterface) {
        return VotingInterface(finder.getImplementationAddress(OracleInterfaces.Oracle));
    }
}

File 14 of 117: DesignatedVotingFactory.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./Withdrawable.sol";
import "./DesignatedVoting.sol";


/**
 * @title Factory to deploy new instances of DesignatedVoting and look up previously deployed instances.
 * @dev Allows off-chain infrastructure to look up a hot wallet's deployed DesignatedVoting contract.
 */
contract DesignatedVotingFactory is Withdrawable {
    /****************************************
     *    INTERNAL VARIABLES AND STORAGE    *
     ****************************************/

    enum Roles {
        Withdrawer // Can withdraw any ETH or ERC20 sent accidentally to this contract.
    }

    address private finder;
    mapping(address => DesignatedVoting) public designatedVotingContracts;

    /**
     * @notice Construct the DesignatedVotingFactory contract.
     * @param finderAddress keeps track of all contracts within the system based on their interfaceName.
     */
    constructor(address finderAddress) public {
        finder = finderAddress;

        _createWithdrawRole(uint256(Roles.Withdrawer), uint256(Roles.Withdrawer), msg.sender);
    }

    /**
     * @notice Deploys a new `DesignatedVoting` contract.
     * @param ownerAddress defines who will own the deployed instance of the designatedVoting contract.
     * @return designatedVoting a new DesignatedVoting contract.
     */
    function newDesignatedVoting(address ownerAddress) external returns (DesignatedVoting) {
        require(address(designatedVotingContracts[msg.sender]) == address(0), "Duplicate hot key not permitted");

        DesignatedVoting designatedVoting = new DesignatedVoting(finder, ownerAddress, msg.sender);
        designatedVotingContracts[msg.sender] = designatedVoting;
        return designatedVoting;
    }

    /**
     * @notice Associates a `DesignatedVoting` instance with `msg.sender`.
     * @param designatedVotingAddress address to designate voting to.
     * @dev This is generally only used if the owner of a `DesignatedVoting` contract changes their `voter`
     * address and wants that reflected here.
     */
    function setDesignatedVoting(address designatedVotingAddress) external {
        require(address(designatedVotingContracts[msg.sender]) == address(0), "Duplicate hot key not permitted");
        designatedVotingContracts[msg.sender] = DesignatedVoting(designatedVotingAddress);
    }
}

File 15 of 117: ECDSA.sol
pragma solidity ^0.6.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            revert("ECDSA: invalid signature length");
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            revert("ECDSA: invalid signature 's' value");
        }

        if (v != 27 && v != 28) {
            revert("ECDSA: invalid signature 'v' value");
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

File 16 of 117: EnumerableMap.sol
pragma solidity ^0.6.0;

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
 * supported.
 */
library EnumerableMap {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct MapEntry {
        bytes32 _key;
        bytes32 _value;
    }

    struct Map {
        // Storage of map keys and values
        MapEntry[] _entries;

        // Position of the entry defined by a key in the `entries` array, plus 1
        // because index 0 means a key is not in the map.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex == 0) { // Equivalent to !contains(map, key)
            map._entries.push(MapEntry({ _key: key, _value: value }));
            // The entry is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            map._indexes[key] = map._entries.length;
            return true;
        } else {
            map._entries[keyIndex - 1]._value = value;
            return false;
        }
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function _remove(Map storage map, bytes32 key) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex != 0) { // Equivalent to contains(map, key)
            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
            // in the array, and then remove the last entry (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = keyIndex - 1;
            uint256 lastIndex = map._entries.length - 1;

            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            MapEntry storage lastEntry = map._entries[lastIndex];

            // Move the last entry to the index where the entry to delete is
            map._entries[toDeleteIndex] = lastEntry;
            // Update the index for the moved entry
            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved entry was stored
            map._entries.pop();

            // Delete the index for the deleted slot
            delete map._indexes[key];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function _contains(Map storage map, bytes32 key) private view returns (bool) {
        return map._indexes[key] != 0;
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function _length(Map storage map) private view returns (uint256) {
        return map._entries.length;
    }

   /**
    * @dev Returns the key-value pair stored at position `index` in the map. O(1).
    *
    * Note that there are no guarantees on the ordering of entries inside the
    * array, and it may change when more entries are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
        require(map._entries.length > index, "EnumerableMap: index out of bounds");

        MapEntry storage entry = map._entries[index];
        return (entry._key, entry._value);
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        return _get(map, key, "EnumerableMap: nonexistent key");
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     */
    function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(value)));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
        return _remove(map._inner, bytes32(key));
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
        return _contains(map._inner, bytes32(key));
    }

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToAddressMap storage map) internal view returns (uint256) {
        return _length(map._inner);
    }

   /**
    * @dev Returns the element stored at position `index` in the set. O(1).
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
        (bytes32 key, bytes32 value) = _at(map._inner, index);
        return (uint256(key), address(uint256(value)));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint256(_get(map._inner, bytes32(key))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     */
    function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
        return address(uint256(_get(map._inner, bytes32(key), errorMessage)));
    }
}

File 17 of 117: EnumerableSet.sol
pragma solidity ^0.6.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint256(_at(set._inner, index)));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 18 of 117: ERC165.sol
pragma solidity ^0.6.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

File 19 of 117: ERC165Checker.sol
pragma solidity ^0.6.2;

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) &&
            _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        // success determines whether the staticcall succeeded and result determines
        // whether the contract at account indicates support of _interfaceId
        (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId);

        return (success && result);
    }

    /**
     * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return success true if the STATICCALL succeeded, false otherwise
     * @return result true if the STATICCALL succeeded and the contract at account
     * indicates support of the interface with identifier interfaceId, false otherwise
     */
    function _callERC165SupportsInterface(address account, bytes4 interfaceId)
        private
        view
        returns (bool, bool)
    {
        bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId);
        (bool success, bytes memory result) = account.staticcall{ gas: 30000 }(encodedParams);
        if (result.length < 32) return (false, false);
        return (success, abi.decode(result, (bool)));
    }
}

File 20 of 117: ERC1820Implementer.sol
pragma solidity ^0.6.0;

import "./IERC1820Implementer.sol";

/**
 * @dev Implementation of the {IERC1820Implementer} interface.
 *
 * Contracts may inherit from this and call {_registerInterfaceForAddress} to
 * declare their willingness to be implementers.
 * {IERC1820Registry-setInterfaceImplementer} should then be called for the
 * registration to be complete.
 */
contract ERC1820Implementer is IERC1820Implementer {
    bytes32 constant private _ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));

    mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;

    /**
     * See {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) public view override returns (bytes32) {
        return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
    }

    /**
     * @dev Declares the contract as willing to be an implementer of
     * `interfaceHash` for `account`.
     *
     * See {IERC1820Registry-setInterfaceImplementer} and
     * {IERC1820Registry-interfaceHash}.
     */
    function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal virtual {
        _supportedInterfaces[interfaceHash][account] = true;
    }
}

File 21 of 117: ERC20.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20MinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

File 22 of 117: ERC20Burnable.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./ERC20.sol";

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
abstract contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");

        _approve(account, _msgSender(), decreasedAllowance);
        _burn(account, amount);
    }
}

File 23 of 117: ERC20Capped.sol
pragma solidity ^0.6.0;

import "./ERC20.sol";

/**
 * @dev Extension of {ERC20} that adds a cap to the supply of tokens.
 */
abstract contract ERC20Capped is ERC20 {
    uint256 private _cap;

    /**
     * @dev Sets the value of the `cap`. This value is immutable, it can only be
     * set once during construction.
     */
    constructor (uint256 cap) public {
        require(cap > 0, "ERC20Capped: cap is 0");
        _cap = cap;
    }

    /**
     * @dev Returns the cap on the token's total supply.
     */
    function cap() public view returns (uint256) {
        return _cap;
    }

    /**
     * @dev See {ERC20-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - minted tokens must not cause the total supply to go over the cap.
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        if (from == address(0)) { // When minting tokens
            require(totalSupply().add(amount) <= _cap, "ERC20Capped: cap exceeded");
        }
    }
}

File 24 of 117: ERC20Pausable.sol
pragma solidity ^0.6.0;

import "./ERC20.sol";
import "./Pausable.sol";

/**
 * @dev ERC20 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 */
abstract contract ERC20Pausable is ERC20, Pausable {
    /**
     * @dev See {ERC20-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        require(!paused(), "ERC20Pausable: token transfer while paused");
    }
}

File 25 of 117: ERC20PresetMinterPauser.sol
pragma solidity ^0.6.0;

import "./AccessControl.sol";
import "./Context.sol";
import "./ERC20.sol";
import "./ERC20Burnable.sol";
import "./ERC20Pausable.sol";

/**
 * @dev {ERC20} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to aother accounts
 */
contract ERC20PresetMinterPauser is Context, AccessControl, ERC20Burnable, ERC20Pausable {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * See {ERC20-constructor}.
     */
    constructor(string memory name, string memory symbol) public ERC20(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    /**
     * @dev Creates `amount` new tokens for `to`.
     *
     * See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to, uint256 amount) public {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
        _mint(to, amount);
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
        _unpause();
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Pausable) {
        super._beforeTokenTransfer(from, to, amount);
    }
}

File 26 of 117: ERC20Snapshot.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";
import "./Arrays.sol";
import "./Counters.sol";
import "./ERC20.sol";

/**
 * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
 * total supply at the time are recorded for later access.
 *
 * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
 * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
 * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
 * used to create an efficient ERC20 forking mechanism.
 *
 * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
 * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
 * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
 * and the account address.
 *
 * ==== Gas Costs
 *
 * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
 * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
 * smaller since identical balances in subsequent snapshots are stored as a single entry.
 *
 * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
 * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
 * transfers will have normal cost until the next snapshot, and so on.
 */
abstract contract ERC20Snapshot is ERC20 {
    // Inspired by Jordi Baylina's MiniMeToken to record historical balances:
    // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol

    using SafeMath for uint256;
    using Arrays for uint256[];
    using Counters for Counters.Counter;

    // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
    // Snapshot struct, but that would impede usage of functions that work on an array.
    struct Snapshots {
        uint256[] ids;
        uint256[] values;
    }

    mapping (address => Snapshots) private _accountBalanceSnapshots;
    Snapshots private _totalSupplySnapshots;

    // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
    Counters.Counter private _currentSnapshotId;

    /**
     * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
     */
    event Snapshot(uint256 id);

    /**
     * @dev Creates a new snapshot and returns its snapshot id.
     *
     * Emits a {Snapshot} event that contains the same id.
     *
     * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
     * set of accounts, for example using {AccessControl}, or it may be open to the public.
     *
     * [WARNING]
     * ====
     * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
     * you must consider that it can potentially be used by attackers in two ways.
     *
     * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
     * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
     * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
     * section above.
     *
     * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
     * ====
     */
    function _snapshot() internal virtual returns (uint256) {
        _currentSnapshotId.increment();

        uint256 currentId = _currentSnapshotId.current();
        emit Snapshot(currentId);
        return currentId;
    }

    /**
     * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
     */
    function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);

        return snapshotted ? value : balanceOf(account);
    }

    /**
     * @dev Retrieves the total supply at the time `snapshotId` was created.
     */
    function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);

        return snapshotted ? value : totalSupply();
    }

    // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the
    // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value.
    // The same is true for the total supply and _mint and _burn.
    function _transfer(address from, address to, uint256 value) internal virtual override {
        _updateAccountSnapshot(from);
        _updateAccountSnapshot(to);

        super._transfer(from, to, value);
    }

    function _mint(address account, uint256 value) internal virtual override {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._mint(account, value);
    }

    function _burn(address account, uint256 value) internal virtual override {
        _updateAccountSnapshot(account);
        _updateTotalSupplySnapshot();

        super._burn(account, value);
    }

    function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
        private view returns (bool, uint256)
    {
        require(snapshotId > 0, "ERC20Snapshot: id is 0");
        // solhint-disable-next-line max-line-length
        require(snapshotId <= _currentSnapshotId.current(), "ERC20Snapshot: nonexistent id");

        // When a valid snapshot is queried, there are three possibilities:
        //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
        //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
        //  to this id is the current one.
        //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
        //  requested id, and its value is the one to return.
        //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
        //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
        //  larger than the requested one.
        //
        // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
        // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
        // exactly this.

        uint256 index = snapshots.ids.findUpperBound(snapshotId);

        if (index == snapshots.ids.length) {
            return (false, 0);
        } else {
            return (true, snapshots.values[index]);
        }
    }

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnapshots, totalSupply());
    }

    function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
        uint256 currentId = _currentSnapshotId.current();
        if (_lastSnapshotId(snapshots.ids) < currentId) {
            snapshots.ids.push(currentId);
            snapshots.values.push(currentValue);
        }
    }

    function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
        if (ids.length == 0) {
            return 0;
        } else {
            return ids[ids.length - 1];
        }
    }
}

File 27 of 117: ERC721.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./IERC721.sol";
import "./IERC721Metadata.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Receiver.sol";
import "./ERC165.sol";
import "./SafeMath.sol";
import "./Address.sol";
import "./EnumerableSet.sol";
import "./EnumerableMap.sol";
import "./Strings.sol";

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using Strings for uint256;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSet.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMap.UintToAddressMap private _tokenOwners;

    // Mapping from token ID to approved address
    mapping (uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

    constructor (string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address owner) public view override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");

        return _holderTokens[owner].length();
    }

    /**
     * @dev Gets the owner of the specified token ID.
     * @param tokenId uint256 ID of the token to query the owner of
     * @return address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

    /**
     * @dev Gets the token name.
     * @return string representing the token name
     */
    function name() public view override returns (string memory) {
        return _name;
    }

    /**
     * @dev Gets the token symbol.
     * @return string representing the token symbol
     */
    function symbol() public view override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the URI for a given token ID. May return an empty string.
     *
     * If a base URI is set (via {_setBaseURI}), it is added as a prefix to the
     * token's own URI (via {_setTokenURI}).
     *
     * If there is a base URI but no token URI, the token's ID will be used as
     * its URI when appending it to the base URI. This pattern for autogenerated
     * token URIs can lead to large gas savings.
     *
     * .Examples
     * |===
     * |`_setBaseURI()` |`_setTokenURI()` |`tokenURI()`
     * | ""
     * | ""
     * | ""
     * | ""
     * | "token.uri/123"
     * | "token.uri/123"
     * | "token.uri/"
     * | "123"
     * | "token.uri/123"
     * | "token.uri/"
     * | ""
     * | "token.uri/<tokenId>"
     * |===
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory _tokenURI = _tokenURIs[tokenId];

        // If there is no base URI, return the token URI.
        if (bytes(_baseURI).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(_baseURI, _tokenURI));
        }
        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(_baseURI, tokenId.toString()));
    }

    /**
    * @dev Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev Gets the token ID at a given index of the tokens list of the requested owner.
     * @param owner address owning the tokens list to be accessed
     * @param index uint256 representing the index to be accessed of the requested tokens list
     * @return uint256 token ID at the given index of the tokens list owned by the requested address
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev Gets the total amount of tokens stored by the contract.
     * @return uint256 representing the total amount of tokens
     */
    function totalSupply() public view override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev Gets the token ID at a given index of all the tokens in this contract
     * Reverts if the index is greater or equal to the total number of tokens.
     * @param index uint256 representing the index to be accessed of the tokens list
     * @return uint256 token ID at the given index of the tokens list
     */
    function tokenByIndex(uint256 index) public view override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param to address to be approved for the given token ID
     * @param tokenId uint256 ID of the token to be approved
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf.
     * @param operator operator address to set the approval
     * @param approved representing the status of the approval to be set
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner.
     * @param owner owner address which you want to query the approval of
     * @param operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address.
     * Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     * Requires the msg.sender to be the owner, approved, or operator.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the _msgSender() to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg.sender to be the owner, approved, or operator
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether the specified token exists.
     * @param tokenId uint256 ID of the token to query the existence of
     * @return bool whether the token exists
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return _tokenOwners.contains(tokenId);
    }

    /**
     * @dev Returns whether the given spender can transfer a given token ID.
     * @param spender address of the spender to query
     * @param tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     * is an operator of the owner, or is the owner of the token
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Internal function to safely mint a new token.
     * Reverts if the given token ID already exists.
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     * @param _data bytes data to send along with a safe transfer check
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Internal function to mint a new token.
     * Reverts if the given token ID already exists.
     * @param to The address that will own the minted token
     * @param tokenId uint256 ID of the token to be minted
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(address(0), to, tokenId);
    }

    /**
     * @dev Internal function to burn a specific token.
     * Reverts if the token does not exist.
     * @param tokenId uint256 ID of the token being burned
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.remove(tokenId);

        emit Transfer(owner, address(0), tokenId);
    }

    /**
     * @dev Internal function to transfer ownership of a given token ID to another address.
     * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     * @param from current owner of the token
     * @param to address to receive the ownership of the given token ID
     * @param tokenId uint256 ID of the token to be transferred
     */
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Internal function to set the token URI for a given token.
     *
     * Reverts if the token ID does not exist.
     *
     * TIP: If all token IDs share a prefix (for example, if your URIs look like
     * `https://api.myproject.com/token/<id>`), use {_setBaseURI} to store
     * it and save gas.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
        _tokenURIs[tokenId] = _tokenURI;
    }

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        private returns (bool)
    {
        if (!to.isContract()) {
            return true;
        }
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = to.call(abi.encodeWithSelector(
            IERC721Receiver(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ));
        if (!success) {
            if (returndata.length > 0) {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert("ERC721: transfer to non ERC721Receiver implementer");
            }
        } else {
            bytes4 retval = abi.decode(returndata, (bytes4));
            return (retval == _ERC721_RECEIVED);
        }
    }

    function _approve(address to, uint256 tokenId) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - when `from` is zero, `tokenId` will be minted for `to`.
     * - when `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}

File 28 of 117: ERC721Burnable.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./ERC721.sol";

/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be irreversibly burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns a specific ERC721 token.
     * @param tokenId uint256 id of the ERC721 token to be burned.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
        _burn(tokenId);
    }
}

File 29 of 117: ERC721Holder.sol
pragma solidity ^0.6.0;

import "./IERC721Receiver.sol";

contract ERC721Holder is IERC721Receiver {
    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

File 30 of 117: ERC721Pausable.sol
pragma solidity ^0.6.0;

import "./ERC721.sol";
import "./Pausable.sol";

/**
 * @dev ERC721 token with pausable token transfers, minting and burning.
 *
 * Useful for scenarios such as preventing trades until the end of an evaluation
 * period, or having an emergency switch for freezing all token transfers in the
 * event of a large bug.
 */
abstract contract ERC721Pausable is ERC721, Pausable {
    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        require(!paused(), "ERC721Pausable: token transfer while paused");
    }
}

File 31 of 117: ERC721PresetMinterPauserAutoId.sol
pragma solidity ^0.6.0;

import "./AccessControl.sol";
import "./Context.sol";
import "./Counters.sol";
import "./ERC721.sol";
import "./ERC721Burnable.sol";
import "./ERC721Pausable.sol";

/**
 * @dev {ERC721} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *  - token ID and URI autogeneration
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to aother accounts
 */
contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Burnable, ERC721Pausable {
    using Counters for Counters.Counter;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    Counters.Counter private _tokenIdTracker;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE` and `MINTER_ROLE`to the account that
     * deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());

        _setBaseURI(baseURI);
    }

    /**
     * @dev Creates a new token for `to`. Its token ID will be automatically
     * assigned (and available on the emitted {Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to) public {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");

        // We can just use balanceOf to create the new tokenId because tokens
        // can be burned (destroyed), so we need a separate counter.
        _mint(to, _tokenIdTracker.current());
        _tokenIdTracker.increment();
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause");
        _unpause();
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override(ERC721, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }
}

File 32 of 117: ERC777.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./IERC777.sol";
import "./IERC777Recipient.sol";
import "./IERC777Sender.sol";
import "./IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";
import "./IERC1820Registry.sol";

/**
 * @dev Implementation of the {IERC777} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * Support for ERC20 is included in this contract, as specified by the EIP: both
 * the ERC777 and ERC20 interfaces can be safely used when interacting with it.
 * Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
 * movements.
 *
 * Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
 * are no special restrictions in the amount of tokens that created, moved, or
 * destroyed. This makes integration with ERC20 applications seamless.
 */
contract ERC777 is Context, IERC777, IERC20 {
    using SafeMath for uint256;
    using Address for address;

    IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);

    mapping(address => uint256) private _balances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    // We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
    // See https://github.com/ethereum/solidity/issues/4024.

    // keccak256("ERC777TokensSender")
    bytes32 constant private _TOKENS_SENDER_INTERFACE_HASH =
        0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;

    // keccak256("ERC777TokensRecipient")
    bytes32 constant private _TOKENS_RECIPIENT_INTERFACE_HASH =
        0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;

    // This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

    // For each account, a mapping of its operators and revoked default operators.
    mapping(address => mapping(address => bool)) private _operators;
    mapping(address => mapping(address => bool)) private _revokedDefaultOperators;

    // ERC20-allowances
    mapping (address => mapping (address => uint256)) private _allowances;

    /**
     * @dev `defaultOperators` may be an empty array.
     */
    constructor(
        string memory name,
        string memory symbol,
        address[] memory defaultOperators
    ) public {
        _name = name;
        _symbol = symbol;

        _defaultOperatorsArray = defaultOperators;
        for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
            _defaultOperators[_defaultOperatorsArray[i]] = true;
        }

        // register interfaces
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
    }

    /**
     * @dev See {IERC777-name}.
     */
    function name() public view override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC777-symbol}.
     */
    function symbol() public view override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {ERC20-decimals}.
     *
     * Always returns 18, as per the
     * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
     */
    function decimals() public pure returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC777-granularity}.
     *
     * This implementation always returns `1`.
     */
    function granularity() public view override returns (uint256) {
        return 1;
    }

    /**
     * @dev See {IERC777-totalSupply}.
     */
    function totalSupply() public view override(IERC20, IERC777) returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
     */
    function balanceOf(address tokenHolder) public view override(IERC20, IERC777) returns (uint256) {
        return _balances[tokenHolder];
    }

    /**
     * @dev See {IERC777-send}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function send(address recipient, uint256 amount, bytes memory data) public override  {
        _send(_msgSender(), recipient, amount, data, "", true);
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
     * interface if it is a contract.
     *
     * Also emits a {Sent} event.
     */
    function transfer(address recipient, uint256 amount) public override returns (bool) {
        require(recipient != address(0), "ERC777: transfer to the zero address");

        address from = _msgSender();

        _callTokensToSend(from, from, recipient, amount, "", "");

        _move(from, from, recipient, amount, "", "");

        _callTokensReceived(from, from, recipient, amount, "", "", false);

        return true;
    }

    /**
     * @dev See {IERC777-burn}.
     *
     * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
     */
    function burn(uint256 amount, bytes memory data) public override  {
        _burn(_msgSender(), amount, data, "");
    }

    /**
     * @dev See {IERC777-isOperatorFor}.
     */
    function isOperatorFor(
        address operator,
        address tokenHolder
    ) public view override returns (bool) {
        return operator == tokenHolder ||
            (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
            _operators[tokenHolder][operator];
    }

    /**
     * @dev See {IERC777-authorizeOperator}.
     */
    function authorizeOperator(address operator) public override  {
        require(_msgSender() != operator, "ERC777: authorizing self as operator");

        if (_defaultOperators[operator]) {
            delete _revokedDefaultOperators[_msgSender()][operator];
        } else {
            _operators[_msgSender()][operator] = true;
        }

        emit AuthorizedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-revokeOperator}.
     */
    function revokeOperator(address operator) public override  {
        require(operator != _msgSender(), "ERC777: revoking self as operator");

        if (_defaultOperators[operator]) {
            _revokedDefaultOperators[_msgSender()][operator] = true;
        } else {
            delete _operators[_msgSender()][operator];
        }

        emit RevokedOperator(operator, _msgSender());
    }

    /**
     * @dev See {IERC777-defaultOperators}.
     */
    function defaultOperators() public view override returns (address[] memory) {
        return _defaultOperatorsArray;
    }

    /**
     * @dev See {IERC777-operatorSend}.
     *
     * Emits {Sent} and {IERC20-Transfer} events.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
    public override
    {
        require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
        _send(sender, recipient, amount, data, operatorData, true);
    }

    /**
     * @dev See {IERC777-operatorBurn}.
     *
     * Emits {Burned} and {IERC20-Transfer} events.
     */
    function operatorBurn(address account, uint256 amount, bytes memory data, bytes memory operatorData) public override {
        require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
        _burn(account, amount, data, operatorData);
    }

    /**
     * @dev See {IERC20-allowance}.
     *
     * Note that operator and allowance concepts are orthogonal: operators may
     * not have allowance, and accounts with allowance may not be operators
     * themselves.
     */
    function allowance(address holder, address spender) public view override returns (uint256) {
        return _allowances[holder][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Note that accounts cannot have allowance issued by their operators.
     */
    function approve(address spender, uint256 value) public override returns (bool) {
        address holder = _msgSender();
        _approve(holder, spender, value);
        return true;
    }

   /**
    * @dev See {IERC20-transferFrom}.
    *
    * Note that operator and allowance concepts are orthogonal: operators cannot
    * call `transferFrom` (unless they have allowance), and accounts with
    * allowance cannot call `operatorSend` (unless they are operators).
    *
    * Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.
    */
    function transferFrom(address holder, address recipient, uint256 amount) public override returns (bool) {
        require(recipient != address(0), "ERC777: transfer to the zero address");
        require(holder != address(0), "ERC777: transfer from the zero address");

        address spender = _msgSender();

        _callTokensToSend(spender, holder, recipient, amount, "", "");

        _move(spender, holder, recipient, amount, "", "");
        _approve(holder, spender, _allowances[holder][spender].sub(amount, "ERC777: transfer amount exceeds allowance"));

        _callTokensReceived(spender, holder, recipient, amount, "", "", false);

        return true;
    }

    /**
     * @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `operator`, `data` and `operatorData`.
     *
     * See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits {Minted} and {IERC20-Transfer} events.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - if `account` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function _mint(
        address account,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
    internal virtual
    {
        require(account != address(0), "ERC777: mint to the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, amount);

        // Update state variables
        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);

        _callTokensReceived(operator, address(0), account, amount, userData, operatorData, true);

        emit Minted(operator, account, amount, userData, operatorData);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Send tokens
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _send(
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
        internal
    {
        require(from != address(0), "ERC777: send from the zero address");
        require(to != address(0), "ERC777: send to the zero address");

        address operator = _msgSender();

        _callTokensToSend(operator, from, to, amount, userData, operatorData);

        _move(operator, from, to, amount, userData, operatorData);

        _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
    }

    /**
     * @dev Burn tokens
     * @param from address token holder address
     * @param amount uint256 amount of tokens to burn
     * @param data bytes extra information provided by the token holder
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _burn(
        address from,
        uint256 amount,
        bytes memory data,
        bytes memory operatorData
    )
        internal virtual
    {
        require(from != address(0), "ERC777: burn from the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, address(0), amount);

        _callTokensToSend(operator, from, address(0), amount, data, operatorData);

        // Update state variables
        _balances[from] = _balances[from].sub(amount, "ERC777: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);

        emit Burned(operator, from, amount, data, operatorData);
        emit Transfer(from, address(0), amount);
    }

    function _move(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
        private
    {
        _beforeTokenTransfer(operator, from, to, amount);

        _balances[from] = _balances[from].sub(amount, "ERC777: transfer amount exceeds balance");
        _balances[to] = _balances[to].add(amount);

        emit Sent(operator, from, to, amount, userData, operatorData);
        emit Transfer(from, to, amount);
    }

    function _approve(address holder, address spender, uint256 value) internal {
        // TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
        // currently unnecessary.
        //require(holder != address(0), "ERC777: approve from the zero address");
        require(spender != address(0), "ERC777: approve to the zero address");

        _allowances[holder][spender] = value;
        emit Approval(holder, spender, value);
    }

    /**
     * @dev Call from.tokensToSend() if the interface is registered
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     */
    function _callTokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData
    )
        private
    {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
        }
    }

    /**
     * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
     * tokensReceived() was not registered for the recipient
     * @param operator address operator requesting the transfer
     * @param from address token holder address
     * @param to address recipient address
     * @param amount uint256 amount of tokens to transfer
     * @param userData bytes extra information provided by the token holder (if any)
     * @param operatorData bytes extra information provided by the operator (if any)
     * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
     */
    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    )
        private
    {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes
     * calls to {send}, {transfer}, {operatorSend}, minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - when `from` is zero, `tokenId` will be minted for `to`.
     * - when `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address operator, address from, address to, uint256 tokenId) internal virtual { }
}

File 33 of 117: Escrow.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";
import "./Ownable.sol";
import "./Address.sol";

 /**
  * @title Escrow
  * @dev Base escrow contract, holds funds designated for a payee until they
  * withdraw them.
  *
  * Intended usage: This contract (and derived escrow contracts) should be a
  * standalone contract, that only interacts with the contract that instantiated
  * it. That way, it is guaranteed that all Ether will be handled according to
  * the `Escrow` rules, and there is no need to check for payable functions or
  * transfers in the inheritance tree. The contract that uses the escrow as its
  * payment method should be its owner, and provide public methods redirecting
  * to the escrow's deposit and withdraw.
  */
contract Escrow is Ownable {
    using SafeMath for uint256;
    using Address for address payable;

    event Deposited(address indexed payee, uint256 weiAmount);
    event Withdrawn(address indexed payee, uint256 weiAmount);

    mapping(address => uint256) private _deposits;

    function depositsOf(address payee) public view returns (uint256) {
        return _deposits[payee];
    }

    /**
     * @dev Stores the sent amount as credit to be withdrawn.
     * @param payee The destination address of the funds.
     */
    function deposit(address payee) public virtual payable onlyOwner {
        uint256 amount = msg.value;
        _deposits[payee] = _deposits[payee].add(amount);

        emit Deposited(payee, amount);
    }

    /**
     * @dev Withdraw accumulated balance for a payee, forwarding all gas to the
     * recipient.
     *
     * WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
     * Make sure you trust the recipient, or are either following the
     * checks-effects-interactions pattern or using {ReentrancyGuard}.
     *
     * @param payee The address whose funds will be withdrawn and transferred to.
     */
    function withdraw(address payable payee) public virtual onlyOwner {
        uint256 payment = _deposits[payee];

        _deposits[payee] = 0;

        payee.sendValue(payment);

        emit Withdrawn(payee, payment);
    }
}

File 34 of 117: ExpandedERC20.sol
pragma solidity ^0.6.0;

import "./ERC20.sol";
import "./MultiRole.sol";
import "./ExpandedIERC20.sol";


/**
 * @title An ERC20 with permissioned burning and minting. The contract deployer will initially
 * be the owner who is capable of adding new roles.
 */
contract ExpandedERC20 is ExpandedIERC20, ERC20, MultiRole {
    enum Roles {
        // Can set the minter and burner.
        Owner,
        // Addresses that can mint new tokens.
        Minter,
        // Addresses that can burn tokens that address owns.
        Burner
    }

    /**
     * @notice Constructs the ExpandedERC20.
     * @param _tokenName The name which describes the new token.
     * @param _tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.
     * @param _tokenDecimals The number of decimals to define token precision.
     */
    constructor(
        string memory _tokenName,
        string memory _tokenSymbol,
        uint8 _tokenDecimals
    ) public ERC20(_tokenName, _tokenSymbol) {
        _setupDecimals(_tokenDecimals);
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
        _createSharedRole(uint256(Roles.Minter), uint256(Roles.Owner), new address[](0));
        _createSharedRole(uint256(Roles.Burner), uint256(Roles.Owner), new address[](0));
    }

    /**
     * @dev Mints `value` tokens to `recipient`, returning true on success.
     * @param recipient address to mint to.
     * @param value amount of tokens to mint.
     * @return True if the mint succeeded, or False.
     */
    function mint(address recipient, uint256 value)
        external
        override
        onlyRoleHolder(uint256(Roles.Minter))
        returns (bool)
    {
        _mint(recipient, value);
        return true;
    }

    /**
     * @dev Burns `value` tokens owned by `msg.sender`.
     * @param value amount of tokens to burn.
     */
    function burn(uint256 value) external override onlyRoleHolder(uint256(Roles.Burner)) {
        _burn(msg.sender, value);
    }
}

File 35 of 117: ExpandedIERC20.sol
pragma solidity ^0.6.0;

import "./IERC20.sol";


/**
 * @title ERC20 interface that includes burn and mint methods.
 */
abstract contract ExpandedIERC20 is IERC20 {
    /**
     * @notice Burns a specific amount of the caller's tokens.
     * @dev Only burns the caller's tokens, so it is safe to leave this method permissionless.
     */
    function burn(uint256 value) external virtual;

    /**
     * @notice Mints tokens and adds them to the balance of the `to` address.
     * @dev This method should be permissioned to only allow designated parties to mint tokens.
     */
    function mint(address to, uint256 value) external virtual returns (bool);
}

File 36 of 117: ExpiringMultiParty.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./FixedPoint.sol";
import "./Liquidatable.sol";


contract ExpiringMultiParty is Liquidatable {
    constructor(ConstructorParams memory params) public Liquidatable(params) {}
}

File 37 of 117: ExpiringMultiPartyCreator.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./ContractCreator.sol";
import "./Testable.sol";
import "./AddressWhitelist.sol";
import "./ExpiringMultiParty.sol";


/**
 * @title Expiring Multi Party Contract creator.
 * @notice Factory contract to create and register new instances of expiring multiparty contracts.
 * Responsible for constraining the parameters used to construct a new EMP.
 */
contract ExpiringMultiPartyCreator is ContractCreator, Testable {
    using FixedPoint for FixedPoint.Unsigned;

    /****************************************
     *     EMP CREATOR DATA STRUCTURES      *
     ****************************************/

    struct Params {
        uint256 expirationTimestamp;
        address collateralAddress;
        bytes32 priceFeedIdentifier;
        string syntheticName;
        string syntheticSymbol;
        FixedPoint.Unsigned collateralRequirement;
        FixedPoint.Unsigned disputeBondPct;
        FixedPoint.Unsigned sponsorDisputeRewardPct;
        FixedPoint.Unsigned disputerDisputeRewardPct;
        FixedPoint.Unsigned minSponsorTokens;
        address timerAddress;
    }

    /**
     * @notice Deployment Configuration Constraints.
     * @dev: These constraints can evolve over time and are initially constrained to conservative values
     * in this first iteration of an EMP creator. Technically there is nothing in the ExpiringMultiParty
     * contract requiring these constraints. However, because "createExpiringMultiParty()" is intended to
     * be the only way to create valid financial contracts that are **registered** with the
     * DVM (via "_registerContract()"), we can enforce deployment configurations here.
     **/

    // - Whitelist allowed collateral currencies.
    // Note: before an instantiation of ExpiringMultipartyCreator is approved to register contracts, voters should
    // ensure that the ownership of this collateralTokenWhitelist has been renounced (so it is effectively
    // frozen). One could also set the owner to the address of the Governor contract, but voters may find that option
    // less preferable since it would force them to take a more active role in managing this financial contract
    // template.
    AddressWhitelist public collateralTokenWhitelist;
    // - Address of TokenFactory to pass into newly constructed ExpiringMultiParty contracts
    address public tokenFactoryAddress;
    // - Discretize expirations such that they must expire on the first of each month.
    uint256[17] public VALID_EXPIRATION_TIMESTAMPS = [
        1585699200, // 2020-04-01T00:00:00.000Z
        1588291200, // 2020-05-01T00:00:00.000Z
        1590969600, // 2020-06-01T00:00:00.000Z
        1593561600, // 2020-07-01T00:00:00.000Z
        1596240000, // 2020-08-01T00:00:00.000Z
        1598918400, // 2020-09-01T00:00:00.000Z
        1601510400, // 2020-10-01T00:00:00.000Z
        1604188800, // 2020-11-01T00:00:00.000Z
        1606780800, // 2020-12-01T00:00:00.000Z
        1609459200, // 2021-01-01T00:00:00.000Z
        1612137600, // 2021-02-01T00:00:00.000Z
        1614556800, // 2021-03-01T00:00:00.000Z
        1617235200, // 2021-04-01T00:00:00.000Z
        1619827200, // 2021-05-01T00:00:00.000Z
        1622505600, // 2021-06-01T00:00:00.000Z
        1625097600 // 2021-07-01T00:00:00.000Z
    ];
    // - Time for pending withdrawal to be disputed: 60 minutes. Lower liveness increases sponsor usability.
    // However, this parameter is a reflection of how long we expect it to take for liquidators to identify
    // that a sponsor is undercollateralized and acquire the tokens needed to liquidate them. This is also a
    // reflection of how long a malicious sponsor would need to maintain a lower-price manipulation to get
    // their withdrawal processed maliciously (if set too low, it’s quite easy for malicious sponsors to
    // request a withdrawal and spend gas to prevent other transactions from processing until the withdrawal
    //  gets approved). Ultimately, liveness is a friction to be minimized, but not critical to system function.
    uint256 public constant STRICT_WITHDRAWAL_LIVENESS = 3600;
    // - Time for liquidation to be disputed: 60 minutes. Similar reasoning to withdrawal liveness.
    // Lower liveness is more usable for liquidators. However, the parameter is a reflection of how
    // long we expect it to take disputers to notice bad liquidations. Malicious liquidators would
    // also need to attack the base chain for this long to prevent dispute transactions from processing.
    uint256 public constant STRICT_LIQUIDATION_LIVENESS = 3600;

    event CreatedExpiringMultiParty(address expiringMultiPartyAddress, address partyMemberAddress);

    /**
     * @notice Constructs the ExpiringMultiPartyCreator contract.
     * @param _finderAddress UMA protocol Finder used to discover other protocol contracts.
     * @param _collateralTokenWhitelist UMA protocol contract to track whitelisted collateral.
     * @param _tokenFactoryAddress ERC20 token factory used to deploy synthetic token instances.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        address _finderAddress,
        address _collateralTokenWhitelist,
        address _tokenFactoryAddress,
        address _timerAddress
    ) public ContractCreator(_finderAddress) Testable(_timerAddress) {
        collateralTokenWhitelist = AddressWhitelist(_collateralTokenWhitelist);
        tokenFactoryAddress = _tokenFactoryAddress;
    }

    /**
     * @notice Creates an instance of expiring multi party and registers it within the registry.
     * @dev caller is automatically registered as the first (and only) party member.
     * @param params is a `ConstructorParams` object from ExpiringMultiParty.
     * @return address of the deployed ExpiringMultiParty contract
     */
    function createExpiringMultiParty(Params memory params) public returns (address) {
        ExpiringMultiParty derivative = new ExpiringMultiParty(_convertParams(params));

        address[] memory parties = new address[](1);
        parties[0] = msg.sender;

        _registerContract(parties, address(derivative));

        emit CreatedExpiringMultiParty(address(derivative), msg.sender);

        return address(derivative);
    }

    /****************************************
     *          PRIVATE FUNCTIONS           *
     ****************************************/

    //  Returns if expiration timestamp is on hardcoded list.
    function _isValidTimestamp(uint256 timestamp) private view returns (bool) {
        for (uint256 i = 0; i < VALID_EXPIRATION_TIMESTAMPS.length; i++) {
            if (VALID_EXPIRATION_TIMESTAMPS[i] == timestamp) {
                return true;
            }
        }
        return false;
    }

    // Converts createExpiringMultiParty params to ExpiringMultiParty constructor params.
    function _convertParams(Params memory params)
        private
        view
        returns (ExpiringMultiParty.ConstructorParams memory constructorParams)
    {
        // Known from creator deployment.
        constructorParams.finderAddress = finderAddress;
        constructorParams.tokenFactoryAddress = tokenFactoryAddress;

        // Enforce configuration constrainments.
        require(_isValidTimestamp(params.expirationTimestamp));
        require(bytes(params.syntheticName).length != 0);
        require(bytes(params.syntheticSymbol).length != 0);
        constructorParams.withdrawalLiveness = STRICT_WITHDRAWAL_LIVENESS;
        constructorParams.liquidationLiveness = STRICT_LIQUIDATION_LIVENESS;
        require(collateralTokenWhitelist.isOnWhitelist(params.collateralAddress));

        // Input from function call.
        constructorParams.expirationTimestamp = params.expirationTimestamp;
        constructorParams.collateralAddress = params.collateralAddress;
        constructorParams.priceFeedIdentifier = params.priceFeedIdentifier;
        constructorParams.syntheticName = params.syntheticName;
        constructorParams.syntheticSymbol = params.syntheticSymbol;
        constructorParams.collateralRequirement = params.collateralRequirement;
        constructorParams.disputeBondPct = params.disputeBondPct;
        constructorParams.sponsorDisputeRewardPct = params.sponsorDisputeRewardPct;
        constructorParams.disputerDisputeRewardPct = params.disputerDisputeRewardPct;
        constructorParams.minSponsorTokens = params.minSponsorTokens;
        constructorParams.timerAddress = params.timerAddress;
    }
}

File 38 of 117: FeePayer.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./IERC20.sol";
import "./SafeERC20.sol";
import "./FixedPoint.sol";
import "./Testable.sol";
import "./StoreInterface.sol";
import "./FinderInterface.sol";
import "./Constants.sol";


/**
 * @title FeePayer contract.
 * @notice Provides fee payment functionality for the ExpiringMultiParty contract.
 * contract is abstract as each derived contract that inherits `FeePayer` must implement `pfc()`.
 */

abstract contract FeePayer is Testable {
    using SafeMath for uint256;
    using FixedPoint for FixedPoint.Unsigned;
    using SafeERC20 for IERC20;

    /****************************************
     *      FEE PAYER DATA STRUCTURES       *
     ****************************************/

    // The collateral currency used to back the positions in this contract.
    IERC20 public collateralCurrency;

    //  Finder contract used to look up addresses for UMA system contracts.
    FinderInterface public finder;

    // Tracks the last block time when the fees were paid.
    uint256 public lastPaymentTime;

    // Tracks the cumulative fees that have been paid by the contract for use by derived contracts.
    // The multiplier starts at 1, and is updated by computing cumulativeFeeMultiplier * (1 - effectiveFee).
    // Put another way, the cumulativeFeeMultiplier is (1 - effectiveFee1) * (1 - effectiveFee2) ...
    // For example:
    // The cumulativeFeeMultiplier should start at 1.
    // If a 1% fee is charged, the multiplier should update to .99.
    // If another 1% fee is charged, the multiplier should be 0.99^2 (0.9801).
    FixedPoint.Unsigned public cumulativeFeeMultiplier;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event RegularFeesPaid(uint256 indexed regularFee, uint256 indexed lateFee);
    event FinalFeesPaid(uint256 indexed amount);

    /****************************************
     *              MODIFIERS               *
     ****************************************/

    // modifier that calls payFees().
    modifier fees {
        payFees();
        _;
    }

    /**
     * @notice Constructs the FeePayer contract. Called by child contracts.
     * @param collateralAddress ERC20 token that is used as the underlying collateral for the synthetic.
     * @param finderAddress UMA protocol Finder used to discover other protocol contracts.
     * @param timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        address collateralAddress,
        address finderAddress,
        address timerAddress
    ) public Testable(timerAddress) {
        collateralCurrency = IERC20(collateralAddress);
        finder = FinderInterface(finderAddress);
        lastPaymentTime = getCurrentTime();
        cumulativeFeeMultiplier = FixedPoint.fromUnscaledUint(1);
    }

    /****************************************
     *        FEE PAYMENT FUNCTIONS         *
     ****************************************/

    /**
     * @notice Pays UMA DVM regular fees to the Store contract.
     * @dev These must be paid periodically for the life of the contract. If the contract has not paid its
     * regular fee in a week or mre then a late penalty is applied which is sent to the caller.
     * @return totalPaid The amount of collateral that the contract paid (sum of the amount paid to the Store and the caller).
     */
    function payFees() public returns (FixedPoint.Unsigned memory totalPaid) {
        StoreInterface store = _getStore();
        uint256 time = getCurrentTime();
        FixedPoint.Unsigned memory _pfc = pfc();

        // Exit early if there is no pfc (thus, no fees to be paid).
        if (_pfc.isEqual(0)) {
            return totalPaid;
        }

        (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty) = store.computeRegularFee(
            lastPaymentTime,
            time,
            _pfc
        );
        lastPaymentTime = time;

        if (regularFee.isGreaterThan(0)) {
            collateralCurrency.safeIncreaseAllowance(address(store), regularFee.rawValue);
            store.payOracleFeesErc20(address(collateralCurrency), regularFee);
        }

        if (latePenalty.isGreaterThan(0)) {
            collateralCurrency.safeTransfer(msg.sender, latePenalty.rawValue);
        }

        emit RegularFeesPaid(regularFee.rawValue, latePenalty.rawValue);

        totalPaid = regularFee.add(latePenalty);
        FixedPoint.Unsigned memory effectiveFee = totalPaid.divCeil(_pfc);
        cumulativeFeeMultiplier = cumulativeFeeMultiplier.mul(FixedPoint.fromUnscaledUint(1).sub(effectiveFee));
    }

    /**
     * @notice Pays UMA DVM final fees to the Store contract.
     * @dev This is a flat fee charged for each price request.
     * @param payer address of who is paying the fees.
     * @param amount the amount of collateral to send as the final fee.
     */
    function _payFinalFees(address payer, FixedPoint.Unsigned memory amount) internal {
        if (amount.isEqual(0)) {
            return;
        }

        if (payer != address(this)) {
            // If the payer is not the contract pull the collateral from the payer.
            collateralCurrency.safeTransferFrom(payer, address(this), amount.rawValue);
        } else {
            // If the payer is the contract, adjust the cumulativeFeeMultiplier to compensate.
            FixedPoint.Unsigned memory _pfc = pfc();

            // The final fee must be < pfc or the fee will be larger than 100%.
            require(_pfc.isGreaterThan(amount));

            // Add the adjustment.
            FixedPoint.Unsigned memory effectiveFee = amount.divCeil(pfc());
            cumulativeFeeMultiplier = cumulativeFeeMultiplier.mul(FixedPoint.fromUnscaledUint(1).sub(effectiveFee));
        }

        emit FinalFeesPaid(amount.rawValue);

        StoreInterface store = _getStore();
        collateralCurrency.safeIncreaseAllowance(address(store), amount.rawValue);
        store.payOracleFeesErc20(address(collateralCurrency), amount);
    }

    /**
     * @notice Gets the current profit from corruption for this contract in terms of the collateral currency.
     * @dev Derived contracts are expected to implement this function so the payFees()
     * method can correctly compute the owed regular fees.
     */
    function pfc() public virtual view returns (FixedPoint.Unsigned memory);

    /****************************************
     *         INTERNAL FUNCTIONS           *
     ****************************************/

    function _getStore() internal view returns (StoreInterface) {
        return StoreInterface(finder.getImplementationAddress(OracleInterfaces.Store));
    }

    function _computeFinalFees() internal returns (FixedPoint.Unsigned memory finalFees) {
        StoreInterface store = _getStore();
        return store.computeFinalFee(address(collateralCurrency));
    }

    // Returns the user's collateral minus any fees that have been subtracted since it was originally
    // deposited into the contract. Note: if the contract has paid fees since it was deployed, the raw
    // value should be larger than the returned value.
    function _getCollateral(FixedPoint.Unsigned memory rawCollateral)
        internal
        view
        returns (FixedPoint.Unsigned memory collateral)
    {
        return rawCollateral.mul(cumulativeFeeMultiplier);
    }

    // Converts a user-readable collateral value into a raw value that accounts for already-assessed
    // fees. If any fees have been taken from this contract in the past, then the raw value will be
    // larger than the user-readable value.
    function _convertCollateral(FixedPoint.Unsigned memory collateral)
        internal
        view
        returns (FixedPoint.Unsigned memory rawCollateral)
    {
        return collateral.div(cumulativeFeeMultiplier);
    }

    // Decrease rawCollateral by a fee-adjusted collateralToRemove amount. Fee adjustment scales up collateralToRemove
    // by dividing it by cumulativeFeeMutliplier. There is potential for this quotient to be floored, therefore rawCollateral
    // is decreased by less than expected. Because this method is usually called in conjunction with an actual removal of collateral
    // from this contract, return the fee-adjusted amount that the rawCollateral is decreased by so that the caller can
    // minimize error between collateral removed and rawCollateral debited.
    function _removeCollateral(FixedPoint.Unsigned storage rawCollateral, FixedPoint.Unsigned memory collateralToRemove)
        internal
        returns (FixedPoint.Unsigned memory removedCollateral)
    {
        FixedPoint.Unsigned memory initialBalance = _getCollateral(rawCollateral);
        FixedPoint.Unsigned memory adjustedCollateral = _convertCollateral(collateralToRemove);
        rawCollateral.rawValue = rawCollateral.sub(adjustedCollateral).rawValue;
        removedCollateral = initialBalance.sub(_getCollateral(rawCollateral));
    }

    // Increase rawCollateral by a fee-adjusted collateralToRemove amount. Fee adjustment scales up collateralToRemove
    // by dividing it by cumulativeFeeMutliplier. There is potential for this quotient to be floored, therefore rawCollateral
    // is increased by less than expected. Because this method is usually called in conjunction with an actual addition of collateral
    // to this contract, return the fee-adjusted amount that the rawCollateral is increased by so that the caller can
    // minimize error between collateral removed and rawCollateral credited.
    // @dev: This return value exists only for the sake of symmetry with `_removeCollateral`. We don't actually use it because
    // we are OK if more collateral is stored in the contract than is represented by `totalPositionCollateral`.
    function _addCollateral(FixedPoint.Unsigned storage rawCollateral, FixedPoint.Unsigned memory collateralToAdd)
        internal
        returns (FixedPoint.Unsigned memory addedCollateral)
    {
        FixedPoint.Unsigned memory initialBalance = _getCollateral(rawCollateral);
        FixedPoint.Unsigned memory adjustedCollateral = _convertCollateral(collateralToAdd);
        rawCollateral.rawValue = rawCollateral.add(adjustedCollateral).rawValue;
        addedCollateral = _getCollateral(rawCollateral).sub(initialBalance);
    }
}

File 39 of 117: FinancialContractsAdmin.sol
pragma solidity ^0.6.0;

import "./AdministrateeInterface.sol";
import "./Ownable.sol";


/**
 * @title Admin for financial contracts in the UMA system.
 * @dev Allows appropriately permissioned admin roles to interact with financial contracts.
 */
contract FinancialContractsAdmin is Ownable {
    /**
     * @notice Calls emergency shutdown on the provided financial contract.
     * @param financialContract address of the FinancialContract to be shut down.
     */
    function callEmergencyShutdown(address financialContract) external onlyOwner {
        AdministrateeInterface administratee = AdministrateeInterface(financialContract);
        administratee.emergencyShutdown();
    }

    /**
     * @notice Calls remargin on the provided financial contract.
     * @param financialContract address of the FinancialContract to be remargined.
     */
    function callRemargin(address financialContract) external onlyOwner {
        AdministrateeInterface administratee = AdministrateeInterface(financialContract);
        administratee.remargin();
    }
}

File 40 of 117: Finder.sol
pragma solidity ^0.6.0;

import "./Ownable.sol";
import "./FinderInterface.sol";


/**
 * @title Provides addresses of the live contracts implementing certain interfaces.
 * @dev Examples of interfaces with implementations that Finder locates are the Oracle and Store interfaces.
 */
contract Finder is FinderInterface, Ownable {
    mapping(bytes32 => address) public interfacesImplemented;

    event InterfaceImplementationChanged(bytes32 indexed interfaceName, address indexed newImplementationAddress);

    /**
     * @notice Updates the address of the contract that implements `interfaceName`.
     * @param interfaceName bytes32 of the interface name that is either changed or registered.
     * @param implementationAddress address of the implementation contract.
     */
    function changeImplementationAddress(bytes32 interfaceName, address implementationAddress)
        external
        override
        onlyOwner
    {
        interfacesImplemented[interfaceName] = implementationAddress;

        emit InterfaceImplementationChanged(interfaceName, implementationAddress);
    }

    /**
     * @notice Gets the address of the contract that implements the given `interfaceName`.
     * @param interfaceName queried interface.
     * @return implementationAddress address of the defined interface.
     */
    function getImplementationAddress(bytes32 interfaceName) external override view returns (address) {
        address implementationAddress = interfacesImplemented[interfaceName];
        require(implementationAddress != address(0x0), "Implementation not found");
        return implementationAddress;
    }
}

File 41 of 117: FinderInterface.sol
pragma solidity ^0.6.0;


/**
 * @title Provides addresses of the live contracts implementing certain interfaces.
 * @dev Examples are the Oracle or Store interfaces.
 */
interface FinderInterface {
    /**
     * @notice Updates the address of the contract that implements `interfaceName`.
     * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
     * @param implementationAddress address of the deployed contract that implements the interface.
     */
    function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;

    /**
     * @notice Gets the address of the contract that implements the given `interfaceName`.
     * @param interfaceName queried interface.
     * @return implementationAddress address of the deployed contract that implements the interface.
     */
    function getImplementationAddress(bytes32 interfaceName) external view returns (address);
}

File 42 of 117: FixedPoint.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";


/**
 * @title Library for fixed point arithmetic on uints
 */
library FixedPoint {
    using SafeMath for uint256;

    // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
    // Can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.
    uint256 private constant FP_SCALING_FACTOR = 10**18;

    struct Unsigned {
        uint256 rawValue;
    }

    /**
     * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5**18`.
     * @param a uint to convert into a FixedPoint.
     * @return the converted FixedPoint.
     */
    function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {
        return Unsigned(a.mul(FP_SCALING_FACTOR));
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue == fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if equal, or False.
     */
    function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue == b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue > fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a > b`, or False.
     */
    function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue > b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue >= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is greater than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a >= b`, or False.
     */
    function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue >= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a < b`, or False.
     */
    function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue < fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a < b`, or False.
     */
    function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue < b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
        return a.rawValue <= b.rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
        return a.rawValue <= fromUnscaledUint(b).rawValue;
    }

    /**
     * @notice Whether `a` is less than or equal to `b`.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return True if `a <= b`, or False.
     */
    function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
        return fromUnscaledUint(a).rawValue <= b.rawValue;
    }

    /**
     * @notice The minimum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the minimum of `a` and `b`.
     */
    function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue < b.rawValue ? a : b;
    }

    /**
     * @notice The maximum of `a` and `b`.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the maximum of `a` and `b`.
     */
    function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return a.rawValue > b.rawValue ? a : b;
    }

    /**
     * @notice Adds two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.add(b.rawValue));
    }

    /**
     * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the sum of `a` and `b`.
     */
    function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return add(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts two `Unsigned`s, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.sub(b.rawValue));
    }

    /**
     * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the difference of `a` and `b`.
     */
    function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return sub(a, fromUnscaledUint(b));
    }

    /**
     * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.
     * @param a a uint256.
     * @param b a FixedPoint.
     * @return the difference of `a` and `b`.
     */
    function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return sub(fromUnscaledUint(a), b);
    }

    /**
     * @notice Multiplies two `Unsigned`s, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
        // stored internally as a uint256 ~10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
        // would round to 3, but this computation produces the result 2.
        // No need to use SafeMath because FP_SCALING_FACTOR != 0.
        return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.
     * @dev This will "floor" the product.
     * @param a a FixedPoint.
     * @param b a uint256.
     * @return the product of `a` and `b`.
     */
    function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Multiplies two `Unsigned`s and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 mulRaw = a.rawValue.mul(b.rawValue);
        uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;
        uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);
        if (mod != 0) {
            return Unsigned(mulFloor.add(1));
        } else {
            return Unsigned(mulFloor);
        }
    }

    /**
     * @notice Multiplies an `Unsigned` and an unscaled uint256 and "ceil's" the product, reverting on overflow.
     * @param a a FixedPoint.
     * @param b a FixedPoint.
     * @return the product of `a` and `b`.
     */
    function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Since b is an int, there is no risk of truncation and we can just mul it normally
        return Unsigned(a.rawValue.mul(b));
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        // There are two caveats with this computation:
        // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
        // 10^41 is stored internally as a uint256 10^59.
        // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
        // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
        return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        return Unsigned(a.rawValue.div(b));
    }

    /**
     * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.
     * @dev This will "floor" the quotient.
     * @param a a uint256 numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
        return div(fromUnscaledUint(a), b);
    }

    /**
     * @notice Divides one `Unsigned` by an `Unsigned` and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a FixedPoint denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
        uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);
        uint256 divFloor = aScaled.div(b.rawValue);
        uint256 mod = aScaled.mod(b.rawValue);
        if (mod != 0) {
            return Unsigned(divFloor.add(1));
        } else {
            return Unsigned(divFloor);
        }
    }

    /**
     * @notice Divides one `Unsigned` by an unscaled uint256 and "ceil's" the quotient, reverting on overflow or division by 0.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return the quotient of `a` divided by `b`.
     */
    function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
        // Because it is possible that a quotient gets truncated, we can't just call "Unsigned(a.rawValue.div(b))"
        // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.
        // This creates the possibility of overflow if b is very large.
        return divCeil(a, fromUnscaledUint(b));
    }

    /**
     * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
     * @dev This will "floor" the result.
     * @param a a FixedPoint numerator.
     * @param b a uint256 denominator.
     * @return output is `a` to the power of `b`.
     */
    function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {
        output = fromUnscaledUint(1);
        for (uint256 i = 0; i < b; i = i.add(1)) {
            output = mul(output, a);
        }
    }
}

File 43 of 117: FixedPointTest.sol
pragma solidity ^0.6.0;

import "./FixedPoint.sol";


// Wraps the FixedPoint library for testing purposes.
contract FixedPointTest {
    using FixedPoint for FixedPoint.Unsigned;
    using FixedPoint for uint256;
    using SafeMath for uint256;

    function wrapFromUnscaledUint(uint256 a) external pure returns (uint256) {
        return FixedPoint.fromUnscaledUint(a).rawValue;
    }

    function wrapIsEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isEqual(FixedPoint.Unsigned(b));
    }

    function wrapMixedIsEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isEqual(b);
    }

    function wrapIsGreaterThan(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isGreaterThan(FixedPoint.Unsigned(b));
    }

    function wrapIsGreaterThanOrEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isGreaterThanOrEqual(FixedPoint.Unsigned(b));
    }

    function wrapMixedIsGreaterThan(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isGreaterThan(b);
    }

    function wrapMixedIsGreaterThanOrEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isGreaterThanOrEqual(b);
    }

    function wrapMixedIsGreaterThanOpposite(uint256 a, uint256 b) external pure returns (bool) {
        return a.isGreaterThan(FixedPoint.Unsigned(b));
    }

    function wrapMixedIsGreaterThanOrEqualOpposite(uint256 a, uint256 b) external pure returns (bool) {
        return a.isGreaterThanOrEqual(FixedPoint.Unsigned(b));
    }

    function wrapIsLessThan(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isLessThan(FixedPoint.Unsigned(b));
    }

    function wrapIsLessThanOrEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isLessThanOrEqual(FixedPoint.Unsigned(b));
    }

    function wrapMixedIsLessThan(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isLessThan(b);
    }

    function wrapMixedIsLessThanOrEqual(uint256 a, uint256 b) external pure returns (bool) {
        return FixedPoint.Unsigned(a).isLessThanOrEqual(b);
    }

    function wrapMixedIsLessThanOpposite(uint256 a, uint256 b) external pure returns (bool) {
        return a.isLessThan(FixedPoint.Unsigned(b));
    }

    function wrapMixedIsLessThanOrEqualOpposite(uint256 a, uint256 b) external pure returns (bool) {
        return a.isLessThanOrEqual(FixedPoint.Unsigned(b));
    }

    function wrapMin(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).min(FixedPoint.Unsigned(b)).rawValue;
    }

    function wrapMax(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).max(FixedPoint.Unsigned(b)).rawValue;
    }

    function wrapAdd(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).add(FixedPoint.Unsigned(b)).rawValue;
    }

    // The first uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedAdd(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).add(b).rawValue;
    }

    function wrapSub(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).sub(FixedPoint.Unsigned(b)).rawValue;
    }

    // The first uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedSub(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).sub(b).rawValue;
    }

    // The second uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedSubOpposite(uint256 a, uint256 b) external pure returns (uint256) {
        return a.sub(FixedPoint.Unsigned(b)).rawValue;
    }

    function wrapMul(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).mul(FixedPoint.Unsigned(b)).rawValue;
    }

    function wrapMulCeil(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).mulCeil(FixedPoint.Unsigned(b)).rawValue;
    }

    // The first uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedMul(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).mul(b).rawValue;
    }

    function wrapMixedMulCeil(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).mulCeil(b).rawValue;
    }

    function wrapDiv(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).div(FixedPoint.Unsigned(b)).rawValue;
    }

    function wrapDivCeil(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).divCeil(FixedPoint.Unsigned(b)).rawValue;
    }

    // The first uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedDiv(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).div(b).rawValue;
    }

    function wrapMixedDivCeil(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).divCeil(b).rawValue;
    }

    // The second uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapMixedDivOpposite(uint256 a, uint256 b) external pure returns (uint256) {
        return a.div(FixedPoint.Unsigned(b)).rawValue;
    }

    // The first uint256 is interpreted with a scaling factor and is converted to an `Unsigned` directly.
    function wrapPow(uint256 a, uint256 b) external pure returns (uint256) {
        return FixedPoint.Unsigned(a).pow(b).rawValue;
    }
}

File 44 of 117: Governor.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./MultiRole.sol";
import "./FixedPoint.sol";
import "./Testable.sol";
import "./FinderInterface.sol";
import "./IdentifierWhitelistInterface.sol";
import "./OracleInterface.sol";
import "./Constants.sol";

import "./SafeMath.sol";
import "./Address.sol";


/**
 * @title Takes proposals for certain governance actions and allows UMA token holders to vote on them.
 */
contract Governor is MultiRole, Testable {
    using SafeMath for uint256;
    using Address for address;

    /****************************************
     *     INTERNAL VARIABLES AND STORAGE   *
     ****************************************/

    enum Roles {
        Owner, // Can set the proposer.
        Proposer // Address that can make proposals.
    }

    struct Transaction {
        address to;
        uint256 value;
        bytes data;
    }

    struct Proposal {
        Transaction[] transactions;
        uint256 requestTime;
    }

    FinderInterface private finder;
    Proposal[] public proposals;

    /****************************************
     *                EVENTS                *
     ****************************************/

    // Emitted when a new proposal is created.
    event NewProposal(uint256 indexed id, Transaction[] transactions);

    // Emitted when an existing proposal is executed.
    event ProposalExecuted(uint256 indexed id, uint256 transactionIndex);

    /**
     * @notice Construct the Governor contract.
     * @param _finderAddress keeps track of all contracts within the system based on their interfaceName.
     * @param _startingId the initial proposal id that the contract will begin incrementing from.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        address _finderAddress,
        uint256 _startingId,
        address _timerAddress
    ) public Testable(_timerAddress) {
        finder = FinderInterface(_finderAddress);
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
        _createExclusiveRole(uint256(Roles.Proposer), uint256(Roles.Owner), msg.sender);

        // Ensure the startingId is not set unreasonably high to avoid it being set such that new proposals overwrite
        // other storage slots in the contract.
        uint256 maxStartingId = 10**18;
        require(_startingId <= maxStartingId, "Cannot set startingId larger than 10^18");

        // This just sets the initial length of the array to the startingId since modifying length directly has been
        // disallowed in solidity 0.6.
        assembly {
            sstore(proposals_slot, _startingId)
        }
    }

    /****************************************
     *          PROPOSAL ACTIONS            *
     ****************************************/

    /**
     * @notice Proposes a new governance action. Can only be called by the holder of the Proposer role.
     * @param transactions list of transactions that are being proposed.
     * @dev You can create the data portion of each transaction by doing the following:
     * ```
     * const truffleContractInstance = await TruffleContract.deployed()
     * const data = truffleContractInstance.methods.methodToCall(arg1, arg2).encodeABI()
     * ```
     * Note: this method must be public because of a solidity limitation that
     * disallows structs arrays to be passed to external functions.
     */
    function propose(Transaction[] memory transactions) public onlyRoleHolder(uint256(Roles.Proposer)) {
        uint256 id = proposals.length;
        uint256 time = getCurrentTime();

        // Note: doing all of this array manipulation manually is necessary because directly setting an array of
        // structs in storage to an an array of structs in memory is currently not implemented in solidity :/.

        // Add a zero-initialized element to the proposals array.
        proposals.push();

        // Initialize the new proposal.
        Proposal storage proposal = proposals[id];
        proposal.requestTime = time;

        // Initialize the transaction array.
        for (uint256 i = 0; i < transactions.length; i++) {
            require(transactions[i].to != address(0), "The `to` address cannot be 0x0");
            // If the transaction has any data with it the recipient must be a contract, not an EOA.
            if (transactions[i].data.length > 0) {
                require(transactions[i].to.isContract(), "EOA can't accept tx with data");
            }
            proposal.transactions.push(transactions[i]);
        }

        bytes32 identifier = _constructIdentifier(id);

        // Request a vote on this proposal in the DVM.
        OracleInterface oracle = _getOracle();
        IdentifierWhitelistInterface supportedIdentifiers = _getIdentifierWhitelist();
        supportedIdentifiers.addSupportedIdentifier(identifier);

        oracle.requestPrice(identifier, time);
        supportedIdentifiers.removeSupportedIdentifier(identifier);

        emit NewProposal(id, transactions);
    }

    /**
     * @notice Executes a proposed governance action that has been approved by voters.
     * @dev This can be called by any address. Caller is expected to send enough ETH to execute payable transactions.
     * @param id unique id for the executed proposal.
     * @param transactionIndex unique transaction index for the executed proposal.
     */
    function executeProposal(uint256 id, uint256 transactionIndex) external payable {
        Proposal storage proposal = proposals[id];
        int256 price = _getOracle().getPrice(_constructIdentifier(id), proposal.requestTime);

        Transaction memory transaction = proposal.transactions[transactionIndex];

        require(
            transactionIndex == 0 || proposal.transactions[transactionIndex.sub(1)].to == address(0),
            "Previous tx not yet executed"
        );
        require(transaction.to != address(0), "Tx already executed");
        require(price != 0, "Proposal was rejected");
        require(msg.value == transaction.value, "Must send exact amount of ETH");

        // Delete the transaction before execution to avoid any potential re-entrancy issues.
        delete proposal.transactions[transactionIndex];

        require(_executeCall(transaction.to, transaction.value, transaction.data), "Tx execution failed");

        emit ProposalExecuted(id, transactionIndex);
    }

    /****************************************
     *       GOVERNOR STATE GETTERS         *
     ****************************************/

    /**
     * @notice Gets the total number of proposals (includes executed and non-executed).
     * @return uint256 representing the current number of proposals.
     */
    function numProposals() external view returns (uint256) {
        return proposals.length;
    }

    /**
     * @notice Gets the proposal data for a particular id.
     * @dev after a proposal is executed, its data will be zeroed out, except for the request time.
     * @param id uniquely identify the identity of the proposal.
     * @return proposal struct containing transactions[] and requestTime.
     */
    function getProposal(uint256 id) external view returns (Proposal memory) {
        return proposals[id];
    }

    /****************************************
     *      PRIVATE GETTERS AND FUNCTIONS   *
     ****************************************/

    function _executeCall(
        address to,
        uint256 value,
        bytes memory data
    ) private returns (bool) {
        // Mostly copied from:
        // solhint-disable-next-line max-line-length
        // https://github.com/gnosis/safe-contracts/blob/59cfdaebcd8b87a0a32f87b50fead092c10d3a05/contracts/base/Executor.sol#L23-L31
        // solhint-disable-next-line no-inline-assembly

        bool success;
        assembly {
            let inputData := add(data, 0x20)
            let inputDataSize := mload(data)
            success := call(gas(), to, value, inputData, inputDataSize, 0, 0)
        }
        return success;
    }

    function _getOracle() private view returns (OracleInterface) {
        return OracleInterface(finder.getImplementationAddress(OracleInterfaces.Oracle));
    }

    function _getIdentifierWhitelist() private view returns (IdentifierWhitelistInterface supportedIdentifiers) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }

    // Returns a UTF-8 identifier representing a particular admin proposal.
    // The identifier is of the form "Admin n", where n is the proposal id provided.
    function _constructIdentifier(uint256 id) internal pure returns (bytes32) {
        bytes32 bytesId = _uintToUtf8(id);
        return _addPrefix(bytesId, "Admin ", 6);
    }

    // This method converts the integer `v` into a base-10, UTF-8 representation stored in a `bytes32` type.
    // If the input cannot be represented by 32 base-10 digits, it returns only the highest 32 digits.
    // This method is based off of this code: https://ethereum.stackexchange.com/a/6613/47801.
    function _uintToUtf8(uint256 v) internal pure returns (bytes32) {
        bytes32 ret;
        if (v == 0) {
            // Handle 0 case explicitly.
            ret = "0";
        } else {
            // Constants.
            uint256 bitsPerByte = 8;
            uint256 base = 10; // Note: the output should be base-10. The below implementation will not work for bases > 10.
            uint256 utf8NumberOffset = 48;
            while (v > 0) {
                // Downshift the entire bytes32 to allow the new digit to be added at the "front" of the bytes32, which
                // translates to the beginning of the UTF-8 representation.
                ret = ret >> bitsPerByte;

                // Separate the last digit that remains in v by modding by the base of desired output representation.
                uint256 leastSignificantDigit = v % base;

                // Digits 0-9 are represented by 48-57 in UTF-8, so an offset must be added to create the character.
                bytes32 utf8Digit = bytes32(leastSignificantDigit + utf8NumberOffset);

                // The top bit of ret has already been cleared to make room for the new digit.
                // Upshift by 31 bytes to put it in position, and OR it with ret to leave the other characters untouched.
                ret |= utf8Digit << (31 * bitsPerByte);

                // Divide v by the base to remove the digit that was just added.
                v /= base;
            }
        }
        return ret;
    }

    // This method takes two UTF-8 strings represented as bytes32 and outputs one as a prefixed by the other.
    // `input` is the UTF-8 that should have the prefix prepended.
    // `prefix` is the UTF-8 that should be prepended onto input.
    // `prefixLength` is number of UTF-8 characters represented by `prefix`.
    // Notes:
    // 1. If the resulting UTF-8 is larger than 32 characters, then only the first 32 characters will be represented
    //    by the bytes32 output.
    // 2. If `prefix` has more characters than `prefixLength`, the function will produce an invalid result.
    function _addPrefix(
        bytes32 input,
        bytes32 prefix,
        uint256 prefixLength
    ) internal pure returns (bytes32) {
        // Downshift `input` to open space at the "front" of the bytes32
        bytes32 shiftedInput = input >> (prefixLength * 8);
        return shiftedInput | prefix;
    }
}

File 45 of 117: GovernorTest.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./Governor.sol";


// GovernorTest exposes internal methods in the Governor for testing.
contract GovernorTest is Governor {
    constructor(address _timerAddress) public Governor(address(0), 0, _timerAddress) {}

    function addPrefix(
        bytes32 input,
        bytes32 prefix,
        uint256 prefixLength
    ) external pure returns (bytes32) {
        return _addPrefix(input, prefix, prefixLength);
    }

    function uintToUtf8(uint256 v) external pure returns (bytes32 ret) {
        return _uintToUtf8(v);
    }

    function constructIdentifier(uint256 id) external pure returns (bytes32 identifier) {
        return _constructIdentifier(id);
    }
}

File 46 of 117: GSNRecipient.sol
pragma solidity ^0.6.0;

import "./IRelayRecipient.sol";
import "./IRelayHub.sol";
import "./Context.sol";

/**
 * @dev Base GSN recipient contract: includes the {IRelayRecipient} interface
 * and enables GSN support on all contracts in the inheritance tree.
 *
 * TIP: This contract is abstract. The functions {IRelayRecipient-acceptRelayedCall},
 *  {_preRelayedCall}, and {_postRelayedCall} are not implemented and must be
 * provided by derived contracts. See the
 * xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategies] for more
 * information on how to use the pre-built {GSNRecipientSignature} and
 * {GSNRecipientERC20Fee}, or how to write your own.
 */
abstract contract GSNRecipient is IRelayRecipient, Context {
    // Default RelayHub address, deployed on mainnet and all testnets at the same address
    address private _relayHub = 0xD216153c06E857cD7f72665E0aF1d7D82172F494;

    uint256 constant private _RELAYED_CALL_ACCEPTED = 0;
    uint256 constant private _RELAYED_CALL_REJECTED = 11;

    // How much gas is forwarded to postRelayedCall
    uint256 constant internal _POST_RELAYED_CALL_MAX_GAS = 100000;

    /**
     * @dev Emitted when a contract changes its {IRelayHub} contract to a new one.
     */
    event RelayHubChanged(address indexed oldRelayHub, address indexed newRelayHub);

    /**
     * @dev Returns the address of the {IRelayHub} contract for this recipient.
     */
    function getHubAddr() public view override returns (address) {
        return _relayHub;
    }

    /**
     * @dev Switches to a new {IRelayHub} instance. This method is added for future-proofing: there's no reason to not
     * use the default instance.
     *
     * IMPORTANT: After upgrading, the {GSNRecipient} will no longer be able to receive relayed calls from the old
     * {IRelayHub} instance. Additionally, all funds should be previously withdrawn via {_withdrawDeposits}.
     */
    function _upgradeRelayHub(address newRelayHub) internal virtual {
        address currentRelayHub = _relayHub;
        require(newRelayHub != address(0), "GSNRecipient: new RelayHub is the zero address");
        require(newRelayHub != currentRelayHub, "GSNRecipient: new RelayHub is the current one");

        emit RelayHubChanged(currentRelayHub, newRelayHub);

        _relayHub = newRelayHub;
    }

    /**
     * @dev Returns the version string of the {IRelayHub} for which this recipient implementation was built. If
     * {_upgradeRelayHub} is used, the new {IRelayHub} instance should be compatible with this version.
     */
    // This function is view for future-proofing, it may require reading from
    // storage in the future.
    function relayHubVersion() public view returns (string memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return "1.0.0";
    }

    /**
     * @dev Withdraws the recipient's deposits in `RelayHub`.
     *
     * Derived contracts should expose this in an external interface with proper access control.
     */
    function _withdrawDeposits(uint256 amount, address payable payee) internal virtual {
        IRelayHub(_relayHub).withdraw(amount, payee);
    }

    // Overrides for Context's functions: when called from RelayHub, sender and
    // data require some pre-processing: the actual sender is stored at the end
    // of the call data, which in turns means it needs to be removed from it
    // when handling said data.

    /**
     * @dev Replacement for msg.sender. Returns the actual sender of a transaction: msg.sender for regular transactions,
     * and the end-user for GSN relayed calls (where msg.sender is actually `RelayHub`).
     *
     * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
     */
    function _msgSender() internal view virtual override returns (address payable) {
        if (msg.sender != _relayHub) {
            return msg.sender;
        } else {
            return _getRelayedCallSender();
        }
    }

    /**
     * @dev Replacement for msg.data. Returns the actual calldata of a transaction: msg.data for regular transactions,
     * and a reduced version for GSN relayed calls (where msg.data contains additional information).
     *
     * IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.data`, and use {_msgData} instead.
     */
    function _msgData() internal view virtual override returns (bytes memory) {
        if (msg.sender != _relayHub) {
            return msg.data;
        } else {
            return _getRelayedCallData();
        }
    }

    // Base implementations for pre and post relayedCall: only RelayHub can invoke them, and data is forwarded to the
    // internal hook.

    /**
     * @dev See `IRelayRecipient.preRelayedCall`.
     *
     * This function should not be overriden directly, use `_preRelayedCall` instead.
     *
     * * Requirements:
     *
     * - the caller must be the `RelayHub` contract.
     */
    function preRelayedCall(bytes memory context) public virtual override returns (bytes32) {
        require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
        return _preRelayedCall(context);
    }

    /**
     * @dev See `IRelayRecipient.preRelayedCall`.
     *
     * Called by `GSNRecipient.preRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts
     * must implement this function with any relayed-call preprocessing they may wish to do.
     *
     */
    function _preRelayedCall(bytes memory context) internal virtual returns (bytes32);

    /**
     * @dev See `IRelayRecipient.postRelayedCall`.
     *
     * This function should not be overriden directly, use `_postRelayedCall` instead.
     *
     * * Requirements:
     *
     * - the caller must be the `RelayHub` contract.
     */
    function postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) public virtual override {
        require(msg.sender == getHubAddr(), "GSNRecipient: caller is not RelayHub");
        _postRelayedCall(context, success, actualCharge, preRetVal);
    }

    /**
     * @dev See `IRelayRecipient.postRelayedCall`.
     *
     * Called by `GSNRecipient.postRelayedCall`, which asserts the caller is the `RelayHub` contract. Derived contracts
     * must implement this function with any relayed-call postprocessing they may wish to do.
     *
     */
    function _postRelayedCall(bytes memory context, bool success, uint256 actualCharge, bytes32 preRetVal) internal virtual;

    /**
     * @dev Return this in acceptRelayedCall to proceed with the execution of a relayed call. Note that this contract
     * will be charged a fee by RelayHub
     */
    function _approveRelayedCall() internal pure returns (uint256, bytes memory) {
        return _approveRelayedCall("");
    }

    /**
     * @dev See `GSNRecipient._approveRelayedCall`.
     *
     * This overload forwards `context` to _preRelayedCall and _postRelayedCall.
     */
    function _approveRelayedCall(bytes memory context) internal pure returns (uint256, bytes memory) {
        return (_RELAYED_CALL_ACCEPTED, context);
    }

    /**
     * @dev Return this in acceptRelayedCall to impede execution of a relayed call. No fees will be charged.
     */
    function _rejectRelayedCall(uint256 errorCode) internal pure returns (uint256, bytes memory) {
        return (_RELAYED_CALL_REJECTED + errorCode, "");
    }

    /*
     * @dev Calculates how much RelayHub will charge a recipient for using `gas` at a `gasPrice`, given a relayer's
     * `serviceFee`.
     */
    function _computeCharge(uint256 gas, uint256 gasPrice, uint256 serviceFee) internal pure returns (uint256) {
        // The fee is expressed as a percentage. E.g. a value of 40 stands for a 40% fee, so the recipient will be
        // charged for 1.4 times the spent amount.
        return (gas * gasPrice * (100 + serviceFee)) / 100;
    }

    function _getRelayedCallSender() private pure returns (address payable result) {
        // We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array
        // is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing
        // so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would
        // require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20
        // bytes. This can always be done due to the 32-byte prefix.

        // The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the
        // easiest/most-efficient way to perform this operation.

        // These fields are not accessible from assembly
        bytes memory array = msg.data;
        uint256 index = msg.data.length;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
            result := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
        return result;
    }

    function _getRelayedCallData() private pure returns (bytes memory) {
        // RelayHub appends the sender address at the end of the calldata, so in order to retrieve the actual msg.data,
        // we must strip the last 20 bytes (length of an address type) from it.

        uint256 actualDataLength = msg.data.length - 20;
        bytes memory actualData = new bytes(actualDataLength);

        for (uint256 i = 0; i < actualDataLength; ++i) {
            actualData[i] = msg.data[i];
        }

        return actualData;
    }
}

File 47 of 117: GSNRecipientERC20Fee.sol
pragma solidity ^0.6.0;

import "./GSNRecipient.sol";
import "./SafeMath.sol";
import "./Ownable.sol";
import "./SafeERC20.sol";
import "./ERC20.sol";

/**
 * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that charges transaction fees in a special purpose ERC20
 * token, which we refer to as the gas payment token. The amount charged is exactly the amount of Ether charged to the
 * recipient. This means that the token is essentially pegged to the value of Ether.
 *
 * The distribution strategy of the gas payment token to users is not defined by this contract. It's a mintable token
 * whose only minter is the recipient, so the strategy must be implemented in a derived contract, making use of the
 * internal {_mint} function.
 */
contract GSNRecipientERC20Fee is GSNRecipient {
    using SafeERC20 for __unstable__ERC20Owned;
    using SafeMath for uint256;

    enum GSNRecipientERC20FeeErrorCodes {
        INSUFFICIENT_BALANCE
    }

    __unstable__ERC20Owned private _token;

    /**
     * @dev The arguments to the constructor are the details that the gas payment token will have: `name` and `symbol`. `decimals` is hard-coded to 18.
     */
    constructor(string memory name, string memory symbol) public {
        _token = new __unstable__ERC20Owned(name, symbol);
    }

    /**
     * @dev Returns the gas payment token.
     */
    function token() public view returns (IERC20) {
        return IERC20(_token);
    }

    /**
     * @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
     */
    function _mint(address account, uint256 amount) internal virtual {
        _token.mint(account, amount);
    }

    /**
     * @dev Ensures that only users with enough gas payment token balance can have transactions relayed through the GSN.
     */
    function acceptRelayedCall(
        address,
        address from,
        bytes memory,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256,
        uint256,
        bytes memory,
        uint256 maxPossibleCharge
    )
        public
        view
        virtual
        override
        returns (uint256, bytes memory)
    {
        if (_token.balanceOf(from) < maxPossibleCharge) {
            return _rejectRelayedCall(uint256(GSNRecipientERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
        }

        return _approveRelayedCall(abi.encode(from, maxPossibleCharge, transactionFee, gasPrice));
    }

    /**
     * @dev Implements the precharge to the user. The maximum possible charge (depending on gas limit, gas price, and
     * fee) will be deducted from the user balance of gas payment token. Note that this is an overestimation of the
     * actual charge, necessary because we cannot predict how much gas the execution will actually need. The remainder
     * is returned to the user in {_postRelayedCall}.
     */
    function _preRelayedCall(bytes memory context) internal virtual override returns (bytes32) {
        (address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));

        // The maximum token charge is pre-charged from the user
        _token.safeTransferFrom(from, address(this), maxPossibleCharge);
    }

    /**
     * @dev Returns to the user the extra amount that was previously charged, once the actual execution cost is known.
     */
    function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal virtual override {
        (address from, uint256 maxPossibleCharge, uint256 transactionFee, uint256 gasPrice) =
            abi.decode(context, (address, uint256, uint256, uint256));

        // actualCharge is an _estimated_ charge, which assumes postRelayedCall will use all available gas.
        // This implementation's gas cost can be roughly estimated as 10k gas, for the two SSTORE operations in an
        // ERC20 transfer.
        uint256 overestimation = _computeCharge(_POST_RELAYED_CALL_MAX_GAS.sub(10000), gasPrice, transactionFee);
        actualCharge = actualCharge.sub(overestimation);

        // After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
        _token.safeTransfer(from, maxPossibleCharge.sub(actualCharge));
    }
}

/**
 * @title __unstable__ERC20Owned
 * @dev An ERC20 token owned by another contract, which has minting permissions and can use transferFrom to receive
 * anyone's tokens. This contract is an internal helper for GSNRecipientERC20Fee, and should not be used
 * outside of this context.
 */
// solhint-disable-next-line contract-name-camelcase
contract __unstable__ERC20Owned is ERC20, Ownable {
    uint256 private constant _UINT256_MAX = 2**256 - 1;

    constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }

    // The owner (GSNRecipientERC20Fee) can mint tokens
    function mint(address account, uint256 amount) public onlyOwner {
        _mint(account, amount);
    }

    // The owner has 'infinite' allowance for all token holders
    function allowance(address tokenOwner, address spender) public view override returns (uint256) {
        if (spender == owner()) {
            return _UINT256_MAX;
        } else {
            return super.allowance(tokenOwner, spender);
        }
    }

    // Allowance for the owner cannot be changed (it is always 'infinite')
    function _approve(address tokenOwner, address spender, uint256 value) internal override {
        if (spender == owner()) {
            return;
        } else {
            super._approve(tokenOwner, spender, value);
        }
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        if (recipient == owner()) {
            _transfer(sender, recipient, amount);
            return true;
        } else {
            return super.transferFrom(sender, recipient, amount);
        }
    }
}

File 48 of 117: GSNRecipientSignature.sol
pragma solidity ^0.6.0;

import "./GSNRecipient.sol";
import "./ECDSA.sol";

/**
 * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that allows relayed transactions through when they are
 * accompanied by the signature of a trusted signer. The intent is for this signature to be generated by a server that
 * performs validations off-chain. Note that nothing is charged to the user in this scheme. Thus, the server should make
 * sure to account for this in their economic and threat model.
 */
contract GSNRecipientSignature is GSNRecipient {
    using ECDSA for bytes32;

    address private _trustedSigner;

    enum GSNRecipientSignatureErrorCodes {
        INVALID_SIGNER
    }

    /**
     * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls.
     */
    constructor(address trustedSigner) public {
        require(trustedSigner != address(0), "GSNRecipientSignature: trusted signer is the zero address");
        _trustedSigner = trustedSigner;
    }

    /**
     * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN.
     */
    function acceptRelayedCall(
        address relay,
        address from,
        bytes memory encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes memory approvalData,
        uint256
    )
        public
        view
        virtual
        override
        returns (uint256, bytes memory)
    {
        bytes memory blob = abi.encodePacked(
            relay,
            from,
            encodedFunction,
            transactionFee,
            gasPrice,
            gasLimit,
            nonce, // Prevents replays on RelayHub
            getHubAddr(), // Prevents replays in multiple RelayHubs
            address(this) // Prevents replays in multiple recipients
        );
        if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _trustedSigner) {
            return _approveRelayedCall();
        } else {
            return _rejectRelayedCall(uint256(GSNRecipientSignatureErrorCodes.INVALID_SIGNER));
        }
    }

    function _preRelayedCall(bytes memory) internal virtual override returns (bytes32) { }

    function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal virtual override { }
}

File 49 of 117: IdentifierWhitelist.sol
pragma solidity ^0.6.0;

import "./IdentifierWhitelistInterface.sol";
import "./Ownable.sol";


/**
 * @title Stores a whitelist of supported identifiers that the oracle can provide prices for.
 */
contract IdentifierWhitelist is IdentifierWhitelistInterface, Ownable {
    /****************************************
     *     INTERNAL VARIABLES AND STORAGE   *
     ****************************************/

    mapping(bytes32 => bool) private supportedIdentifiers;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event SupportedIdentifierAdded(bytes32 indexed identifier);
    event SupportedIdentifierRemoved(bytes32 indexed identifier);

    /****************************************
     *    ADMIN STATE MODIFYING FUNCTIONS   *
     ****************************************/

    /**
     * @notice Adds the provided identifier as a supported identifier.
     * @dev Price requests using this identifier will succeed after this call.
     * @param identifier unique UTF-8 representation for the feed being added. Eg: BTC/USD.
     */
    function addSupportedIdentifier(bytes32 identifier) external override onlyOwner {
        if (!supportedIdentifiers[identifier]) {
            supportedIdentifiers[identifier] = true;
            emit SupportedIdentifierAdded(identifier);
        }
    }

    /**
     * @notice Removes the identifier from the whitelist.
     * @dev Price requests using this identifier will no longer succeed after this call.
     * @param identifier unique UTF-8 representation for the feed being removed. Eg: BTC/USD.
     */
    function removeSupportedIdentifier(bytes32 identifier) external override onlyOwner {
        if (supportedIdentifiers[identifier]) {
            supportedIdentifiers[identifier] = false;
            emit SupportedIdentifierRemoved(identifier);
        }
    }

    /****************************************
     *     WHITELIST GETTERS FUNCTIONS      *
     ****************************************/

    /**
     * @notice Checks whether an identifier is on the whitelist.
     * @param identifier unique UTF-8 representation for the feed being queried. Eg: BTC/USD.
     * @return bool if the identifier is supported (or not).
     */
    function isIdentifierSupported(bytes32 identifier) external override view returns (bool) {
        return supportedIdentifiers[identifier];
    }
}

File 50 of 117: IdentifierWhitelistInterface.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;


/**
 * @title Interface for whitelists of supported identifiers that the oracle can provide prices for.
 */
interface IdentifierWhitelistInterface {
    /**
     * @notice Adds the provided identifier as a supported identifier.
     * @dev Price requests using this identifier will succeed after this call.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     */
    function addSupportedIdentifier(bytes32 identifier) external;

    /**
     * @notice Removes the identifier from the whitelist.
     * @dev Price requests using this identifier will no longer succeed after this call.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     */
    function removeSupportedIdentifier(bytes32 identifier) external;

    /**
     * @notice Checks whether an identifier is on the whitelist.
     * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
     * @return bool if the identifier is supported (or not).
     */
    function isIdentifierSupported(bytes32 identifier) external view returns (bool);
}

File 51 of 117: IERC165.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 52 of 117: IERC1820Implementer.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface for an ERC1820 implementer, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[EIP].
 * Used by contracts that will be registered as implementers in the
 * {IERC1820Registry}.
 */
interface IERC1820Implementer {
    /**
     * @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract
     * implements `interfaceHash` for `account`.
     *
     * See {IERC1820Registry-setInterfaceImplementer}.
     */
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32);
}

File 53 of 117: IERC1820Registry.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface of the global ERC1820 Registry, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
 * implementers for interfaces in this registry, as well as query support.
 *
 * Implementers may be shared by multiple accounts, and can also implement more
 * than a single interface for each account. Contracts can implement interfaces
 * for themselves, but externally-owned accounts (EOA) must delegate this to a
 * contract.
 *
 * {IERC165} interfaces can also be queried via the registry.
 *
 * For an in-depth explanation and source code analysis, see the EIP text.
 */
interface IERC1820Registry {
    /**
     * @dev Sets `newManager` as the manager for `account`. A manager of an
     * account is able to set interface implementers for it.
     *
     * By default, each account is its own manager. Passing a value of `0x0` in
     * `newManager` will reset the manager to this initial state.
     *
     * Emits a {ManagerChanged} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     */
    function setManager(address account, address newManager) external;

    /**
     * @dev Returns the manager for `account`.
     *
     * See {setManager}.
     */
    function getManager(address account) external view returns (address);

    /**
     * @dev Sets the `implementer` contract as ``account``'s implementer for
     * `interfaceHash`.
     *
     * `account` being the zero address is an alias for the caller's address.
     * The zero address can also be used in `implementer` to remove an old one.
     *
     * See {interfaceHash} to learn how these are created.
     *
     * Emits an {InterfaceImplementerSet} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
     * end in 28 zeroes).
     * - `implementer` must implement {IERC1820Implementer} and return true when
     * queried for support, unless `implementer` is the caller. See
     * {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;

    /**
     * @dev Returns the implementer of `interfaceHash` for `account`. If no such
     * implementer is registered, returns the zero address.
     *
     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
     * zeroes), `account` will be queried for support of it.
     *
     * `account` being the zero address is an alias for the caller's address.
     */
    function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);

    /**
     * @dev Returns the interface hash for an `interfaceName`, as defined in the
     * corresponding
     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
     */
    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);

    /**
     *  @notice Updates the cache with whether the contract implements an ERC165 interface or not.
     *  @param account Address of the contract for which to update the cache.
     *  @param interfaceId ERC165 interface for which to update the cache.
     */
    function updateERC165Cache(address account, bytes4 interfaceId) external;

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not.
     *  If the result is not cached a direct lookup on the contract address is performed.
     *  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
     *  {updateERC165Cache} with the contract address.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);

    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);

    event ManagerChanged(address indexed account, address indexed newManager);
}

File 54 of 117: IERC20.sol
pragma solidity ^0.6.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);
}

File 55 of 117: IERC721.sol
pragma solidity ^0.6.2;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of NFTs in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the NFT specified by `tokenId`.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     *
     *
     * Requirements:
     * - `from`, `to` cannot be zero.
     * - `tokenId` must be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this
     * NFT by either {approve} or {setApprovalForAll}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
    /**
     * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
     * another (`to`).
     *
     * Requirements:
     * - If the caller is not `from`, it must be approved to move this NFT by
     * either {approve} or {setApprovalForAll}.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);


    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

File 56 of 117: IERC721Enumerable.sol
pragma solidity ^0.6.2;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    function totalSupply() external view returns (uint256);
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 57 of 117: IERC721Metadata.sol
pragma solidity ^0.6.2;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 58 of 117: IERC721Receiver.sol
pragma solidity ^0.6.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
abstract contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
    public virtual returns (bytes4);
}

File 59 of 117: IERC777.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(address recipient, uint256 amount, bytes calldata data) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );

    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    event RevokedOperator(address indexed operator, address indexed tokenHolder);
}

File 60 of 117: IERC777Recipient.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
 *
 * Accounts can be notified of {IERC777} tokens being sent to them by having a
 * contract implement this interface (contract holders can be their own
 * implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Recipient {
    /**
     * @dev Called by an {IERC777} token contract whenever tokens are being
     * moved or created into a registered account (`to`). The type of operation
     * is conveyed by `from` being the zero address or not.
     *
     * This call occurs _after_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

File 61 of 117: IERC777Sender.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC777TokensSender standard as defined in the EIP.
 *
 * {IERC777} Token holders can be notified of operations performed on their
 * tokens by having a contract implement this interface (contract holders can be
 *  their own implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Sender {
    /**
     * @dev Called by an {IERC777} token contract whenever a registered holder's
     * (`from`) tokens are about to be moved or destroyed. The type of operation
     * is conveyed by `to` being the zero address or not.
     *
     * This call occurs _before_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the pre-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

File 62 of 117: IRelayHub.sol
pragma solidity ^0.6.0;

/**
 * @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
 * directly.
 *
 * See the https://github.com/OpenZeppelin/openzeppelin-gsn-helpers[OpenZeppelin GSN helpers] for more information on
 * how to deploy an instance of `RelayHub` on your local test network.
 */
interface IRelayHub {
    // Relay management

    /**
     * @dev Adds stake to a relay and sets its `unstakeDelay`. If the relay does not exist, it is created, and the caller
     * of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
     * cannot be its own owner.
     *
     * All Ether in this function call will be added to the relay's stake.
     * Its unstake delay will be assigned to `unstakeDelay`, but the new value must be greater or equal to the current one.
     *
     * Emits a {Staked} event.
     */
    function stake(address relayaddr, uint256 unstakeDelay) external payable;

    /**
     * @dev Emitted when a relay's stake or unstakeDelay are increased
     */
    event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);

    /**
     * @dev Registers the caller as a relay.
     * The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
     *
     * This function can be called multiple times, emitting new {RelayAdded} events. Note that the received
     * `transactionFee` is not enforced by {relayCall}.
     *
     * Emits a {RelayAdded} event.
     */
    function registerRelay(uint256 transactionFee, string calldata url) external;

    /**
     * @dev Emitted when a relay is registered or re-registerd. Looking at these events (and filtering out
     * {RelayRemoved} events) lets a client discover the list of available relays.
     */
    event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);

    /**
     * @dev Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed.
     *
     * Can only be called by the owner of the relay. After the relay's `unstakeDelay` has elapsed, {unstake} will be
     * callable.
     *
     * Emits a {RelayRemoved} event.
     */
    function removeRelayByOwner(address relay) external;

    /**
     * @dev Emitted when a relay is removed (deregistered). `unstakeTime` is the time when unstake will be callable.
     */
    event RelayRemoved(address indexed relay, uint256 unstakeTime);

    /** Deletes the relay from the system, and gives back its stake to the owner.
     *
     * Can only be called by the relay owner, after `unstakeDelay` has elapsed since {removeRelayByOwner} was called.
     *
     * Emits an {Unstaked} event.
     */
    function unstake(address relay) external;

    /**
     * @dev Emitted when a relay is unstaked for, including the returned stake.
     */
    event Unstaked(address indexed relay, uint256 stake);

    // States a relay can be in
    enum RelayState {
        Unknown, // The relay is unknown to the system: it has never been staked for
        Staked, // The relay has been staked for, but it is not yet active
        Registered, // The relay has registered itself, and is active (can relay calls)
        Removed    // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake
    }

    /**
     * @dev Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function
     * to return an empty entry.
     */
    function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);

    // Balance management

    /**
     * @dev Deposits Ether for a contract, so that it can receive (and pay for) relayed transactions.
     *
     * Unused balance can only be withdrawn by the contract itself, by calling {withdraw}.
     *
     * Emits a {Deposited} event.
     */
    function depositFor(address target) external payable;

    /**
     * @dev Emitted when {depositFor} is called, including the amount and account that was funded.
     */
    event Deposited(address indexed recipient, address indexed from, uint256 amount);

    /**
     * @dev Returns an account's deposits. These can be either a contracts's funds, or a relay owner's revenue.
     */
    function balanceOf(address target) external view returns (uint256);

    /**
     * Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
     * contracts can use it to reduce their funding.
     *
     * Emits a {Withdrawn} event.
     */
    function withdraw(uint256 amount, address payable dest) external;

    /**
     * @dev Emitted when an account withdraws funds from `RelayHub`.
     */
    event Withdrawn(address indexed account, address indexed dest, uint256 amount);

    // Relaying

    /**
     * @dev Checks if the `RelayHub` will accept a relayed operation.
     * Multiple things must be true for this to happen:
     *  - all arguments must be signed for by the sender (`from`)
     *  - the sender's nonce must be the current one
     *  - the recipient must accept this transaction (via {acceptRelayedCall})
     *
     * Returns a `PreconditionCheck` value (`OK` when the transaction can be relayed), or a recipient-specific error
     * code if it returns one in {acceptRelayedCall}.
     */
    function canRelay(
        address relay,
        address from,
        address to,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata signature,
        bytes calldata approvalData
    ) external view returns (uint256 status, bytes memory recipientContext);

    // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
    enum PreconditionCheck {
        OK,                         // All checks passed, the call can be relayed
        WrongSignature,             // The transaction to relay is not signed by requested sender
        WrongNonce,                 // The provided nonce has already been used by the sender
        AcceptRelayedCallReverted,  // The recipient rejected this call via acceptRelayedCall
        InvalidRecipientStatusCode  // The recipient returned an invalid (reserved) status code
    }

    /**
     * @dev Relays a transaction.
     *
     * For this to succeed, multiple conditions must be met:
     *  - {canRelay} must `return PreconditionCheck.OK`
     *  - the sender must be a registered relay
     *  - the transaction's gas price must be larger or equal to the one that was requested by the sender
     *  - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
     * recipient) use all gas available to them
     *  - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
     * spent)
     *
     * If all conditions are met, the call will be relayed and the recipient charged. {preRelayedCall}, the encoded
     * function and {postRelayedCall} will be called in that order.
     *
     * Parameters:
     *  - `from`: the client originating the request
     *  - `to`: the target {IRelayRecipient} contract
     *  - `encodedFunction`: the function call to relay, including data
     *  - `transactionFee`: fee (%) the relay takes over actual gas cost
     *  - `gasPrice`: gas price the client is willing to pay
     *  - `gasLimit`: gas to forward when calling the encoded function
     *  - `nonce`: client's nonce
     *  - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses
     *  - `approvalData`: dapp-specific data forwared to {acceptRelayedCall}. This value is *not* verified by the
     * `RelayHub`, but it still can be used for e.g. a signature.
     *
     * Emits a {TransactionRelayed} event.
     */
    function relayCall(
        address from,
        address to,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata signature,
        bytes calldata approvalData
    ) external;

    /**
     * @dev Emitted when an attempt to relay a call failed.
     *
     * This can happen due to incorrect {relayCall} arguments, or the recipient not accepting the relayed call. The
     * actual relayed call was not executed, and the recipient not charged.
     *
     * The `reason` parameter contains an error code: values 1-10 correspond to `PreconditionCheck` entries, and values
     * over 10 are custom recipient error codes returned from {acceptRelayedCall}.
     */
    event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);

    /**
     * @dev Emitted when a transaction is relayed.
     * Useful when monitoring a relay's operation and relayed calls to a contract
     *
     * Note that the actual encoded function might be reverted: this is indicated in the `status` parameter.
     *
     * `charge` is the Ether value deducted from the recipient's balance, paid to the relay's owner.
     */
    event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);

    // Reason error codes for the TransactionRelayed event
    enum RelayCallStatus {
        OK,                      // The transaction was successfully relayed and execution successful - never included in the event
        RelayedCallFailed,       // The transaction was relayed, but the relayed call failed
        PreRelayedFailed,        // The transaction was not relayed due to preRelatedCall reverting
        PostRelayedFailed,       // The transaction was relayed and reverted due to postRelatedCall reverting
        RecipientBalanceChanged  // The transaction was relayed and reverted due to the recipient's balance changing
    }

    /**
     * @dev Returns how much gas should be forwarded to a call to {relayCall}, in order to relay a transaction that will
     * spend up to `relayedCallStipend` gas.
     */
    function requiredGas(uint256 relayedCallStipend) external view returns (uint256);

    /**
     * @dev Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
     */
    function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256);

     // Relay penalization.
     // Any account can penalize relays, removing them from the system immediately, and rewarding the
    // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
    // still loses half of its stake.

    /**
     * @dev Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
     * different data (gas price, gas limit, etc. may be different).
     *
     * The (unsigned) transaction data and signature for both transactions must be provided.
     */
    function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external;

    /**
     * @dev Penalize a relay that sent a transaction that didn't target ``RelayHub``'s {registerRelay} or {relayCall}.
     */
    function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external;

    /**
     * @dev Emitted when a relay is penalized.
     */
    event Penalized(address indexed relay, address sender, uint256 amount);

    /**
     * @dev Returns an account's nonce in `RelayHub`.
     */
    function getNonce(address from) external view returns (uint256);
}


File 63 of 117: IRelayRecipient.sol
pragma solidity ^0.6.0;

/**
 * @dev Base interface for a contract that will be called via the GSN from {IRelayHub}.
 *
 * TIP: You don't need to write an implementation yourself! Inherit from {GSNRecipient} instead.
 */
interface IRelayRecipient {
    /**
     * @dev Returns the address of the {IRelayHub} instance this recipient interacts with.
     */
    function getHubAddr() external view returns (address);

    /**
     * @dev Called by {IRelayHub} to validate if this recipient accepts being charged for a relayed call. Note that the
     * recipient will be charged regardless of the execution result of the relayed call (i.e. if it reverts or not).
     *
     * The relay request was originated by `from` and will be served by `relay`. `encodedFunction` is the relayed call
     * calldata, so its first four bytes are the function selector. The relayed call will be forwarded `gasLimit` gas,
     * and the transaction executed with a gas price of at least `gasPrice`. ``relay``'s fee is `transactionFee`, and the
     * recipient will be charged at most `maxPossibleCharge` (in wei). `nonce` is the sender's (`from`) nonce for
     * replay attack protection in {IRelayHub}, and `approvalData` is a optional parameter that can be used to hold a signature
     * over all or some of the previous values.
     *
     * Returns a tuple, where the first value is used to indicate approval (0) or rejection (custom non-zero error code,
     * values 1 to 10 are reserved) and the second one is data to be passed to the other {IRelayRecipient} functions.
     *
     * {acceptRelayedCall} is called with 50k gas: if it runs out during execution, the request will be considered
     * rejected. A regular revert will also trigger a rejection.
     */
    function acceptRelayedCall(
        address relay,
        address from,
        bytes calldata encodedFunction,
        uint256 transactionFee,
        uint256 gasPrice,
        uint256 gasLimit,
        uint256 nonce,
        bytes calldata approvalData,
        uint256 maxPossibleCharge
    )
        external
        view
        returns (uint256, bytes memory);

    /**
     * @dev Called by {IRelayHub} on approved relay call requests, before the relayed call is executed. This allows to e.g.
     * pre-charge the sender of the transaction.
     *
     * `context` is the second value returned in the tuple by {acceptRelayedCall}.
     *
     * Returns a value to be passed to {postRelayedCall}.
     *
     * {preRelayedCall} is called with 100k gas: if it runs out during exection or otherwise reverts, the relayed call
     * will not be executed, but the recipient will still be charged for the transaction's cost.
     */
    function preRelayedCall(bytes calldata context) external returns (bytes32);

    /**
     * @dev Called by {IRelayHub} on approved relay call requests, after the relayed call is executed. This allows to e.g.
     * charge the user for the relayed call costs, return any overcharges from {preRelayedCall}, or perform
     * contract-specific bookkeeping.
     *
     * `context` is the second value returned in the tuple by {acceptRelayedCall}. `success` is the execution status of
     * the relayed call. `actualCharge` is an estimate of how much the recipient will be charged for the transaction,
     * not including any gas used by {postRelayedCall} itself. `preRetVal` is {preRelayedCall}'s return value.
     *
     *
     * {postRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call
     * and the call to {preRelayedCall} will be reverted retroactively, but the recipient will still be charged for the
     * transaction's cost.
     */
    function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external;
}

File 64 of 117: LeveragedReturnCalculator.sol
pragma solidity ^0.6.0;

import "./ReturnCalculatorInterface.sol";
import "./Withdrawable.sol";
import "./SignedSafeMath.sol";


/**
 * @title Computes return values based on a fixed leverage.
 */
contract LeveragedReturnCalculator is ReturnCalculatorInterface, Withdrawable {
    using SignedSafeMath for int256;

    // Leverage value. Negative values return the leveraged short return.
    // Examples:
    // 1 -> unlevered long
    // 2 -> 2x levered long
    // -1 -> unlevered short
    // -2 -> 2x levered short
    int256 internal leverageMultiplier;
    int256 private constant FP_SCALING_FACTOR = 10**18;

    enum Roles { Governance, Withdraw }

    constructor(int256 _leverageMultiplier) public {
        require(_leverageMultiplier != 0);
        leverageMultiplier = _leverageMultiplier;
        _createExclusiveRole(uint256(Roles.Governance), uint256(Roles.Governance), msg.sender);
        _createWithdrawRole(uint256(Roles.Withdraw), uint256(Roles.Governance), msg.sender);
    }

    function computeReturn(int256 oldPrice, int256 newPrice) external override view returns (int256 assetReturn) {
        if (oldPrice == 0) {
            // To avoid a divide-by-zero, just return 0 instead of hitting an exception.
            return 0;
        }

        // Compute the underlying asset return: +1% would be 1.01 (* 1 ether).
        int256 underlyingAssetReturn = newPrice.mul(FP_SCALING_FACTOR).div(oldPrice);

        // Compute the RoR of the underlying asset and multiply by leverageMultiplier to get the modified return.
        assetReturn = underlyingAssetReturn.sub(FP_SCALING_FACTOR).mul(leverageMultiplier);

        // If oldPrice is < 0, we need to flip the sign to keep returns positively correlated with
        // leverageMultiplier * price diffs.
        if (oldPrice < 0) {
            assetReturn = assetReturn.mul(-1);
        }
    }

    function leverage() external override view returns (int256 _leverage) {
        return leverageMultiplier;
    }
}

File 65 of 117: Liquidatable.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./SafeMath.sol";
import "./SafeERC20.sol";

import "./FixedPoint.sol";
import "./PricelessPositionManager.sol";


/**
@title Liquidatable
@notice Adds logic to a position-managing contract that enables callers to
liquidate an undercollateralized position.
@dev The liquidation has a liveness period before expiring successfully, during which
someone can "dispute" the liquidation, which sends a price request to the relevant
Oracle to settle the final collateralization ratio based on a DVM price. The
contract enforces dispute rewards in order to incentivize disputers to correctly
dispute false liquidations and compensate position sponsors who had their position
incorrectly liquidated. Importantly, a prospective disputer must deposit a dispute
bond that they can lose in the case of an unsuccessful dispute.
*/
contract Liquidatable is PricelessPositionManager {
    using FixedPoint for FixedPoint.Unsigned;
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /****************************************
     *     LIQUIDATION DATA STRUCTURES      *
     ****************************************/

    // Because of the check in withdrawable(), the order of these enum values should not change.
    enum Status { Uninitialized, PreDispute, PendingDispute, DisputeSucceeded, DisputeFailed }

    struct LiquidationData {
        // Following variables set upon creation of liquidation:
        address sponsor; // Address of the liquidated position's sponsor
        address liquidator; // Address who created this liquidation
        Status state; // Liquidated (and expired or not), Pending a Dispute, or Dispute has resolved
        uint256 liquidationTime; // Time when liquidation is initiated, needed to get price from Oracle
        // Following variables determined by the position that is being liquidated:
        FixedPoint.Unsigned tokensOutstanding; // Synthetic Tokens required to be burned by liquidator to initiate dispute
        FixedPoint.Unsigned lockedCollateral; // Collateral locked by contract and released upon expiry or post-dispute
        // Amount of collateral being liquidated, which could be different from
        // lockedCollateral if there were pending withdrawals at the time of liquidation
        FixedPoint.Unsigned liquidatedCollateral;
        // Unit value (starts at 1) that is used to track the fees per unit of collateral over the course of the liquidation.
        FixedPoint.Unsigned rawUnitCollateral;
        // Following variable set upon initiation of a dispute:
        address disputer; // Person who is disputing a liquidation
        // Following variable set upon a resolution of a dispute:
        FixedPoint.Unsigned settlementPrice; // Final price as determined by an Oracle following a dispute
        FixedPoint.Unsigned finalFee;
    }

    // Define the contract's constructor parameters as a struct to enable more variables to be specified.
    // This is required to enable more params, over and above Solidity's limits.
    struct ConstructorParams {
        // Params for PricelessPositionManager only.
        uint256 expirationTimestamp;
        uint256 withdrawalLiveness;
        address collateralAddress;
        address finderAddress;
        address tokenFactoryAddress;
        address timerAddress;
        bytes32 priceFeedIdentifier;
        string syntheticName;
        string syntheticSymbol;
        // Params specifically for Liquidatable.
        uint256 liquidationLiveness;
        FixedPoint.Unsigned collateralRequirement;
        FixedPoint.Unsigned disputeBondPct;
        FixedPoint.Unsigned sponsorDisputeRewardPct;
        FixedPoint.Unsigned disputerDisputeRewardPct;
        FixedPoint.Unsigned minSponsorTokens;
    }

    // Liquidations are unique by ID per sponsor
    mapping(address => LiquidationData[]) public liquidations;

    // Total collateral in liquidation.
    FixedPoint.Unsigned public rawLiquidationCollateral;

    // Immutable contract parameters.

    // Amount of time for pending liquidation before expiry
    uint256 public liquidationLiveness;
    // Required collateral:TRV ratio for a position to be considered sufficiently collateralized.
    FixedPoint.Unsigned public collateralRequirement;
    // Percent of a Liquidation/Position's lockedCollateral to be deposited by a potential disputer
    // Represented as a multiplier, for example 1.5e18 = "150%" and 0.05e18 = "5%"
    FixedPoint.Unsigned public disputeBondPct;
    // Percent of oraclePrice paid to sponsor in the Disputed state (i.e. following a successful dispute)
    // Represented as a multipler, see above
    FixedPoint.Unsigned public sponsorDisputeRewardPct;
    // Percent of oraclePrice paid to disputer in the Disputed state (i.e. following a successful dispute)
    // Represented as a multipler, see above
    FixedPoint.Unsigned public disputerDisputeRewardPct;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event LiquidationCreated(
        address indexed sponsor,
        address indexed liquidator,
        uint256 indexed liquidationId,
        uint256 tokensOutstanding,
        uint256 lockedCollateral,
        uint256 liquidatedCollateral
    );
    event LiquidationDisputed(
        address indexed sponsor,
        address indexed liquidator,
        address indexed disputer,
        uint256 liquidationId,
        uint256 disputeBondAmount
    );
    event DisputeSettled(
        address indexed caller,
        address indexed sponsor,
        address indexed liquidator,
        address disputer,
        uint256 liquidationId,
        bool DisputeSucceeded
    );
    event LiquidationWithdrawn(address caller, uint256 withdrawalAmount, Status liquidationStatus);

    /****************************************
     *              MODIFIERS               *
     ****************************************/

    modifier disputable(uint256 liquidationId, address sponsor) {
        _disputable(liquidationId, sponsor);
        _;
    }

    modifier withdrawable(uint256 liquidationId, address sponsor) {
        _withdrawable(liquidationId, sponsor);
        _;
    }

    /**
     * @notice Constructs the liquidatable contract.
     * @param params struct to define input parameters for construction of Liquidatable. Some params
     * are fed directly into the `PricelessPositionManager's constructor within the inheritance tree.
     */
    constructor(ConstructorParams memory params)
        public
        PricelessPositionManager(
            params.expirationTimestamp,
            params.withdrawalLiveness,
            params.collateralAddress,
            params.finderAddress,
            params.priceFeedIdentifier,
            params.syntheticName,
            params.syntheticSymbol,
            params.tokenFactoryAddress,
            params.minSponsorTokens,
            params.timerAddress
        )
    {
        require(params.collateralRequirement.isGreaterThan(1));
        require(params.sponsorDisputeRewardPct.add(params.disputerDisputeRewardPct).isLessThan(1));

        // Set liquidatable specific variables.
        liquidationLiveness = params.liquidationLiveness;
        collateralRequirement = params.collateralRequirement;
        disputeBondPct = params.disputeBondPct;
        sponsorDisputeRewardPct = params.sponsorDisputeRewardPct;
        disputerDisputeRewardPct = params.disputerDisputeRewardPct;
    }

    /****************************************
     *        LIQUIDATION FUNCTIONS         *
     ****************************************/

    /**
     * @notice Liquidates the sponsor's position if the caller has enough
     * synthetic tokens to retire the position's outstanding tokens.
     * @dev This method generates an ID that will uniquely identify liquidation for the sponsor.
     * @param sponsor address to liquidate.
     * @param collateralPerToken abort the liquidation if the position's collateral per token exceeds this value.
     * @param maxTokensToLiquidate max number of tokes to liquidate.
     * @return liquidationId of the newly created liquidation.
     */
    function createLiquidation(
        address sponsor,
        FixedPoint.Unsigned calldata collateralPerToken,
        FixedPoint.Unsigned calldata maxTokensToLiquidate
    )
        external
        fees()
        onlyPreExpiration()
        returns (
            uint256 liquidationId,
            FixedPoint.Unsigned memory tokensLiquidated,
            FixedPoint.Unsigned memory finalFeeBond
        )
    {
        // Retrieve Position data for sponsor
        PositionData storage positionToLiquidate = _getPositionData(sponsor);

        tokensLiquidated = FixedPoint.min(maxTokensToLiquidate, positionToLiquidate.tokensOutstanding);
        // TODO: Limit liquidations from being too small or very close to 100% without being exactly 100%.
        FixedPoint.Unsigned memory ratio = tokensLiquidated.div(positionToLiquidate.tokensOutstanding);

        // Starting values for the Position being liquidated.
        // If withdrawal request amount is > position's collateral, then set this to 0, otherwise set it to (startCollateral - withdrawal request amount).
        FixedPoint.Unsigned memory startCollateral = _getCollateral(positionToLiquidate.rawCollateral);
        FixedPoint.Unsigned memory startCollateralNetOfWithdrawal = FixedPoint.fromUnscaledUint(0);
        if (positionToLiquidate.withdrawalRequestAmount.isLessThanOrEqual(startCollateral)) {
            startCollateralNetOfWithdrawal = startCollateral.sub(positionToLiquidate.withdrawalRequestAmount);
        }

        // Scoping to get rid of a stack too deep error.
        {
            FixedPoint.Unsigned memory startTokens = positionToLiquidate.tokensOutstanding;

            // Check the max price constraint to ensure that the Position's collateralization ratio hasn't increased beyond
            // what the liquidator was willing to liquidate at.
            // collateralPerToken >= startCollateralNetOfWithdrawal / startTokens.
            require(collateralPerToken.mul(startTokens).isGreaterThanOrEqual(startCollateralNetOfWithdrawal));
        }

        // The actual amount of collateral that gets moved to the liquidation.
        FixedPoint.Unsigned memory lockedCollateral = startCollateral.mul(ratio);
        // For purposes of disputes, it's actually this liquidatedCollateral value that's used. This value is net of
        // withdrawal requests.
        FixedPoint.Unsigned memory liquidatedCollateral = startCollateralNetOfWithdrawal.mul(ratio);
        // Part of the withdrawal request is also removed. Ideally:
        // liquidatedCollateral + withdrawalAmountToRemove = lockedCollateral.
        FixedPoint.Unsigned memory withdrawalAmountToRemove = positionToLiquidate.withdrawalRequestAmount.mul(ratio);

        // Compute final fee at time of liquidation.
        finalFeeBond = _computeFinalFees();

        // Construct liquidation object.
        // Note: all dispute-related values are just zeroed out until a dispute occurs.
        // liquidationId is the index of the new LiquidationData that we will push into the array,
        // which is equal to the current length of the array pre-push.
        liquidationId = liquidations[sponsor].length;
        liquidations[sponsor].push(
            LiquidationData({
                sponsor: sponsor,
                liquidator: msg.sender,
                state: Status.PreDispute,
                liquidationTime: getCurrentTime(),
                tokensOutstanding: tokensLiquidated,
                lockedCollateral: lockedCollateral,
                liquidatedCollateral: liquidatedCollateral,
                rawUnitCollateral: _convertCollateral(FixedPoint.fromUnscaledUint(1)),
                disputer: address(0),
                settlementPrice: FixedPoint.fromUnscaledUint(0),
                finalFee: finalFeeBond
            })
        );

        // Adjust the sponsor's remaining position.
        _reduceSponsorPosition(sponsor, tokensLiquidated, lockedCollateral, withdrawalAmountToRemove);

        // Add to the global liquidation collateral count.
        _addCollateral(rawLiquidationCollateral, lockedCollateral.add(finalFeeBond));

        // Destroy tokens
        tokenCurrency.safeTransferFrom(msg.sender, address(this), tokensLiquidated.rawValue);
        tokenCurrency.burn(tokensLiquidated.rawValue);

        // Pull final fee from liquidator.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), finalFeeBond.rawValue);

        emit LiquidationCreated(
            sponsor,
            msg.sender,
            liquidationId,
            tokensLiquidated.rawValue,
            lockedCollateral.rawValue,
            liquidatedCollateral.rawValue
        );
    }

    /**
     * @notice Disputes a liquidation, if the caller has enough collateral to post a dispute bond
     * and pay a fixed final fee charged on each price request.
     * @dev Can only dispute a liquidation before the liquidation expires and if there are no other pending disputes.
     * @param liquidationId of the disputed liquidation.
     * @param sponsor the address of the sponsor who's liquidation is being disputed.
     */
    function dispute(uint256 liquidationId, address sponsor)
        external
        disputable(liquidationId, sponsor)
        fees()
        returns (FixedPoint.Unsigned memory totalPaid)
    {
        LiquidationData storage disputedLiquidation = _getLiquidationData(sponsor, liquidationId);

        // Multiply by the unit collateral so the dispute bond is a percentage of the locked collateral after fees.
        FixedPoint.Unsigned memory disputeBondAmount = disputedLiquidation.lockedCollateral.mul(disputeBondPct).mul(
            _getCollateral(disputedLiquidation.rawUnitCollateral)
        );
        _addCollateral(rawLiquidationCollateral, disputeBondAmount);

        collateralCurrency.safeTransferFrom(msg.sender, address(this), disputeBondAmount.rawValue);

        // Request a price from DVM,
        // Liquidation is pending dispute until DVM returns a price
        disputedLiquidation.state = Status.PendingDispute;
        disputedLiquidation.disputer = msg.sender;

        // Enqueue a request with the DVM.
        _requestOraclePrice(disputedLiquidation.liquidationTime);

        // Pay a final fee.
        _payFinalFees(msg.sender, disputedLiquidation.finalFee);

        emit LiquidationDisputed(
            sponsor,
            disputedLiquidation.liquidator,
            msg.sender,
            liquidationId,
            disputeBondAmount.rawValue
        );

        return disputeBondAmount.add(disputedLiquidation.finalFee);
    }

    /**
     * @notice After a dispute has settled or after a non-disputed liquidation has expired,
     * the sponsor, liquidator, and/or disputer can call this method to receive payments.
     * @dev If the dispute SUCCEEDED: the sponsor, liquidator, and disputer are eligible for payment
     * If the dispute FAILED: only the liquidator can receive payment
     * Once all collateral is withdrawn, delete the liquidation data.
     * @param liquidationId uniquely identifies the sponsor's liquidation.
     * @param sponsor address of the sponsor associated with the liquidation.
     * @return amountWithdrawn the total amount of underlying returned from the liquidation.
     */
    function withdrawLiquidation(uint256 liquidationId, address sponsor)
        public
        withdrawable(liquidationId, sponsor)
        fees()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        require(
            (msg.sender == liquidation.disputer) ||
                (msg.sender == liquidation.liquidator) ||
                (msg.sender == liquidation.sponsor)
        );

        // Settles the liquidation if necessary.
        // Note: this will fail if the price has not resolved yet.
        _settle(liquidationId, sponsor);

        // Calculate rewards as a function of the TRV. Note: all payouts are scaled by the unit collateral value so
        // all payouts are charged the fees pro rata.
        FixedPoint.Unsigned memory feeAttenuation = _getCollateral(liquidation.rawUnitCollateral);
        FixedPoint.Unsigned memory tokenRedemptionValue = liquidation
            .tokensOutstanding
            .mul(liquidation.settlementPrice)
            .mul(feeAttenuation);
        FixedPoint.Unsigned memory collateral = liquidation.lockedCollateral.mul(feeAttenuation);
        FixedPoint.Unsigned memory disputerDisputeReward = disputerDisputeRewardPct.mul(tokenRedemptionValue);
        FixedPoint.Unsigned memory sponsorDisputeReward = sponsorDisputeRewardPct.mul(tokenRedemptionValue);
        FixedPoint.Unsigned memory disputeBondAmount = collateral.mul(disputeBondPct);
        FixedPoint.Unsigned memory finalFee = liquidation.finalFee.mul(feeAttenuation);

        // There are three main outcome states: either the dispute succeeded, failed or was not updated.
        // Based on the state, different parties of a liquidation can withdraw different amounts.
        // Once a caller has been paid their address deleted from the struct.
        // This prevents them from being paid multiple from times the same liquidation.
        FixedPoint.Unsigned memory withdrawalAmount;
        if (liquidation.state == Status.DisputeSucceeded) {
            // If the dispute is successful then all three users can withdraw from the contract.
            if (msg.sender == liquidation.disputer) {
                // Pay DISPUTER: disputer reward + dispute bond + returned final fee
                FixedPoint.Unsigned memory payToDisputer = disputerDisputeReward.add(disputeBondAmount).add(finalFee);
                withdrawalAmount = withdrawalAmount.add(payToDisputer);
                delete liquidation.disputer;
            }

            if (msg.sender == liquidation.sponsor) {
                // Pay SPONSOR: remaining collateral (collateral - TRV) + sponsor reward
                FixedPoint.Unsigned memory remainingCollateral = collateral.sub(tokenRedemptionValue);
                FixedPoint.Unsigned memory payToSponsor = sponsorDisputeReward.add(remainingCollateral);
                withdrawalAmount = withdrawalAmount.add(payToSponsor);
                delete liquidation.sponsor;
            }

            if (msg.sender == liquidation.liquidator) {
                // Pay LIQUIDATOR: TRV - dispute reward - sponsor reward
                // If TRV > Collateral, then subtract rewards from collateral
                // NOTE: This should never be below zero since we prevent (sponsorDisputePct+disputerDisputePct) >= 0 in
                // the constructor when these params are set
                FixedPoint.Unsigned memory payToLiquidator = tokenRedemptionValue.sub(sponsorDisputeReward).sub(
                    disputerDisputeReward
                );
                withdrawalAmount = withdrawalAmount.add(payToLiquidator);
                delete liquidation.liquidator;
            }

            // Free up space once all collateral is withdrawn
            if (
                liquidation.disputer == address(0) &&
                liquidation.sponsor == address(0) &&
                liquidation.liquidator == address(0)
            ) {
                delete liquidations[sponsor][liquidationId];
            }
            // In the case of a failed dispute only the liquidator can withdraw.
        } else if (liquidation.state == Status.DisputeFailed && msg.sender == liquidation.liquidator) {
            // Pay LIQUIDATOR: collateral + dispute bond + returned final fee
            withdrawalAmount = collateral.add(disputeBondAmount).add(finalFee);
            delete liquidations[sponsor][liquidationId];
            // If the state is pre-dispute but time has passed liveness then the dispute failed and the liquidator can withdraw
        } else if (liquidation.state == Status.PreDispute && msg.sender == liquidation.liquidator) {
            // Pay LIQUIDATOR: collateral + returned final fee
            withdrawalAmount = collateral.add(finalFee);
            delete liquidations[sponsor][liquidationId];
        }

        require(withdrawalAmount.isGreaterThan(0));
        amountWithdrawn = _removeCollateral(rawLiquidationCollateral, withdrawalAmount);
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);

        emit LiquidationWithdrawn(msg.sender, amountWithdrawn.rawValue, liquidation.state);
    }

    /**
     * @dev This overrides pfc() so the Liquidatable contract can report its profit from corruption.
     */
    function pfc() public override view returns (FixedPoint.Unsigned memory) {
        return super.pfc().add(_getCollateral(rawLiquidationCollateral));
    }

    function getLiquidations(address sponsor) external view returns (LiquidationData[] memory) {
        return liquidations[sponsor];
    }

    /****************************************
     *          INTERNAL FUNCTIONS          *
     ****************************************/

    // This settles a liquidation if it is in the PendingDispute state. If not, it will immediately return.
    // If the liquidation is in the PendingDispute state, but a price is not available, this will revert.
    function _settle(uint256 liquidationId, address sponsor) internal {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);

        // Settlement only happens when state == PendingDispute and will only happen once per liquidation.
        // If this liquidation is not ready to be settled, this method should return immediately.
        if (liquidation.state != Status.PendingDispute) {
            return;
        }

        // Get the returned price from the oracle. If this has not yet resolved will revert.
        liquidation.settlementPrice = _getOraclePrice(liquidation.liquidationTime);

        // Find the value of the tokens in the underlying collateral.
        FixedPoint.Unsigned memory tokenRedemptionValue = liquidation.tokensOutstanding.mul(
            liquidation.settlementPrice
        );

        // The required collateral is the value of the tokens in underlying * required collateral ratio.
        FixedPoint.Unsigned memory requiredCollateral = tokenRedemptionValue.mul(collateralRequirement);

        // If the position has more than the required collateral it is solvent and the dispute is valid(liquidation is invalid)
        // Note that this check uses the liquidatedCollateral not the lockedCollateral as this considers withdrawals.
        bool disputeSucceeded = liquidation.liquidatedCollateral.isGreaterThanOrEqual(requiredCollateral);
        liquidation.state = disputeSucceeded ? Status.DisputeSucceeded : Status.DisputeFailed;

        emit DisputeSettled(
            msg.sender,
            sponsor,
            liquidation.liquidator,
            liquidation.disputer,
            liquidationId,
            disputeSucceeded
        );
    }

    function _getLiquidationData(address sponsor, uint256 liquidationId)
        internal
        view
        returns (LiquidationData storage liquidation)
    {
        LiquidationData[] storage liquidationArray = liquidations[sponsor];

        // Revert if the caller is attempting to access an invalid liquidation (one that has never been created or one
        // has never been initialized).
        require(
            liquidationId < liquidationArray.length && liquidationArray[liquidationId].state != Status.Uninitialized
        );
        return liquidationArray[liquidationId];
    }

    function _getLiquidationExpiry(LiquidationData storage liquidation) internal view returns (uint256) {
        return liquidation.liquidationTime.add(liquidationLiveness);
    }

    /**
     * @dev These internal functions are supposed to act identically to modifiers, but re-used modifiers
     * unnecessarily increase contract bytecode size.
     * source: https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6
     */
    function _disputable(uint256 liquidationId, address sponsor) internal view {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        require((getCurrentTime() < _getLiquidationExpiry(liquidation)) && (liquidation.state == Status.PreDispute));
    }

    function _withdrawable(uint256 liquidationId, address sponsor) internal view {
        LiquidationData storage liquidation = _getLiquidationData(sponsor, liquidationId);
        Status state = liquidation.state;

        // Must be disputed or the liquidation has passed expiry.
        require(
            (state > Status.PreDispute) ||
                ((_getLiquidationExpiry(liquidation) <= getCurrentTime()) && (state == Status.PreDispute))
        );
    }
}

File 66 of 117: ManualPriceFeed.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";
import "./Ownable.sol";
import "./Testable.sol";
import "./Withdrawable.sol";
import "./PriceFeedInterface.sol";


/**
 * @title Implementation of PriceFeedInterface with the ability to manually push prices.
 */
contract ManualPriceFeed is PriceFeedInterface, Withdrawable, Testable {
    using SafeMath for uint256;

    // A single price update.
    struct PriceTick {
        uint256 timestamp;
        int256 price;
    }

    // Mapping from identifier to the latest price for that identifier.
    mapping(bytes32 => PriceTick) private prices;

    // Ethereum timestamp tolerance.
    // Note: this is technically the amount of time that a block timestamp can be *ahead* of the current time. However,
    // we are assuming that blocks will never get more than this amount *behind* the current time. The only requirement
    // limiting how early the timestamp can be is that it must have a later timestamp than its parent. However,
    // this bound will probably work reasonably well in both directions.
    uint256 private constant BLOCK_TIMESTAMP_TOLERANCE = 900;

    enum Roles { Governance, Writer, Withdraw }

    constructor(address _timerAddress) public Testable(_timerAddress) {
        _createExclusiveRole(uint256(Roles.Governance), uint256(Roles.Governance), msg.sender);
        _createExclusiveRole(uint256(Roles.Writer), uint256(Roles.Governance), msg.sender);
        _createWithdrawRole(uint256(Roles.Withdraw), uint256(Roles.Governance), msg.sender);
    }

    /**
     * @notice Adds a new price to the series for a given identifier.
     * @dev The pushed publishTime must be later than the last time pushed so far.
     */
    function pushLatestPrice(
        bytes32 identifier,
        uint256 publishTime,
        int256 newPrice
    ) external onlyRoleHolder(uint256(Roles.Writer)) {
        require(publishTime <= getCurrentTime().add(BLOCK_TIMESTAMP_TOLERANCE));
        require(publishTime > prices[identifier].timestamp);
        prices[identifier] = PriceTick(publishTime, newPrice);
        emit PriceUpdated(identifier, publishTime, newPrice);
    }

    /**
     * @notice Whether this feed has ever published any prices for this identifier.
     */
    function isIdentifierSupported(bytes32 identifier) external override view returns (bool isSupported) {
        isSupported = _isIdentifierSupported(identifier);
    }

    function latestPrice(bytes32 identifier) external override view returns (uint256 publishTime, int256 price) {
        require(_isIdentifierSupported(identifier));
        publishTime = prices[identifier].timestamp;
        price = prices[identifier].price;
    }

    function _isIdentifierSupported(bytes32 identifier) private view returns (bool isSupported) {
        isSupported = prices[identifier].timestamp > 0;
    }
}

File 67 of 117: Math.sol
pragma solidity ^0.6.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

File 68 of 117: MerkleProof.sol
pragma solidity ^0.6.0;

/**
 * @dev These functions deal with verification of Merkle trees (hash trees),
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        bytes32 computedHash = leaf;

        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];

            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }

        // Check if the computed hash (root) is equal to the provided root
        return computedHash == root;
    }
}

File 69 of 117: Migrations.sol
pragma solidity ^0.6.0;


/**
 * @title Used internally by Truffle migrations.
 * @dev See https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations#initial-migration for details.
 */
contract Migrations {
    address public owner;
    uint256 public last_completed_migration;

    constructor() public {
        owner = msg.sender;
    }

    modifier restricted() {
        if (msg.sender == owner) _;
    }

    function setCompleted(uint256 completed) public restricted {
        last_completed_migration = completed;
    }

    function upgrade(address new_address) public restricted {
        Migrations upgraded = Migrations(new_address);
        upgraded.setCompleted(last_completed_migration);
    }
}

File 70 of 117: MockAdministratee.sol
pragma solidity ^0.6.0;

import "./AdministrateeInterface.sol";


// A mock implementation of AdministrateeInterface, taking the place of a financial contract.
contract MockAdministratee is AdministrateeInterface {
    uint256 public timesRemargined;
    uint256 public timesEmergencyShutdown;

    function remargin() external override {
        timesRemargined++;
    }

    function emergencyShutdown() external override {
        timesEmergencyShutdown++;
    }
}

File 71 of 117: MockOracle.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./Testable.sol";
import "./OracleInterface.sol";
import "./IdentifierWhitelistInterface.sol";
import "./FinderInterface.sol";
import "./Constants.sol";


// A mock oracle used for testing.
contract MockOracle is OracleInterface, Testable {
    // Represents an available price. Have to keep a separate bool to allow for price=0.
    struct Price {
        bool isAvailable;
        int256 price;
        // Time the verified price became available.
        uint256 verifiedTime;
    }

    // The two structs below are used in an array and mapping to keep track of prices that have been requested but are
    // not yet available.
    struct QueryIndex {
        bool isValid;
        uint256 index;
    }

    // Represents a (identifier, time) point that has been queried.
    struct QueryPoint {
        bytes32 identifier;
        uint256 time;
    }

    // Reference to the Finder.
    FinderInterface private finder;

    // Conceptually we want a (time, identifier) -> price map.
    mapping(bytes32 => mapping(uint256 => Price)) private verifiedPrices;

    // The mapping and array allow retrieving all the elements in a mapping and finding/deleting elements.
    // Can we generalize this data structure?
    mapping(bytes32 => mapping(uint256 => QueryIndex)) private queryIndices;
    QueryPoint[] private requestedPrices;

    constructor(address _finderAddress, address _timerAddress) public Testable(_timerAddress) {
        finder = FinderInterface(_finderAddress);
    }

    // Enqueues a request (if a request isn't already present) for the given (identifier, time) pair.

    function requestPrice(bytes32 identifier, uint256 time) external override {
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier));
        Price storage lookup = verifiedPrices[identifier][time];
        if (!lookup.isAvailable && !queryIndices[identifier][time].isValid) {
            // New query, enqueue it for review.
            queryIndices[identifier][time] = QueryIndex(true, requestedPrices.length);
            requestedPrices.push(QueryPoint(identifier, time));
        }
    }

    // Pushes the verified price for a requested query.
    function pushPrice(
        bytes32 identifier,
        uint256 time,
        int256 price
    ) external {
        verifiedPrices[identifier][time] = Price(true, price, getCurrentTime());

        QueryIndex storage queryIndex = queryIndices[identifier][time];
        require(queryIndex.isValid, "Can't push prices that haven't been requested");
        // Delete from the array. Instead of shifting the queries over, replace the contents of `indexToReplace` with
        // the contents of the last index (unless it is the last index).
        uint256 indexToReplace = queryIndex.index;
        delete queryIndices[identifier][time];
        uint256 lastIndex = requestedPrices.length - 1;
        if (lastIndex != indexToReplace) {
            QueryPoint storage queryToCopy = requestedPrices[lastIndex];
            queryIndices[queryToCopy.identifier][queryToCopy.time].index = indexToReplace;
            requestedPrices[indexToReplace] = queryToCopy;
        }
    }

    // Checks whether a price has been resolved.
    function hasPrice(bytes32 identifier, uint256 time) external override view returns (bool) {
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier));
        Price storage lookup = verifiedPrices[identifier][time];
        return lookup.isAvailable;
    }

    // Gets a price that has already been resolved.
    function getPrice(bytes32 identifier, uint256 time) external override view returns (int256) {
        require(_getIdentifierWhitelist().isIdentifierSupported(identifier));
        Price storage lookup = verifiedPrices[identifier][time];
        require(lookup.isAvailable);
        return lookup.price;
    }

    // Gets the queries that still need verified prices.
    function getPendingQueries() external view returns (QueryPoint[] memory) {
        return requestedPrices;
    }

    function _getIdentifierWhitelist() private view returns (IdentifierWhitelistInterface supportedIdentifiers) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }
}

File 72 of 117: MultiRole.sol
pragma solidity ^0.6.0;


library Exclusive {
    struct RoleMembership {
        address member;
    }

    function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
        return roleMembership.member == memberToCheck;
    }

    function resetMember(RoleMembership storage roleMembership, address newMember) internal {
        require(newMember != address(0x0), "Cannot set an exclusive role to 0x0");
        roleMembership.member = newMember;
    }

    function getMember(RoleMembership storage roleMembership) internal view returns (address) {
        return roleMembership.member;
    }

    function init(RoleMembership storage roleMembership, address initialMember) internal {
        resetMember(roleMembership, initialMember);
    }
}


library Shared {
    struct RoleMembership {
        mapping(address => bool) members;
    }

    function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
        return roleMembership.members[memberToCheck];
    }

    function addMember(RoleMembership storage roleMembership, address memberToAdd) internal {
        require(memberToAdd != address(0x0), "Cannot add 0x0 to a shared role");
        roleMembership.members[memberToAdd] = true;
    }

    function removeMember(RoleMembership storage roleMembership, address memberToRemove) internal {
        roleMembership.members[memberToRemove] = false;
    }

    function init(RoleMembership storage roleMembership, address[] memory initialMembers) internal {
        for (uint256 i = 0; i < initialMembers.length; i++) {
            addMember(roleMembership, initialMembers[i]);
        }
    }
}


/**
 * @title Base class to manage permissions for the derived class.
 */
abstract contract MultiRole {
    using Exclusive for Exclusive.RoleMembership;
    using Shared for Shared.RoleMembership;

    enum RoleType { Invalid, Exclusive, Shared }

    struct Role {
        uint256 managingRole;
        RoleType roleType;
        Exclusive.RoleMembership exclusiveRoleMembership;
        Shared.RoleMembership sharedRoleMembership;
    }

    mapping(uint256 => Role) private roles;

    event ResetExclusiveMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
    event AddedSharedMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
    event RemovedSharedMember(uint256 indexed roleId, address indexed oldMember, address indexed manager);

    /**
     * @notice Reverts unless the caller is a member of the specified roleId.
     */
    modifier onlyRoleHolder(uint256 roleId) {
        require(holdsRole(roleId, msg.sender), "Sender does not hold required role");
        _;
    }

    /**
     * @notice Reverts unless the caller is a member of the manager role for the specified roleId.
     */
    modifier onlyRoleManager(uint256 roleId) {
        require(holdsRole(roles[roleId].managingRole, msg.sender), "Can only be called by a role manager");
        _;
    }

    /**
     * @notice Reverts unless the roleId represents an initialized, exclusive roleId.
     */
    modifier onlyExclusive(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Exclusive, "Must be called on an initialized Exclusive role");
        _;
    }

    /**
     * @notice Reverts unless the roleId represents an initialized, shared roleId.
     */
    modifier onlyShared(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Shared, "Must be called on an initialized Shared role");
        _;
    }

    /**
     * @notice Whether `memberToCheck` is a member of roleId.
     * @dev Reverts if roleId does not correspond to an initialized role.
     * @param roleId the Role to check.
     * @param memberToCheck the address to check.
     * @return True if `memberToCheck` is a member of `roleId`.
     */
    function holdsRole(uint256 roleId, address memberToCheck) public view returns (bool) {
        Role storage role = roles[roleId];
        if (role.roleType == RoleType.Exclusive) {
            return role.exclusiveRoleMembership.isMember(memberToCheck);
        } else if (role.roleType == RoleType.Shared) {
            return role.sharedRoleMembership.isMember(memberToCheck);
        }
        revert("Invalid roleId");
    }

    /**
     * @notice Changes the exclusive role holder of `roleId` to `newMember`.
     * @dev Reverts if the caller is not a member of the managing role for `roleId` or if `roleId` is not an
     * initialized, ExclusiveRole.
     * @param roleId the ExclusiveRole membership to modify.
     * @param newMember the new ExclusiveRole member.
     */
    function resetMember(uint256 roleId, address newMember) public onlyExclusive(roleId) onlyRoleManager(roleId) {
        roles[roleId].exclusiveRoleMembership.resetMember(newMember);
        emit ResetExclusiveMember(roleId, newMember, msg.sender);
    }

    /**
     * @notice Gets the current holder of the exclusive role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, exclusive role.
     * @param roleId the ExclusiveRole membership to check.
     * @return the address of the current ExclusiveRole member.
     */
    function getMember(uint256 roleId) public view onlyExclusive(roleId) returns (address) {
        return roles[roleId].exclusiveRoleMembership.getMember();
    }

    /**
     * @notice Adds `newMember` to the shared role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
     * managing role for `roleId`.
     * @param roleId the SharedRole membership to modify.
     * @param newMember the new SharedRole member.
     */
    function addMember(uint256 roleId, address newMember) public onlyShared(roleId) onlyRoleManager(roleId) {
        roles[roleId].sharedRoleMembership.addMember(newMember);
        emit AddedSharedMember(roleId, newMember, msg.sender);
    }

    /**
     * @notice Removes `memberToRemove` from the shared role, `roleId`.
     * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
     * managing role for `roleId`.
     * @param roleId the SharedRole membership to modify.
     * @param memberToRemove the current SharedRole member to remove.
     */
    function removeMember(uint256 roleId, address memberToRemove) public onlyShared(roleId) onlyRoleManager(roleId) {
        roles[roleId].sharedRoleMembership.removeMember(memberToRemove);
        emit RemovedSharedMember(roleId, memberToRemove, msg.sender);
    }

    /**
     * @notice Removes caller from the role, `roleId`.
     * @dev Reverts if the caller is not a member of the role for `roleId` or if `roleId` is not an
     * initialized, SharedRole.
     * @param roleId the SharedRole membership to modify.
     */
    function renounceMembership(uint256 roleId) public onlyShared(roleId) onlyRoleHolder(roleId) {
        roles[roleId].sharedRoleMembership.removeMember(msg.sender);
        emit RemovedSharedMember(roleId, msg.sender, msg.sender);
    }

    /**
     * @notice Reverts if `roleId` is not initialized.
     */
    modifier onlyValidRole(uint256 roleId) {
        require(roles[roleId].roleType != RoleType.Invalid, "Attempted to use an invalid roleId");
        _;
    }

    /**
     * @notice Reverts if `roleId` is initialized.
     */
    modifier onlyInvalidRole(uint256 roleId) {
        require(roles[roleId].roleType == RoleType.Invalid, "Cannot use a pre-existing role");
        _;
    }

    /**
     * @notice Internal method to initialize a shared role, `roleId`, which will be managed by `managingRoleId`.
     * `initialMembers` will be immediately added to the role.
     * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
     * initialized.
     */
    function _createSharedRole(
        uint256 roleId,
        uint256 managingRoleId,
        address[] memory initialMembers
    ) internal onlyInvalidRole(roleId) {
        Role storage role = roles[roleId];
        role.roleType = RoleType.Shared;
        role.managingRole = managingRoleId;
        role.sharedRoleMembership.init(initialMembers);
        require(
            roles[managingRoleId].roleType != RoleType.Invalid,
            "Attempted to use an invalid role to manage a shared role"
        );
    }

    /**
     * @notice Internal method to initialize an exclusive role, `roleId`, which will be managed by `managingRoleId`.
     * `initialMember` will be immediately added to the role.
     * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
     * initialized.
     */
    function _createExclusiveRole(
        uint256 roleId,
        uint256 managingRoleId,
        address initialMember
    ) internal onlyInvalidRole(roleId) {
        Role storage role = roles[roleId];
        role.roleType = RoleType.Exclusive;
        role.managingRole = managingRoleId;
        role.exclusiveRoleMembership.init(initialMember);
        require(
            roles[managingRoleId].roleType != RoleType.Invalid,
            "Attempted to use an invalid role to manage an exclusive role"
        );
    }
}

File 73 of 117: MultiRoleTest.sol
/*
  MultiRoleTest contract.
*/

pragma solidity ^0.6.0;

import "./MultiRole.sol";


// The purpose of this contract is to make the MultiRole creation methods externally callable for testing purposes.
contract MultiRoleTest is MultiRole {
    function createSharedRole(
        uint256 roleId,
        uint256 managingRoleId,
        address[] calldata initialMembers
    ) external {
        _createSharedRole(roleId, managingRoleId, initialMembers);
    }

    function createExclusiveRole(
        uint256 roleId,
        uint256 managingRoleId,
        address initialMember
    ) external {
        _createExclusiveRole(roleId, managingRoleId, initialMember);
    }

    // solhint-disable-next-line no-empty-blocks
    function revertIfNotHoldingRole(uint256 roleId) external view onlyRoleHolder(roleId) {}
}

File 74 of 117: OracleInterface.sol
pragma solidity ^0.6.0;


/**
 * @title Financial contract facing Oracle interface.
 * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
 */
interface OracleInterface {
    /**
     * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     */
    function requestPrice(bytes32 identifier, uint256 time) external;

    /**
     * @notice Whether the price for `identifier` and `time` is available.
     * @dev Time must be in the past and the identifier must be supported.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
     */
    function hasPrice(bytes32 identifier, uint256 time) external view returns (bool);

    /**
     * @notice Gets the price for `identifier` and `time` if it has already been requested and resolved.
     * @dev If the price is not available, the method reverts.
     * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
     * @param time unix timestamp for the price request.
     * @return int256 representing the resolved price for the given identifier and timestamp.
     */
    function getPrice(bytes32 identifier, uint256 time) external view returns (int256);
}

File 75 of 117: Ownable.sol
pragma solidity ^0.6.0;

import "./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.
 */
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 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;
    }
}

File 76 of 117: Pausable.sol
pragma solidity ^0.6.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.
 */
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 returns (bool) {
        return _paused;
    }

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

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

    /**
     * @dev Triggers stopped state.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 77 of 117: PaymentSplitter.sol
pragma solidity ^0.6.0;

import "./Context.sol";
import "./SafeMath.sol";

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 */
contract PaymentSplitter is Context {
    using SafeMath for uint256;

    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor (address[] memory payees, uint256[] memory shares) public payable {
        // solhint-disable-next-line max-line-length
        require(payees.length == shares.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive () external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = address(this).balance.add(_totalReleased);
        uint256 payment = totalReceived.mul(_shares[account]).div(_totalShares).sub(_released[account]);

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] = _released[account].add(payment);
        _totalReleased = _totalReleased.add(payment);

        account.transfer(payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares.add(shares_);
        emit PayeeAdded(account, shares_);
    }
}

File 78 of 117: PriceFeedInterface.sol
pragma solidity ^0.6.0;


/**
 * @title This interface allows contracts to query unverified prices.
 */
interface PriceFeedInterface {
    /**
     * @notice An event fired when a price is published.
     */
    event PriceUpdated(bytes32 indexed identifier, uint256 indexed time, int256 price);

    /**
     * @notice Whether this PriceFeeds provides prices for the given identifier.
     */
    function isIdentifierSupported(bytes32 identifier) external view returns (bool isSupported);

    /**
     * @notice Gets the latest time-price pair at which a price was published.
     * @dev Will revert if no prices have been published for this identifier.
     */
    function latestPrice(bytes32 identifier) external view returns (uint256 publishTime, int256 price);
}

File 79 of 117: PricelessPositionManager.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./SafeMath.sol";
import "./IERC20.sol";
import "./SafeERC20.sol";

import "./FixedPoint.sol";
import "./ExpandedIERC20.sol";

import "./OracleInterface.sol";
import "./IdentifierWhitelistInterface.sol";
import "./AdministrateeInterface.sol";
import "./Constants.sol";

import "./TokenFactory.sol";
import "./FeePayer.sol";


/**
 * @title Financial contract with priceless position management.
 * @notice Handles positions for multiple sponsors in an optimistic (i.e., priceless) way without relying
 * on a price feed. On construction, deploys a new ERC20, managed by this contract, that is the synthetic token.
 */

contract PricelessPositionManager is FeePayer, AdministrateeInterface {
    using SafeMath for uint256;
    using FixedPoint for FixedPoint.Unsigned;
    using SafeERC20 for IERC20;
    using SafeERC20 for ExpandedIERC20;

    /****************************************
     *  PRICELESS POSITION DATA STRUCTURES  *
     ****************************************/

    // Enum to store the state of the PricelessPositionManager. Set on expiration or emergency shutdown.
    enum ContractState { Open, ExpiredPriceRequested, ExpiredPriceReceived }
    ContractState public contractState;

    // Represents a single sponsor's position. All collateral is held by this contract.
    // This struct acts is bookkeeping for how much of that collateral is allocated to each sponsor.
    struct PositionData {
        FixedPoint.Unsigned tokensOutstanding;
        // Tracks pending withdrawal requests. A withdrawal request is pending if `requestPassTimestamp != 0`.
        uint256 requestPassTimestamp;
        FixedPoint.Unsigned withdrawalRequestAmount;
        // Raw collateral value. This value should never be accessed directly -- always use _getCollateral().
        // To add or remove collateral, use _addCollateral() and _removeCollateral().
        FixedPoint.Unsigned rawCollateral;
    }

    // Maps sponsor addresses to their positions. Each sponsor can have only one position.
    mapping(address => PositionData) public positions;

    // Keep track of the total collateral and tokens across all positions to enable calculating the
    // global collateralization ratio without iterating over all positions.
    FixedPoint.Unsigned public totalTokensOutstanding;

    // Similar to the rawCollateral in PositionData, this value should not be used directly.
    // _getCollateral(), _addCollateral() and _removeCollateral() must be used to access and adjust.
    FixedPoint.Unsigned public rawTotalPositionCollateral;

    // Synthetic token created by this contract.
    ExpandedIERC20 public tokenCurrency;

    // Unique identifier for DVM price feed ticker.
    bytes32 public priceIdentifer;
    // Time that this contract expires. Should not change post-construction unless a emergency shutdown occurs.
    uint256 public expirationTimestamp;
    // Time that has to elapse for a withdrawal request to be considered passed, if no liquidations occur.
    uint256 public withdrawalLiveness;

    // Minimum number of tokens in a sponsor's position.
    FixedPoint.Unsigned public minSponsorTokens;

    // The expiry price pulled from the DVM.
    FixedPoint.Unsigned public expiryPrice;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event Transfer(address indexed oldSponsor, address indexed newSponsor);
    event Deposit(address indexed sponsor, uint256 indexed collateralAmount);
    event Withdrawal(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawal(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawalExecuted(address indexed sponsor, uint256 indexed collateralAmount);
    event RequestWithdrawalCanceled(address indexed sponsor, uint256 indexed collateralAmount);
    event PositionCreated(address indexed sponsor, uint256 indexed collateralAmount, uint256 indexed tokenAmount);
    event NewSponsor(address indexed sponsor);
    event EndedSponsor(address indexed sponsor);
    event Redeem(address indexed sponsor, uint256 indexed collateralAmount, uint256 indexed tokenAmount);
    event ContractExpired(address indexed caller);
    event SettleExpiredPosition(
        address indexed caller,
        uint256 indexed collateralReturned,
        uint256 indexed tokensBurned
    );
    event EmergencyShutdown(address indexed caller, uint256 originalExpirationTimestamp, uint256 shutdownTimestamp);

    /****************************************
     *               MODIFIERS              *
     ****************************************/

    modifier onlyPreExpiration() {
        _onlyPreExpiration();
        _;
    }

    modifier onlyPostExpiration() {
        _onlyPostExpiration();
        _;
    }

    modifier onlyCollateralizedPosition(address sponsor) {
        _onlyCollateralizedPosition(sponsor);
        _;
    }

    // Check that the current state of the pricelessPositionManager is Open.
    // This prevents multiple calls to `expire` and `EmergencyShutdown` post expiration.
    modifier onlyOpenState() {
        _onlyOpenState();
        _;
    }

    /**
     * @notice Construct the PricelessPositionManager
     * @param _expirationTimestamp unix timestamp of when the contract will expire.
     * @param _withdrawalLiveness liveness delay, in seconds, for pending withdrawals.
     * @param _collateralAddress ERC20 token used as collateral for all positions.
     * @param _finderAddress UMA protocol Finder used to discover other protocol contracts.
     * @param _priceIdentifier registered in the DVM for the synthetic.
     * @param _syntheticName name for the token contract that will be deployed.
     * @param _syntheticSymbol symbol for the token contract that will be deployed.
     * @param _tokenFactoryAddress deployed UMA token factory to create the synthetic token.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(
        uint256 _expirationTimestamp,
        uint256 _withdrawalLiveness,
        address _collateralAddress,
        address _finderAddress,
        bytes32 _priceIdentifier,
        string memory _syntheticName,
        string memory _syntheticSymbol,
        address _tokenFactoryAddress,
        FixedPoint.Unsigned memory _minSponsorTokens,
        address _timerAddress
    ) public FeePayer(_collateralAddress, _finderAddress, _timerAddress) {
        expirationTimestamp = _expirationTimestamp;
        withdrawalLiveness = _withdrawalLiveness;
        TokenFactory tf = TokenFactory(_tokenFactoryAddress);
        tokenCurrency = tf.createToken(_syntheticName, _syntheticSymbol, 18);
        minSponsorTokens = _minSponsorTokens;

        require(_getIdentifierWhitelist().isIdentifierSupported(_priceIdentifier));

        priceIdentifer = _priceIdentifier;
    }

    /****************************************
     *          POSITION FUNCTIONS          *
     ****************************************/

    /**
     * @notice Transfers ownership of the caller's current position to `newSponsorAddress`.
     * @dev Transferring positions can only occur if the recipient does not already have a position.
     * @param newSponsorAddress is the address to which the position will be transferred.
     */
    function transfer(address newSponsorAddress) public onlyPreExpiration() {
        require(_getCollateral(positions[newSponsorAddress].rawCollateral).isEqual(FixedPoint.fromUnscaledUint(0)));
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp == 0);
        positions[newSponsorAddress] = positionData;
        delete positions[msg.sender];

        emit Transfer(msg.sender, newSponsorAddress);
        emit NewSponsor(newSponsorAddress);
    }

    /**
     * @notice Transfers `collateralAmount` of `collateralCurrency` into the sponsor's position.
     * @dev Increases the collateralization level of a position after creation.
     * @param collateralAmount total amount of collateral tokens to be sent to the sponsor's position.
     */
    function deposit(FixedPoint.Unsigned memory collateralAmount) public onlyPreExpiration() fees() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp == 0);
        _addCollateral(positionData.rawCollateral, collateralAmount);
        _addCollateral(rawTotalPositionCollateral, collateralAmount);

        // Move collateral currency from sender to contract.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), collateralAmount.rawValue);

        emit Deposit(msg.sender, collateralAmount.rawValue);
    }

    /**
     * @notice Transfers `collateralAmount` of `collateralCurrency` from the sponsor's position to the sponsor.
     * @dev Reverts if the withdrawal puts this position's collateralization ratio below the global
     * collateralization ratio. In that case, use `requestWithdrawawal`. Might not withdraw the full requested
     * amount in order to account for precision loss.
     * @param collateralAmount is the amount of collateral to withdraw.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function withdraw(FixedPoint.Unsigned memory collateralAmount)
        public
        onlyPreExpiration()
        fees()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp == 0);

        _removeCollateral(positionData.rawCollateral, collateralAmount);
        require(_checkPositionCollateralization(positionData));
        // We elect to withdraw the amount that the global collateral is decreased by,
        // rather than the individual position's collateral, because we need to maintain the invariant that
        // the global collateral is always <= the collateral owned by the contract to avoid reverts on withdrawals.
        amountWithdrawn = _removeCollateral(rawTotalPositionCollateral, collateralAmount);

        // Move collateral currency from contract to sender.
        // Note that we move the amount of collateral that is decreased from rawCollateral (inclusive of fees)
        // instead of the user requested amount. This eliminates precision loss that could occur
        // where the user withdraws more collateral than rawCollateral is decremented by.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);

        emit Withdrawal(msg.sender, amountWithdrawn.rawValue);
    }

    /**
     * @notice Starts a withdrawal request that, if passed, allows the sponsor to withdraw
     * `collateralAmount` from their position.
     * @dev The request will be pending for `withdrawalLiveness`, during which the position can be liquidated.
     * @param collateralAmount the amount of collateral requested to withdraw
     */
    function requestWithdrawal(FixedPoint.Unsigned memory collateralAmount) public onlyPreExpiration() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp == 0);

        // Make sure the proposed expiration of this request is not post-expiry.
        uint256 requestPassTime = getCurrentTime() + withdrawalLiveness;
        require(requestPassTime <= expirationTimestamp);

        // Update the position object for the user.
        positionData.requestPassTimestamp = requestPassTime;
        positionData.withdrawalRequestAmount = collateralAmount;

        emit RequestWithdrawal(msg.sender, collateralAmount.rawValue);
    }

    /**
     * @notice After a passed withdrawal request (i.e., by a call to `requestWithdrawal` and waiting
     * `withdrawalLiveness`), withdraws `positionData.withdrawalRequestAmount` of collateral currency.
     * @dev Might not withdraw the full requested amount in order to account for precision loss.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    // TODO: Decide whether to fold this functionality into withdraw() method above.
    function withdrawPassedRequest()
        external
        onlyPreExpiration()
        fees()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp <= getCurrentTime());

        // If withdrawal request amount is > position collateral, then withdraw the full collateral amount.
        FixedPoint.Unsigned memory amountToWithdraw = positionData.withdrawalRequestAmount;
        if (positionData.withdrawalRequestAmount.isGreaterThan(_getCollateral(positionData.rawCollateral))) {
            amountToWithdraw = _getCollateral(positionData.rawCollateral);
        }

        _removeCollateral(positionData.rawCollateral, amountToWithdraw);
        amountWithdrawn = _removeCollateral(rawTotalPositionCollateral, amountToWithdraw);

        // Transfer approved withdrawal amount from the contract to the caller.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);

        emit RequestWithdrawalExecuted(msg.sender, amountWithdrawn.rawValue);

        // Reset withdrawal request
        positionData.withdrawalRequestAmount = FixedPoint.fromUnscaledUint(0);
        positionData.requestPassTimestamp = 0;
    }

    /**
     * @notice Cancels a pending withdrawal request.
     */
    function cancelWithdrawal() external onlyPreExpiration() {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp != 0);

        emit RequestWithdrawalCanceled(msg.sender, positionData.withdrawalRequestAmount.rawValue);

        // Reset withdrawal request
        positionData.requestPassTimestamp = 0;
        positionData.withdrawalRequestAmount = FixedPoint.fromUnscaledUint(0);
    }

    /**
     * @notice Pulls `collateralAmount` into the sponsor's position and mints `numTokens` of `tokenCurrency`.
     * @dev Reverts if the minting these tokens would put the position's collateralization ratio below the
     * global collateralization ratio.
     * @param collateralAmount is the number of collateral tokens to collateralize the position with
     * @param numTokens is the number of tokens to mint from the position.
     */
    function create(FixedPoint.Unsigned memory collateralAmount, FixedPoint.Unsigned memory numTokens)
        public
        onlyPreExpiration()
        fees()
    {
        require(_checkCollateralization(collateralAmount, numTokens));

        PositionData storage positionData = positions[msg.sender];
        require(positionData.requestPassTimestamp == 0);
        if (positionData.tokensOutstanding.isEqual(0)) {
            require(numTokens.isGreaterThanOrEqual(minSponsorTokens));
            emit NewSponsor(msg.sender);
        }
        _addCollateral(positionData.rawCollateral, collateralAmount);
        positionData.tokensOutstanding = positionData.tokensOutstanding.add(numTokens);

        _addCollateral(rawTotalPositionCollateral, collateralAmount);
        totalTokensOutstanding = totalTokensOutstanding.add(numTokens);

        // Transfer tokens into the contract from caller and mint the caller synthetic tokens.
        collateralCurrency.safeTransferFrom(msg.sender, address(this), collateralAmount.rawValue);
        require(tokenCurrency.mint(msg.sender, numTokens.rawValue), "Minting synthetic tokens failed");

        emit PositionCreated(msg.sender, collateralAmount.rawValue, numTokens.rawValue);
    }

    /**
     * @notice Burns `numTokens` of `tokenCurrency` and sends back the proportional amount of `collateralCurrency`.
     * @dev Can only be called by a token sponsor. Might not redeem the full proportional amount of collateral
     * in order to account for precision loss.
     * @param numTokens is the number of tokens to be burnt for a commensurate amount of collateral.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function redeem(FixedPoint.Unsigned memory numTokens)
        public
        onlyPreExpiration()
        fees()
        returns (FixedPoint.Unsigned memory amountWithdrawn)
    {
        PositionData storage positionData = _getPositionData(msg.sender);
        require(positionData.requestPassTimestamp == 0);
        require(!numTokens.isGreaterThan(positionData.tokensOutstanding));

        FixedPoint.Unsigned memory fractionRedeemed = numTokens.div(positionData.tokensOutstanding);
        FixedPoint.Unsigned memory collateralRedeemed = fractionRedeemed.mul(
            _getCollateral(positionData.rawCollateral)
        );

        // If redemption returns all tokens the sponsor has then we can delete their position. Else, downsize.
        if (positionData.tokensOutstanding.isEqual(numTokens)) {
            amountWithdrawn = _deleteSponsorPosition(msg.sender);
        } else {
            // Decrease the sponsors position size of collateral and tokens.
            _removeCollateral(positionData.rawCollateral, collateralRedeemed);
            FixedPoint.Unsigned memory newTokenCount = positionData.tokensOutstanding.sub(numTokens);
            require(newTokenCount.isGreaterThanOrEqual(minSponsorTokens));
            positionData.tokensOutstanding = newTokenCount;

            // Decrease the contract's collateral and tokens.
            amountWithdrawn = _removeCollateral(rawTotalPositionCollateral, collateralRedeemed);
            totalTokensOutstanding = totalTokensOutstanding.sub(numTokens);
        }

        // Transfer collateral from contract to caller and burn callers synthetic tokens.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);
        tokenCurrency.safeTransferFrom(msg.sender, address(this), numTokens.rawValue);
        tokenCurrency.burn(numTokens.rawValue);

        emit Redeem(msg.sender, amountWithdrawn.rawValue, numTokens.rawValue);
    }

    /**
     * @notice After a contract has passed expiry all token holders can redeem their tokens for
     * underlying at the prevailing price defined by the DVM from the `expire` function.
     * @dev This Burns all tokens from the caller of `tokenCurrency` and sends back the proportional
     * amount of `collateralCurrency`. Might not redeem the full proportional amount of collateral
     * in order to account for precision loss.
     * @return amountWithdrawn The actual amount of collateral withdrawn.
     */
    function settleExpired() external onlyPostExpiration() fees() returns (FixedPoint.Unsigned memory amountWithdrawn) {
        // If the contract state is open and onlyPostExpiration passed then `expire()` has not yet been called.
        require(contractState != ContractState.Open);

        // Get the current settlement price and store it. If it is not resolved will revert.
        if (contractState != ContractState.ExpiredPriceReceived) {
            expiryPrice = _getOraclePrice(expirationTimestamp);
            contractState = ContractState.ExpiredPriceReceived;
        }

        // Get caller's tokens balance and calculate amount of underlying entitled to them.
        FixedPoint.Unsigned memory tokensToRedeem = FixedPoint.Unsigned(tokenCurrency.balanceOf(msg.sender));
        FixedPoint.Unsigned memory totalRedeemableCollateral = tokensToRedeem.mul(expiryPrice);

        // If the caller is a sponsor with outstanding collateral they are also entitled to their excess collateral after their debt.
        PositionData storage positionData = positions[msg.sender];
        if (_getCollateral(positionData.rawCollateral).isGreaterThan(0)) {
            // Calculate the underlying entitled to a token sponsor. This is collateral - debt in underlying.
            FixedPoint.Unsigned memory tokenDebtValueInCollateral = positionData.tokensOutstanding.mul(expiryPrice);
            FixedPoint.Unsigned memory positionCollateral = _getCollateral(positionData.rawCollateral);

            // If the debt is greater than the remaining collateral, they cannot redeem anything.
            FixedPoint.Unsigned memory positionRedeemableCollateral = tokenDebtValueInCollateral.isLessThan(
                positionCollateral
            )
                ? positionCollateral.sub(tokenDebtValueInCollateral)
                : FixedPoint.Unsigned(0);

            // Add the number of redeemable tokens for the sponsor to their total redeemable collateral.
            totalRedeemableCollateral = totalRedeemableCollateral.add(positionRedeemableCollateral);

            // Reset the position state as all the value has been removed after settlement.
            delete positions[msg.sender];
        }

        // Take the min of the remaining collateral and the collateral "owed". If the contract is undercapitalized,
        // the caller will get as much collateral as the contract can pay out.
        FixedPoint.Unsigned memory payout = FixedPoint.min(
            _getCollateral(rawTotalPositionCollateral),
            totalRedeemableCollateral
        );

        // Decrement total contract collateral and outstanding debt.
        amountWithdrawn = _removeCollateral(rawTotalPositionCollateral, payout);
        totalTokensOutstanding = totalTokensOutstanding.sub(tokensToRedeem);

        // Transfer tokens & collateral and burn the redeemed tokens.
        collateralCurrency.safeTransfer(msg.sender, amountWithdrawn.rawValue);
        tokenCurrency.safeTransferFrom(msg.sender, address(this), tokensToRedeem.rawValue);
        tokenCurrency.burn(tokensToRedeem.rawValue);

        emit SettleExpiredPosition(msg.sender, amountWithdrawn.rawValue, tokensToRedeem.rawValue);
    }

    /****************************************
     *        GLOBAL STATE FUNCTIONS        *
     ****************************************/

    /**
     * @notice Locks contract state in expired and requests oracle price.
     * @dev this function can only be called once the contract is expired and cant be re-called
     * due to the state modifiers applied on it.
     */
    function expire() external onlyPostExpiration() onlyOpenState() fees() {
        contractState = ContractState.ExpiredPriceRequested;

        // The final fee for this request is paid out of the contract rather than by the caller.
        _payFinalFees(address(this), _computeFinalFees());
        _requestOraclePrice(expirationTimestamp);

        emit ContractExpired(msg.sender);
    }

    /**
     * @notice Premature contract settlement under emergency circumstances.
     * @dev Only the governor can call this function as they are permissioned within the `FinancialContractAdmin`.
     * Upon emergency shutdown, the contract settlement time is set to the shutdown time. This enables withdrawal
     * to occur via the standard `settleExpired` function. Contract state is set to `ExpiredPriceRequested`
     * which prevents re-entry into this function or the `expire` function. No fees are paid when calling
     * `emergencyShutdown` as the governor who would call the function would also receive the fees.
     */
    function emergencyShutdown() external override onlyPreExpiration() onlyOpenState() {
        require(msg.sender == _getFinancialContractsAdminAddress());

        contractState = ContractState.ExpiredPriceRequested;
        // Expiratory time now becomes the current time (emergency shutdown time).
        // Price requested at this time stamp. `settleExpired` can now withdraw at this timestamp.
        uint256 oldExpirationTimestamp = expirationTimestamp;
        expirationTimestamp = getCurrentTime();
        _requestOraclePrice(expirationTimestamp);

        emit EmergencyShutdown(msg.sender, oldExpirationTimestamp, expirationTimestamp);
    }

    // TODO is this how we want this function to be implemented?
    function remargin() external override onlyPreExpiration() {
        return;
    }

    /**
     * @notice Accessor method for a sponsor's collateral.
     * @dev This is necessary because the struct returned by the positions() method shows
     * rawCollateral, which isn't a user-readable value.
     * @param sponsor address whose collateral amount is retrieved.
     */
    function getCollateral(address sponsor) external view returns (FixedPoint.Unsigned memory) {
        // Note: do a direct access to avoid the validity check.
        return _getCollateral(positions[sponsor].rawCollateral);
    }

    /**
     * @notice Accessor method for the total collateral stored within the PricelessPositionManager.
     */
    function totalPositionCollateral() external view returns (FixedPoint.Unsigned memory) {
        return _getCollateral(rawTotalPositionCollateral);
    }

    /**
     * @dev This overrides pfc() so the PricelessPositionManager can report its profit from corruption.
     */
    function pfc() public virtual override view returns (FixedPoint.Unsigned memory) {
        return _getCollateral(rawTotalPositionCollateral);
    }

    /****************************************
     *          INTERNAL FUNCTIONS         *
     ****************************************/

    function _reduceSponsorPosition(
        address sponsor,
        FixedPoint.Unsigned memory tokensToRemove,
        FixedPoint.Unsigned memory collateralToRemove,
        FixedPoint.Unsigned memory withdrawalAmountToRemove
    ) internal {
        PositionData storage positionData = _getPositionData(sponsor);

        // If the entire position is being removed, delete it instead.
        if (
            tokensToRemove.isEqual(positionData.tokensOutstanding) &&
            _getCollateral(positionData.rawCollateral).isEqual(collateralToRemove)
        ) {
            _deleteSponsorPosition(sponsor);
            return;
        }

        // Decrease the sponsor's collateral, tokens, and withdrawal request.
        _removeCollateral(positionData.rawCollateral, collateralToRemove);
        FixedPoint.Unsigned memory newTokenCount = positionData.tokensOutstanding.sub(tokensToRemove);
        require(newTokenCount.isGreaterThanOrEqual(minSponsorTokens));
        positionData.tokensOutstanding = newTokenCount;

        positionData.withdrawalRequestAmount = positionData.withdrawalRequestAmount.sub(withdrawalAmountToRemove);

        // Decrease the contract's global counters of collateral and tokens.
        _removeCollateral(rawTotalPositionCollateral, collateralToRemove);
        totalTokensOutstanding = totalTokensOutstanding.sub(tokensToRemove);
    }

    function _deleteSponsorPosition(address sponsor) internal returns (FixedPoint.Unsigned memory) {
        PositionData storage positionToLiquidate = _getPositionData(sponsor);

        FixedPoint.Unsigned memory startingGlobalCollateral = _getCollateral(rawTotalPositionCollateral);

        // Remove the collateral and outstanding from the overall total position.
        FixedPoint.Unsigned memory remainingRawCollateral = positionToLiquidate.rawCollateral;
        rawTotalPositionCollateral = rawTotalPositionCollateral.sub(remainingRawCollateral);
        totalTokensOutstanding = totalTokensOutstanding.sub(positionToLiquidate.tokensOutstanding);

        // Reset the sponsors position to have zero outstanding and collateral.
        delete positions[sponsor];

        emit EndedSponsor(sponsor);

        // Return fee-adjusted amount of collateral deleted from position.
        return startingGlobalCollateral.sub(_getCollateral(rawTotalPositionCollateral));
    }

    function _getPositionData(address sponsor)
        internal
        view
        onlyCollateralizedPosition(sponsor)
        returns (PositionData storage)
    {
        return positions[sponsor];
    }

    function _getIdentifierWhitelist() internal view returns (IdentifierWhitelistInterface) {
        return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
    }

    function _getOracle() internal view returns (OracleInterface) {
        return OracleInterface(finder.getImplementationAddress(OracleInterfaces.Oracle));
    }

    function _getStoreAddress() internal view returns (address) {
        return finder.getImplementationAddress(OracleInterfaces.Store);
    }

    function _getFinancialContractsAdminAddress() internal view returns (address) {
        return finder.getImplementationAddress(OracleInterfaces.FinancialContractsAdmin);
    }

    function _requestOraclePrice(uint256 requestedTime) internal {
        OracleInterface oracle = _getOracle();
        oracle.requestPrice(priceIdentifer, requestedTime);
    }

    function _getOraclePrice(uint256 requestedTime) internal view returns (FixedPoint.Unsigned memory) {
        // Create an instance of the oracle and get the price. If the price is not resolved revert.
        OracleInterface oracle = _getOracle();
        require(oracle.hasPrice(priceIdentifer, requestedTime), "Can only get a price once the DVM has resolved");
        int256 oraclePrice = oracle.getPrice(priceIdentifer, requestedTime);

        // For now we don't want to deal with negative prices in positions.
        if (oraclePrice < 0) {
            oraclePrice = 0;
        }
        return FixedPoint.Unsigned(_safeUintCast(oraclePrice));
    }

    function _checkPositionCollateralization(PositionData storage positionData) private view returns (bool) {
        return _checkCollateralization(_getCollateral(positionData.rawCollateral), positionData.tokensOutstanding);
    }

    function _checkCollateralization(FixedPoint.Unsigned memory collateral, FixedPoint.Unsigned memory numTokens)
        private
        view
        returns (bool)
    {
        FixedPoint.Unsigned memory global = _getCollateralizationRatio(
            _getCollateral(rawTotalPositionCollateral),
            totalTokensOutstanding
        );
        FixedPoint.Unsigned memory thisChange = _getCollateralizationRatio(collateral, numTokens);
        return !global.isGreaterThan(thisChange);
    }

    function _getCollateralizationRatio(FixedPoint.Unsigned memory collateral, FixedPoint.Unsigned memory numTokens)
        private
        pure
        returns (FixedPoint.Unsigned memory ratio)
    {
        if (!numTokens.isGreaterThan(0)) {
            return FixedPoint.fromUnscaledUint(0);
        } else {
            return collateral.div(numTokens);
        }
    }

    function _safeUintCast(int256 value) private pure returns (uint256 result) {
        require(value >= 0, "uint256 underflow");
        return uint256(value);
    }

    /**
     * @dev These internal functions are supposed to act identically to modifiers, but re-used modifiers
     * unnecessarily increase contract bytecode size.
     * source: https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6
     */
    function _onlyOpenState() internal view {
        require(contractState == ContractState.Open);
    }

    function _onlyPreExpiration() internal view {
        require(getCurrentTime() < expirationTimestamp);
    }

    function _onlyPostExpiration() internal view {
        require(getCurrentTime() >= expirationTimestamp);
    }

    function _onlyCollateralizedPosition(address sponsor) internal view {
        require(_getCollateral(positions[sponsor].rawCollateral).isGreaterThan(0));
    }
}

File 80 of 117: PullPayment.sol
pragma solidity ^0.6.2;

import "./Escrow.sol";

/**
 * @dev Simple implementation of a
 * https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls[pull-payment]
 * strategy, where the paying contract doesn't interact directly with the
 * receiver account, which must withdraw its payments itself.
 *
 * Pull-payments are often considered the best practice when it comes to sending
 * Ether, security-wise. It prevents recipients from blocking execution, and
 * eliminates reentrancy concerns.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 *
 * To use, derive from the `PullPayment` contract, and use {_asyncTransfer}
 * instead of Solidity's `transfer` function. Payees can query their due
 * payments with {payments}, and retrieve them with {withdrawPayments}.
 */
contract PullPayment {
    Escrow private _escrow;

    constructor () internal {
        _escrow = new Escrow();
    }

    /**
     * @dev Withdraw accumulated payments, forwarding all gas to the recipient.
     *
     * Note that _any_ account can call this function, not just the `payee`.
     * This means that contracts unaware of the `PullPayment` protocol can still
     * receive funds this way, by having a separate account call
     * {withdrawPayments}.
     *
     * WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
     * Make sure you trust the recipient, or are either following the
     * checks-effects-interactions pattern or using {ReentrancyGuard}.
     *
     * @param payee Whose payments will be withdrawn.
     */
    function withdrawPayments(address payable payee) public virtual {
        _escrow.withdraw(payee);
    }

    /**
     * @dev Returns the payments owed to an address.
     * @param dest The creditor's address.
     */
    function payments(address dest) public view returns (uint256) {
        return _escrow.depositsOf(dest);
    }

    /**
     * @dev Called by the payer to store the sent amount as credit to be pulled.
     * Funds sent in this way are stored in an intermediate {Escrow} contract, so
     * there is no danger of them being spent before withdrawal.
     *
     * @param dest The destination address of the funds.
     * @param amount The amount to transfer.
     */
    function _asyncTransfer(address dest, uint256 amount) internal virtual {
        // solhint-disable-previous-line no-unused-vars

        // TODO: remove the previous linter directive once
        // https://github.com/protofire/solhint/issues/170 is fixed
        _escrow.deposit{ value: amount }(dest);
    }
}

File 81 of 117: ReentrancyChecker.sol
pragma solidity ^0.6.0;


// The Reentrancy Checker causes failures if it is successfully able to re-enter a contract.
// How to use:
// 1. Call setTransactionData with the transaction data you want the Reentrancy Checker to reenter the calling
//    contract with.
// 2. Get the calling contract to call into the reentrancy checker with any call. The fallback function will receive
//    this call and reenter the contract with the transaction data provided in 1. If that reentrancy call does not
//    revert, then the reentrancy checker reverts the initial call, likely causeing the entire transaction to revert.
//
// Note: the reentrancy checker has a guard to prevent an infinite cycle of reentrancy. Inifinite cycles will run out
// of gas in all cases, potentially causing a revert when the contract is adequately protected from reentrancy.
contract ReentrancyChecker {
    bytes public txnData;
    bool hasBeenCalled;

    // Used to prevent infinite cycles where the reentrancy is cycled forever.
    modifier skipIfReentered {
        if (hasBeenCalled) {
            return;
        }
        hasBeenCalled = true;
        _;
        hasBeenCalled = false;
    }

    function setTransactionData(bytes memory _txnData) public {
        txnData = _txnData;
    }

    function _executeCall(
        address to,
        uint256 value,
        bytes memory data
    ) private returns (bool success) {
        // Mostly copied from:
        // solhint-disable-next-line max-line-length
        // https://github.com/gnosis/safe-contracts/blob/59cfdaebcd8b87a0a32f87b50fead092c10d3a05/contracts/base/Executor.sol#L23-L31
        // solhint-disable-next-line no-inline-assembly

        assembly {
            let inputData := add(data, 0x20)
            let inputDataSize := mload(data)
            success := call(gas(), to, value, inputData, inputDataSize, 0, 0)
        }
    }

    fallback() external skipIfReentered {
        // Attampt to re-enter with the set txnData.
        bool success = _executeCall(msg.sender, 0, txnData);

        // Fail if the call succeeds because that means the re-entrancy was successful.
        require(!success, "Re-entrancy was successful");
    }
}

File 82 of 117: ReentrancyGuard.sol
pragma solidity ^0.6.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
contract ReentrancyGuard {
    bool private _notEntered;

    constructor () internal {
        // Storing an initial non-zero value makes deployment a bit more
        // expensive, but in exchange the refund on every call to nonReentrant
        // will be lower in amount. Since refunds are capped to a percetange of
        // the total transaction's gas, it is best to keep them low in cases
        // like this one, to increase the likelihood of the full refund coming
        // into effect.
        _notEntered = true;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_notEntered, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _notEntered = false;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _notEntered = true;
    }
}

File 83 of 117: RefundEscrow.sol
pragma solidity ^0.6.0;

import "./ConditionalEscrow.sol";

/**
 * @title RefundEscrow
 * @dev Escrow that holds funds for a beneficiary, deposited from multiple
 * parties.
 * @dev Intended usage: See {Escrow}. Same usage guidelines apply here.
 * @dev The owner account (that is, the contract that instantiates this
 * contract) may deposit, close the deposit period, and allow for either
 * withdrawal by the beneficiary, or refunds to the depositors. All interactions
 * with `RefundEscrow` will be made through the owner contract.
 */
contract RefundEscrow is ConditionalEscrow {
    enum State { Active, Refunding, Closed }

    event RefundsClosed();
    event RefundsEnabled();

    State private _state;
    address payable private _beneficiary;

    /**
     * @dev Constructor.
     * @param beneficiary The beneficiary of the deposits.
     */
    constructor (address payable beneficiary) public {
        require(beneficiary != address(0), "RefundEscrow: beneficiary is the zero address");
        _beneficiary = beneficiary;
        _state = State.Active;
    }

    /**
     * @return The current state of the escrow.
     */
    function state() public view returns (State) {
        return _state;
    }

    /**
     * @return The beneficiary of the escrow.
     */
    function beneficiary() public view returns (address) {
        return _beneficiary;
    }

    /**
     * @dev Stores funds that may later be refunded.
     * @param refundee The address funds will be sent to if a refund occurs.
     */
    function deposit(address refundee) public payable virtual override {
        require(_state == State.Active, "RefundEscrow: can only deposit while active");
        super.deposit(refundee);
    }

    /**
     * @dev Allows for the beneficiary to withdraw their funds, rejecting
     * further deposits.
     */
    function close() public onlyOwner virtual {
        require(_state == State.Active, "RefundEscrow: can only close while active");
        _state = State.Closed;
        emit RefundsClosed();
    }

    /**
     * @dev Allows for refunds to take place, rejecting further deposits.
     */
    function enableRefunds() public onlyOwner virtual {
        require(_state == State.Active, "RefundEscrow: can only enable refunds while active");
        _state = State.Refunding;
        emit RefundsEnabled();
    }

    /**
     * @dev Withdraws the beneficiary's funds.
     */
    function beneficiaryWithdraw() public virtual {
        require(_state == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
        _beneficiary.transfer(address(this).balance);
    }

    /**
     * @dev Returns whether refundees can withdraw their deposits (be refunded). The overridden function receives a
     * 'payee' argument, but we ignore it here since the condition is global, not per-payee.
     */
    function withdrawalAllowed(address) public view override returns (bool) {
        return _state == State.Refunding;
    }
}

File 84 of 117: Registry.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./MultiRole.sol";
import "./RegistryInterface.sol";

import "./SafeMath.sol";


/**
 * @title Registry for financial contracts and approved financial contract creators.
 * @dev Maintains a whitelist of financial contract creators that are allowed
 * to register new financial contracts and stores party members of a financial contract.
 */
contract Registry is RegistryInterface, MultiRole {
    using SafeMath for uint256;

    /****************************************
     *    INTERNAL VARIABLES AND STORAGE    *
     ****************************************/

    enum Roles {
        Owner, // The owner manages the set of ContractCreators.
        ContractCreator // Can register financial contracts.
    }

    // This enum is required because a `WasValid` state is required
    // to ensure that financial contracts cannot be re-registered.
    enum Validity { Invalid, Valid }

    // Local information about a contract.
    struct FinancialContract {
        Validity valid;
        uint128 index;
    }

    struct Party {
        address[] contracts; // Each financial contract address is stored in this array.
        // The address of each financial contract is mapped to its index for constant time look up and deletion.
        mapping(address => uint256) contractIndex;
    }

    // Array of all contracts that are approved to use the UMA Oracle.
    address[] public registeredContracts;

    // Map of financial contract contracts to the associated FinancialContract struct.
    mapping(address => FinancialContract) public contractMap;

    // Map each party member to their their associated Party struct.
    mapping(address => Party) private partyMap;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event NewContractRegistered(address indexed contractAddress, address indexed creator, address[] parties);
    event PartyAdded(address indexed contractAddress, address indexed party);
    event PartyRemoved(address indexed contractAddress, address indexed party);

    /**
     * @notice Construct the Registry contract.
     */
    constructor() public {
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
        // Start with no contract creators registered.
        _createSharedRole(uint256(Roles.ContractCreator), uint256(Roles.Owner), new address[](0));
    }

    /****************************************
     *        REGISTRATION FUNCTIONS        *
     ****************************************/

    /**
     * @notice Registers a new financial contract.
     * @dev Only authorized contract creators can call this method.
     * @param parties array of addresses who become parties in the contract.
     * @param contractAddress address of the contract against which the parties are registered.
     */
    function registerContract(address[] calldata parties, address contractAddress)
        external
        override
        onlyRoleHolder(uint256(Roles.ContractCreator))
    {
        FinancialContract storage financialContract = contractMap[contractAddress];
        require(contractMap[contractAddress].valid == Validity.Invalid, "Can only register once");

        // Store contract address as a registered contract.
        registeredContracts.push(contractAddress);

        // No length check necessary because we should never hit (2^127 - 1) contracts.
        financialContract.index = uint128(registeredContracts.length.sub(1));

        // For all parties in the array add them to the contract's parties.
        financialContract.valid = Validity.Valid;
        for (uint256 i = 0; i < parties.length; i = i.add(1)) {
            _addPartyToContract(parties[i], contractAddress);
        }

        emit NewContractRegistered(contractAddress, msg.sender, parties);
    }

    /**
     * @notice Adds a party member to the calling contract.
     * @dev msg.sender will be used to determine the contract that this party is added to.
     * @param party new party for the calling contract.
     */
    function addPartyToContract(address party) external override {
        address contractAddress = msg.sender;
        require(contractMap[contractAddress].valid == Validity.Valid, "Can only add to valid contract");

        _addPartyToContract(party, contractAddress);
    }

    /**
     * @notice Removes a party member from the calling contract.
     * @dev msg.sender will be used to determine the contract that this party is removed from.
     * @param partyAddress address to be removed from the calling contract.
     */
    function removePartyFromContract(address partyAddress) external override {
        address contractAddress = msg.sender;
        Party storage party = partyMap[partyAddress];
        uint256 numberOfContracts = party.contracts.length;

        require(numberOfContracts != 0, "Party has no contracts");
        require(contractMap[contractAddress].valid == Validity.Valid, "Remove only from valid contract");
        require(isPartyMemberOfContract(partyAddress, contractAddress), "Can only remove existing party");

        // Index of the current location of the contract to remove.
        uint256 deleteIndex = party.contractIndex[contractAddress];

        // Store the last contract's address to update the lookup map.
        address lastContractAddress = party.contracts[numberOfContracts - 1];

        // Swap the contract to be removed with the last contract.
        party.contracts[deleteIndex] = lastContractAddress;

        // Update the lookup index with the new location.
        party.contractIndex[lastContractAddress] = deleteIndex;

        // Pop the last contract from the array and update the lookup map.
        party.contracts.pop();
        delete party.contractIndex[contractAddress];

        emit PartyRemoved(contractAddress, partyAddress);
    }

    /****************************************
     *         REGISTRY STATE GETTERS       *
     ****************************************/

    /**
     * @notice Returns whether the contract has been registered with the registry.
     * @dev If it is registered, it is an authorized participant in the UMA system.
     * @param contractAddress address of the financial contract.
     * @return bool indicates whether the contract is registered.
     */
    function isContractRegistered(address contractAddress) external override view returns (bool) {
        return contractMap[contractAddress].valid == Validity.Valid;
    }

    /**
     * @notice Returns a list of all contracts that are associated with a particular party.
     * @param party address of the party.
     * @return an array of the contracts the party is registered to.
     */
    function getRegisteredContracts(address party) external override view returns (address[] memory) {
        return partyMap[party].contracts;
    }

    /**
     * @notice Returns all registered contracts.
     * @return all registered contract addresses within the system.
     */
    function getAllRegisteredContracts() external override view returns (address[] memory) {
        return registeredContracts;
    }

    /**
     * @notice checks if an address is a party of a contract.
     * @param party party to check.
     * @param contractAddress address to check against the party.
     * @return bool indicating if the address is a party of the contract.
     */
    function isPartyMemberOfContract(address party, address contractAddress) public override view returns (bool) {
        uint256 index = partyMap[party].contractIndex[contractAddress];
        return partyMap[party].contracts.length > index && partyMap[party].contracts[index] == contractAddress;
    }

    /****************************************
     *           INTERNAL FUNCTIONS         *
     ****************************************/

    function _addPartyToContract(address party, address contractAddress) internal {
        require(!isPartyMemberOfContract(party, contractAddress), "Can only register a party once");
        uint256 contractIndex = partyMap[party].contracts.length;
        partyMap[party].contracts.push(contractAddress);
        partyMap[party].contractIndex[contractAddress] = contractIndex;

        emit PartyAdded(contractAddress, party);
    }
}

File 85 of 117: RegistryInterface.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;


/**
 * @title Interface for a registry of contracts and contract creators.
 */
interface RegistryInterface {
    /**
     * @notice Registers a new contract.
     * @dev Only authorized contract creators can call this method.
     * @param parties an array of addresses who become parties in the contract.
     * @param contractAddress defines the address of the deployed contract.
     */
    function registerContract(address[] calldata parties, address contractAddress) external;

    /**
     * @notice Returns whether the contract has been registered with the registry.
     * @dev If it is registered, it is an authorized participant in the UMA system.
     * @param contractAddress address of the contract.
     * @return bool indicates whether the contract is registered.
     */
    function isContractRegistered(address contractAddress) external view returns (bool);

    /**
     * @notice Returns a list of all contracts that are associated with a particular party.
     * @param party address of the party.
     * @return an array of the contracts the party is registered to.
     */
    function getRegisteredContracts(address party) external view returns (address[] memory);

    /**
     * @notice Returns all registered contracts.
     * @return all registered contract addresses within the system.
     */
    function getAllRegisteredContracts() external view returns (address[] memory);

    /**
     * @notice Adds a party to the calling contract.
     * @dev msg.sender must be the contract to which the party member is added.
     * @param party address to be added to the contract.
     */
    function addPartyToContract(address party) external;

    /**
     * @notice Removes a party member to the calling contract.
     * @dev msg.sender must be the contract to which the party member is added.
     * @param party address to be removed from the contract.
     */
    function removePartyFromContract(address party) external;

    /**
     * @notice checks if an address is a party in a contract.
     * @param party party to check.
     * @param contractAddress address to check against the party.
     * @return bool indicating if the address is a party of the contract.
     */
    function isPartyMemberOfContract(address party, address contractAddress) external view returns (bool);
}

File 86 of 117: ResultComputation.sol
pragma solidity ^0.6.0;

import "./FixedPoint.sol";


/**
 * @title Computes vote results.
 * @dev The result is the mode of the added votes. Otherwise, the vote is unresolved.
 */
library ResultComputation {
    using FixedPoint for FixedPoint.Unsigned;

    /****************************************
     *   INTERNAL LIBRARY DATA STRUCTURE    *
     ****************************************/

    struct Data {
        // Maps price to number of tokens that voted for that price.
        mapping(int256 => FixedPoint.Unsigned) voteFrequency;
        // The total votes that have been added.
        FixedPoint.Unsigned totalVotes;
        // The price that is the current mode, i.e., the price with the highest frequency in `voteFrequency`.
        int256 currentMode;
    }

    /****************************************
     *            VOTING FUNCTIONS          *
     ****************************************/

    /**
     * @notice Adds a new vote to be used when computing the result.
     * @param data contains information to which the vote is applied.
     * @param votePrice value specified in the vote for the given `numberTokens`.
     * @param numberTokens number of tokens that voted on the `votePrice`.
     */
    function addVote(
        Data storage data,
        int256 votePrice,
        FixedPoint.Unsigned memory numberTokens
    ) internal {
        data.totalVotes = data.totalVotes.add(numberTokens);
        data.voteFrequency[votePrice] = data.voteFrequency[votePrice].add(numberTokens);
        if (
            votePrice != data.currentMode &&
            data.voteFrequency[votePrice].isGreaterThan(data.voteFrequency[data.currentMode])
        ) {
            data.currentMode = votePrice;
        }
    }

    /****************************************
     *        VOTING STATE GETTERS          *
     ****************************************/

    /**
     * @notice Returns whether the result is resolved, and if so, what value it resolved to.
     * @dev `price` should be ignored if `isResolved` is false.
     * @param data contains information against which the `minVoteThreshold` is applied.
     * @param minVoteThreshold min (exclusive) number of tokens that must have voted for the result to be valid. Can be
     * used to enforce a minimum voter participation rate, regardless of how the votes are distributed.
     * @return isResolved indicates if the price has been resolved correctly.
     * @return price the price that the dvm resolved to.
     */
    function getResolvedPrice(Data storage data, FixedPoint.Unsigned memory minVoteThreshold)
        internal
        view
        returns (bool isResolved, int256 price)
    {
        FixedPoint.Unsigned memory modeThreshold = FixedPoint.fromUnscaledUint(50).div(100);

        if (
            data.totalVotes.isGreaterThan(minVoteThreshold) &&
            data.voteFrequency[data.currentMode].div(data.totalVotes).isGreaterThan(modeThreshold)
        ) {
            // `modeThreshold` and `minVoteThreshold` are exceeded, so the current mode is the resolved price.
            isResolved = true;
            price = data.currentMode;
        } else {
            isResolved = false;
        }
    }

    /**
     * @notice Checks whether a `voteHash` is considered correct.
     * @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
     * @param data contains information against which the `voteHash` is checked.
     * @param voteHash committed hash submitted by the voter.
     * @return bool true if the vote was correct.
     */
    function wasVoteCorrect(Data storage data, bytes32 voteHash) internal view returns (bool) {
        return voteHash == keccak256(abi.encode(data.currentMode));
    }

    /**
     * @notice Gets the total number of tokens whose votes are considered correct.
     * @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
     * @param data contains all votes against which the correctly voted tokens are counted.
     * @return FixedPoint.Unsigned which indicates the frequency of the correctly voted tokens.
     */
    function getTotalCorrectlyVotedTokens(Data storage data) internal view returns (FixedPoint.Unsigned memory) {
        return data.voteFrequency[data.currentMode];
    }
}

File 87 of 117: ResultComputationTest.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./ResultComputation.sol";
import "./FixedPoint.sol";


// Wraps the library ResultComputation for testing purposes.
contract ResultComputationTest {
    using ResultComputation for ResultComputation.Data;

    ResultComputation.Data public data;

    function wrapAddVote(int256 votePrice, uint256 numberTokens) external {
        data.addVote(votePrice, FixedPoint.Unsigned(numberTokens));
    }

    function wrapGetResolvedPrice(uint256 minVoteThreshold) external view returns (bool isResolved, int256 price) {
        return data.getResolvedPrice(FixedPoint.Unsigned(minVoteThreshold));
    }

    function wrapWasVoteCorrect(bytes32 revealHash) external view returns (bool) {
        return data.wasVoteCorrect(revealHash);
    }

    function wrapGetTotalCorrectlyVotedTokens() external view returns (uint256) {
        return data.getTotalCorrectlyVotedTokens().rawValue;
    }
}

File 88 of 117: ReturnCalculatorInterface.sol
pragma solidity ^0.6.0;


/**
 * @title Computes the synthetic asset return based on the underlying asset's return.
 * @dev Different implementations can compute different return structures.
 */
interface ReturnCalculatorInterface {
    /**
     * @notice Computes the synthetic asset return when the underlying asset price changes from `oldPrice` to
     * `newPrice`.
     * @dev This can be implemented in many different ways, but a simple one would just be levering (or multiplying)
     * the return by some fixed integer.
     */
    function computeReturn(int256 oldPrice, int256 newPrice) external view returns (int256 assetReturn);

    /**
     * @notice Gets the effective leverage for the return calculator.
     * @dev If there is no sensible leverage value for a return calculator, this method should return 1.
     */
    function leverage() external view returns (int256 _leverage);
}

File 89 of 117: SafeCast.sol
pragma solidity ^0.6.0;


/**
 * @dev Wrappers over Solidity's uintXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and then downcasting.
 */
library SafeCast {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 90 of 117: SafeERC20.sol
pragma solidity ^0.6.0;

import "./IERC20.sol";
import "./SafeMath.sol";
import "./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, "SafeERC20: decreased allowance below zero");
        _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 91 of 117: SafeMath.sol
pragma solidity ^0.6.0;

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

        return c;
    }

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

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

        return c;
    }

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

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

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

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

        return c;
    }

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

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

File 92 of 117: SignedSafeMath.sol
pragma solidity ^0.6.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMath {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @dev Multiplies two signed integers, reverts on overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Subtracts two signed integers, reverts on overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

    /**
     * @dev Adds two signed integers, reverts on overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

        return c;
    }
}

File 93 of 117: Store.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./SafeMath.sol";
import "./IERC20.sol";
import "./SafeERC20.sol";
import "./FixedPoint.sol";
import "./MultiRole.sol";
import "./Withdrawable.sol";
import "./Testable.sol";
import "./StoreInterface.sol";


/**
 * @title An implementation of Store that can accept Oracle fees in ETH or any arbitrary ERC20 token.
 */
contract Store is StoreInterface, Withdrawable, Testable {
    using SafeMath for uint256;
    using FixedPoint for FixedPoint.Unsigned;
    using FixedPoint for uint256;
    using SafeERC20 for IERC20;

    /****************************************
     *    INTERNAL VARIABLES AND STORAGE    *
     ****************************************/

    enum Roles { Owner, Withdrawer }

    FixedPoint.Unsigned public fixedOracleFeePerSecondPerPfc; // Percentage of 1 E.g., .1 is 10% Oracle fee.
    FixedPoint.Unsigned public weeklyDelayFeePerSecondPerPfc; // Percentage of 1 E.g., .1 is 10% weekly delay fee.

    mapping(address => FixedPoint.Unsigned) public finalFees;
    uint256 public constant SECONDS_PER_WEEK = 604800;

    /****************************************
     *                EVENTS                *
     ****************************************/

    event NewFixedOracleFeePerSecondPerPfc(FixedPoint.Unsigned newOracleFee);
    event NewWeeklyDelayFeePerSecondPerPfc(FixedPoint.Unsigned newWeeklyDelayFeePerSecondPerPfc);
    event NewFinalFee(FixedPoint.Unsigned newFinalFee);

    /**
     * @notice Construct the Store contract.
     */
    constructor(
        FixedPoint.Unsigned memory _fixedOracleFeePerSecondPerPfc,
        FixedPoint.Unsigned memory _weeklyDelayFeePerSecondPerPfc,
        address _timerAddress
    ) public Testable(_timerAddress) {
        _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
        _createWithdrawRole(uint256(Roles.Withdrawer), uint256(Roles.Owner), msg.sender);
        setFixedOracleFeePerSecondPerPfc(_fixedOracleFeePerSecondPerPfc);
        setWeeklyDelayFeePerSecondPerPfc(_weeklyDelayFeePerSecondPerPfc);
    }

    /****************************************
     *  ORACLE FEE CALCULATION AND PAYMENT  *
     ****************************************/

    /**
     * @notice Pays Oracle fees in ETH to the store.
     * @dev To be used by contracts whose margin currency is ETH.
     */
    function payOracleFees() external override payable {
        require(msg.value > 0, "Value sent can't be zero");
    }

    /**
     * @notice Pays oracle fees in the margin currency, erc20Address, to the store.
     * @dev To be used if the margin currency is an ERC20 token rather than ETH.
     * @param erc20Address address of the ERC20 token used to pay the fee.
     * @param amount number of tokens to transfer. An approval for at least this amount must exist.
     */
    function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external override {
        IERC20 erc20 = IERC20(erc20Address);
        require(amount.isGreaterThan(0), "Amount sent can't be zero");
        erc20.safeTransferFrom(msg.sender, address(this), amount.rawValue);
    }

    /**
     * @notice Computes the regular oracle fees that a contract should pay for a period.
     * @dev The late penalty is similar to the regular fee in that is is charged per second over the period between
     * startTime and endTime. The late penalty percentage increases over time as follows:
     * - 0-1 week since startTime: no late penalty
     * - 1-2 weeks since startTime: 1x late penalty percentage is applied
     * - 2-3 weeks since startTime: 2x late penalty percentage is applied
     * - ...
     * @param startTime defines the beginning time from which the fee is paid.
     * @param endTime end time until which the fee is paid.
     * @param pfc "profit from corruption", or the maximum amount of margin currency that a
     * token sponsor could extract from the contract through corrupting the price feed in their favor.
     * @return regularFee amount owed for the duration from start to end time for the given pfc.
     * @return latePenalty penalty percentage, if any, for paying the fee after the deadline.
     */
    function computeRegularFee(
        uint256 startTime,
        uint256 endTime,
        FixedPoint.Unsigned calldata pfc
    ) external override view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty) {
        uint256 timeDiff = endTime.sub(startTime);

        // Multiply by the unscaled `timeDiff` first, to get more accurate results.
        regularFee = pfc.mul(timeDiff).mul(fixedOracleFeePerSecondPerPfc);

        // Compute how long ago the start time was to compute the delay penalty.
        uint256 paymentDelay = getCurrentTime().sub(startTime);

        // Compute the additional percentage (per second) that will be charged because of the penalty.
        // Note: if less than a week has gone by since the startTime, paymentDelay / SECONDS_PER_WEEK will truncate to
        // 0, causing no penalty to be charged.
        FixedPoint.Unsigned memory penaltyPercentagePerSecond = weeklyDelayFeePerSecondPerPfc.mul(
            paymentDelay.div(SECONDS_PER_WEEK)
        );

        // Apply the penaltyPercentagePerSecond to the payment period.
        latePenalty = pfc.mul(timeDiff).mul(penaltyPercentagePerSecond);
    }

    /**
     * @notice Computes the final oracle fees that a contract should pay at settlement.
     * @param currency token used to pay the final fee.
     * @return finalFee amount due denominated in units of `currency`.
     */
    function computeFinalFee(address currency) external override view returns (FixedPoint.Unsigned memory) {
        return finalFees[currency];
    }

    /****************************************
     *   ADMIN STATE MODIFYING FUNCTIONS    *
     ****************************************/

    /**
     * @notice Sets a new oracle fee per second.
     * @param newFixedOracleFeePerSecondPerPfc new fee per second charged to use the oracle.
     */
    function setFixedOracleFeePerSecondPerPfc(FixedPoint.Unsigned memory newFixedOracleFeePerSecondPerPfc)
        public
        onlyRoleHolder(uint256(Roles.Owner))
    {
        // Oracle fees at or over 100% don't make sense.
        require(newFixedOracleFeePerSecondPerPfc.isLessThan(1), "Fee must be < 100% per second.");
        fixedOracleFeePerSecondPerPfc = newFixedOracleFeePerSecondPerPfc;
        emit NewFixedOracleFeePerSecondPerPfc(newFixedOracleFeePerSecondPerPfc);
    }

    /**
     * @notice Sets a new weekly delay fee.
     * @param newWeeklyDelayFeePerSecondPerPfc fee escalation per week of late fee payment.
     */
    function setWeeklyDelayFeePerSecondPerPfc(FixedPoint.Unsigned memory newWeeklyDelayFeePerSecondPerPfc)
        public
        onlyRoleHolder(uint256(Roles.Owner))
    {
        require(newWeeklyDelayFeePerSecondPerPfc.isLessThan(1), "weekly delay fee must be < 100%");
        weeklyDelayFeePerSecondPerPfc = newWeeklyDelayFeePerSecondPerPfc;
        emit NewWeeklyDelayFeePerSecondPerPfc(newWeeklyDelayFeePerSecondPerPfc);
    }

    /**
     * @notice Sets a new final fee for a particular currency.
     * @param currency defines the token currency used to pay the final fee.
     * @param newFinalFee final fee amount.
     */
    function setFinalFee(address currency, FixedPoint.Unsigned memory newFinalFee)
        public
        onlyRoleHolder(uint256(Roles.Owner))
    {
        finalFees[currency] = newFinalFee;
        emit NewFinalFee(newFinalFee);
    }
}

File 94 of 117: StoreInterface.sol
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

import "./IERC20.sol";
import "./FixedPoint.sol";


/**
 * @title Interface that allows financial contracts to pay oracle fees for their use of the system.
 */
interface StoreInterface {
    /**
     * @notice Pays Oracle fees in ETH to the store.
     * @dev To be used by contracts whose margin currency is ETH.
     */
    function payOracleFees() external payable;

    /**
     * @notice Pays oracle fees in the margin currency, erc20Address, to the store.
     * @dev To be used if the margin currency is an ERC20 token rather than ETH.
     * @param erc20Address address of the ERC20 token used to pay the fee.
     * @param amount number of tokens to transfer. An approval for at least this amount must exist.
     */
    function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external;

    /**
     * @notice Computes the regular oracle fees that a contract should pay for a period.
     * @param startTime defines the beginning time from which the fee is paid.
     * @param endTime end time until which the fee is paid.
     * @param pfc "profit from corruption", or the maximum amount of margin currency that a
     * token sponsor could extract from the contract through corrupting the price feed in their favor.
     * @return regularFee amount owed for the duration from start to end time for the given pfc.
     * @return latePenalty for paying the fee after the deadline.
     */
    function computeRegularFee(
        uint256 startTime,
        uint256 endTime,
        FixedPoint.Unsigned calldata pfc
    ) external view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty);

    /**
     * @notice Computes the final oracle fees that a contract should pay at settlement.
     * @param currency token used to pay the final fee.
     * @return finalFee amount due.
     */
    function computeFinalFee(address currency) external view returns (FixedPoint.Unsigned memory);
}

File 95 of 117: Strings.sol
pragma solidity ^0.6.0;

/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = byte(uint8(48 + temp % 10));
            temp /= 10;
        }
        return string(buffer);
    }
}

File 96 of 117: SyntheticToken.sol
pragma solidity ^0.6.0;
import "./ExpandedERC20.sol";


/**
 * @title Burnable and mintable ERC20.
 * @dev The contract deployer will initially be the only minter and burner as well as the owner  who
 * is capable of adding new roles.
 */

contract SyntheticToken is ExpandedERC20 {
    /**
     * @notice Constructs the SyntheticToken.
     * @param tokenName The name which describes the new token.
     * @param tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.
     * @param tokenDecimals The number of decimals to define token precision.
     */
    constructor(
        string memory tokenName,
        string memory tokenSymbol,
        uint8 tokenDecimals
    ) public ExpandedERC20(tokenName, tokenSymbol, tokenDecimals) {}

    /**
     * @notice Add Minter role to account.
     * @dev The caller must have the Owner role.
     * @param account The address to which the Minter role is added.
     */
    function addMinter(address account) external {
        addMember(uint256(Roles.Minter), account);
    }

    /**
     * @notice Remove Minter role from account.
     * @dev The caller must have the Owner role.
     * @param account The address from which the Minter role is removed.
     */
    function removeMinter(address account) external {
        removeMember(uint256(Roles.Minter), account);
    }

    /**
     * @notice Add Burner role to account.
     * @dev The caller must have the Owner role.
     * @param account The address to which the Burner role is added.
     */
    function addBurner(address account) external {
        addMember(uint256(Roles.Burner), account);
    }

    /**
     * @notice Removes Burner role from account.
     * @dev The caller must have the Owner role.
     * @param account The address from which the Burner role is removed.
     */
    function removeBurner(address account) external {
        removeMember(uint256(Roles.Burner), account);
    }

    /**
     * @notice Reset Owner role to account.
     * @dev The caller must have the Owner role.
     * @param account The new holder of the Owner role.
     */
    function resetOwner(address account) external {
        resetMember(uint256(Roles.Owner), account);
    }

    /**
     * @notice Checks if a given account holds the Minter role.
     * @param account The address which is checked for the Minter role.
     * @return bool True if the provided account is a Minter.
     */
    function isMinter(address account) public view returns (bool) {
        return holdsRole(uint256(Roles.Minter), account);
    }

    /**
     * @notice Checks if a given account holds the Burner role.
     * @param account The address which is checked for the Burner role.
     * @return bool True if the provided account is a Burner.
     */
    function isBurner(address account) public view returns (bool) {
        return holdsRole(uint256(Roles.Burner), account);
    }
}

File 97 of 117: Testable.sol
pragma solidity ^0.6.0;

import "./Timer.sol";


/**
 * @title Base class that provides time overrides, but only if being run in test mode.
 */
abstract contract Testable {
    // If the contract is being run on the test network, then `timerAddress` will be the 0x0.
    // Note: this variable should be set on construction and never modified.
    address public timerAddress;

    /**
     * @notice Constructs the Testable contract. Called by child contracts.
     * @param _timerAddress Contract that stores the current time in a testing environment.
     * Must be set to 0x0 for production environments that use live time.
     */
    constructor(address _timerAddress) internal {
        timerAddress = _timerAddress;
    }

    /**
     * @notice Reverts if not running in test mode.
     */
    modifier onlyIfTest {
        require(timerAddress != address(0x0));
        _;
    }

    /**
     * @notice Sets the current time.
     * @dev Will revert if not running in test mode.
     * @param time timestamp to set current Tesable time to.
     */
    function setCurrentTime(uint256 time) external onlyIfTest {
        Timer(timerAddress).setCurrentTime(time);
    }

    /**
     * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.
     * Otherwise, it will return the block timestamp.
     * @return uint for the current Testable timestamp.
     */
    function getCurrentTime() public view returns (uint256) {
        if (timerAddress != address(0x0)) {
            return Timer(timerAddress).getCurrentTime();
        } else {
            return now; // solhint-disable-line not-rely-on-time
        }
    }
}

File 98 of 117: TestableTest.sol
pragma solidity ^0.6.0;

import "./Testable.sol";


// TestableTest is derived from the abstract contract Testable for testing purposes.
contract TestableTest is Testable {
    // solhint-disable-next-line no-empty-blocks
    constructor(address _timerAddress) public Testable(_timerAddress) {}

    function getTestableTimeAndBlockTime() external view returns (uint256 testableTime, uint256 blockTime) {
        // solhint-disable-next-line not-rely-on-time
        return (getCurrentTime(), now);
    }
}

File 99 of 117: TestnetERC20.sol
pragma solidity ^0.6.0;

import "./ERC20.sol";


/**
 * @title An implementation of ERC20 with the same interface as the Compound project's testnet tokens (mainly DAI)
 * @dev This contract can be deployed or the interface can be used to communicate with Compound's ERC20 tokens.  Note:
 * this token should never be used to store real value since it allows permissionless minting.
 */
contract TestnetERC20 is ERC20 {
    /**
     * @notice Constructs the TestnetERC20.
     * @param _name The name which describes the new token.
     * @param _symbol The ticker abbreviation of the name. Ideally < 5 chars.
     * @param _decimals The number of decimals to define token precision.
     */
    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) public ERC20(_name, _symbol) {
        _setupDecimals(_decimals);
    }

    // Sample token information.

    /**
     * @notice Mints value tokens to the owner address.
     * @param ownerAddress the address to mint to.
     * @param value the amount of tokens to mint.
     */
    function allocateTo(address ownerAddress, uint256 value) external {
        _mint(ownerAddress, value);
    }
}

File 100 of 117: Timer.sol
pragma solidity ^0.6.0;


/**
 * @title Universal store of current contract time for testing environments.
 */
contract Timer {
    uint256 private currentTime;

    constructor() public {
        currentTime = now; // solhint-disable-line not-rely-on-time
    }

    /**
     * @notice Sets the current time.
     * @dev Will revert if not running in test mode.
     * @param time timestamp to set `currentTime` to.
     */
    function setCurrentTime(uint256 time) external {
        currentTime = time;
    }

    /**
     * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.
     * Otherwise, it will return the block timestamp.
     * @return uint256 for the current Testable timestamp.
     */
    function getCurrentTime() public view returns (uint256) {
        return currentTime;
    }
}

File 101 of 117: TokenFactory.sol
pragma solidity ^0.6.0;
import "./SyntheticToken.sol";
import "./ExpandedIERC20.sol";


/**
 * @title Factory for creating new mintable and burnable tokens.
 */

contract TokenFactory {
    /**
     * @notice Create a new token and return to the caller.
     * @dev The caller will become the only minter and burner and the new owner capable of adding new roles.
     * @param tokenName used to describe the new token.
     * @param tokenSymbol short ticker abbreviation of the name. Ideally < 5 chars.
     * @param tokenDecimals used to define the precision used in the tokens numerical representation.
     * @return newToken an instance of the newly created token interface.
     */
    function createToken(
        string calldata tokenName,
        string calldata tokenSymbol,
        uint8 tokenDecimals
    ) external returns (ExpandedIERC20 newToken) {
        SyntheticToken mintableToken = new SyntheticToken(tokenName, tokenSymbol, tokenDecimals);
        mintableToken.addMinter(msg.sender);
        mintableToken.addBurner(msg.sender);
        mintableToken.resetOwner(msg.sender);
        newToken = ExpandedIERC20(address(mintableToken));
    }
}

File 102 of 117: TokenizedDerivative.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./ExpandedIERC20.sol";
import "./FixedPoint.sol";
import "./AdministrateeInterface.sol";
import "./OracleInterface.sol";
import "./StoreInterface.sol";
import "./IdentifierWhitelistInterface.sol";
import "./FinderInterface.sol";
import "./Constants.sol";
import "./PriceFeedInterface.sol";
import "./ReturnCalculatorInterface.sol";

import "./SafeMath.sol";
import "./SignedSafeMath.sol";
import "./ERC20.sol";
import "./IERC20.sol";


library TokenizedDerivativeParams {
    enum ReturnType { Linear, Compound }

    struct ConstructorParams {
        address sponsor;
        address finderAddress;
        address priceFeedAddress;
        uint256 defaultPenalty; // Percentage of margin requirement * 10^18
        uint256 supportedMove; // Expected percentage move in the underlying price that the long is protected against.
        bytes32 product;
        uint256 fixedYearlyFee; // Percentage of nav * 10^18
        uint256 disputeDeposit; // Percentage of margin requirement * 10^18
        address returnCalculator;
        uint256 startingTokenPrice;
        uint256 expiry;
        address marginCurrency;
        uint256 withdrawLimit; // Percentage of derivativeStorage.shortBalance * 10^18
        ReturnType returnType;
        uint256 startingUnderlyingPrice;
        uint256 creationTime;
    }
}


/**
 * @title Tokenized Derivative Storage
 * @dev This library name is shortened due to it being used so often.
 */
library TDS {
    enum State {
        // The contract is active, and tokens can be created and redeemed. Margin can be added and withdrawn (as long as
        // it exceeds required levels). Remargining is allowed. Created contracts immediately begin in this state.
        // Possible state transitions: Disputed, Expired, Defaulted.
        Live,
        // Disputed, Expired, Defaulted, and Emergency are Frozen states. In a Frozen state, the contract is frozen in
        // time awaiting a resolution by the Oracle. No tokens can be created or redeemed. Margin cannot be withdrawn.
        // The resolution of these states moves the contract to the Settled state. Remargining is not allowed.

        // The sponsor has disputed the price feed output. If the dispute is valid (i.e., the NAV calculated from the
        // Oracle price differs from the NAV calculated from the price feed), the dispute fee is added to the short
        // account. Otherwise, the dispute fee is added to the long margin account.
        // Possible state transitions: Settled.
        Disputed,
        // Contract expiration has been reached.
        // Possible state transitions: Settled.
        Expired,
        // The short margin account is below its margin requirement. The sponsor can choose to confirm the default and
        // move to Settle without waiting for the Oracle. Default penalties will be assessed when the contract moves to
        // Settled.
        // Possible state transitions: Settled.
        Defaulted,
        // UMA has manually triggered a shutdown of the account.
        // Possible state transitions: Settled.
        Emergency,
        // Token price is fixed. Tokens can be redeemed by anyone. All short margin can be withdrawn. Tokens can't be
        // created, and contract can't remargin.
        // Possible state transitions: None.
        Settled
    }

    // The state of the token at a particular time. The state gets updated on remargin.
    struct TokenState {
        int256 underlyingPrice;
        int256 tokenPrice;
        uint256 time;
    }

    // The information in the following struct is only valid if in the midst of a Dispute.
    struct Dispute {
        int256 disputedNav;
        uint256 deposit;
    }

    struct WithdrawThrottle {
        uint256 startTime;
        uint256 remainingWithdrawal;
    }

    struct FixedParameters {
        // Fixed contract parameters.
        uint256 defaultPenalty; // Percentage of margin requirement * 10^18
        uint256 supportedMove; // Expected percentage move that the long is protected against.
        uint256 disputeDeposit; // Percentage of margin requirement * 10^18
        uint256 fixedFeePerSecond; // Percentage of nav*10^18
        uint256 withdrawLimit; // Percentage of derivativeStorage.shortBalance*10^18
        bytes32 product;
        TokenizedDerivativeParams.ReturnType returnType;
        uint256 initialTokenUnderlyingRatio;
        uint256 creationTime;
        string symbol;
    }

    struct ExternalAddresses {
        // Other addresses/contracts
        address sponsor;
        address apDelegate;
        FinderInterface finder;
        PriceFeedInterface priceFeed;
        ReturnCalculatorInterface returnCalculator;
        IERC20 marginCurrency;
    }

    struct Storage {
        FixedParameters fixedParameters;
        ExternalAddresses externalAddresses;
        // Balances
        int256 shortBalance;
        int256 longBalance;
        State state;
        uint256 endTime;
        // The NAV of the contract always reflects the transition from (`prev`, `current`).
        // In the case of a remargin, a `latest` price is retrieved from the price feed, and we shift
        // `current` -> `prev` and `latest` -> `current` (and then recompute).
        // In the case of a dispute, `current` might change (which is why we have to hold on to `prev`).
        TokenState referenceTokenState;
        TokenState currentTokenState;
        int256 nav; // Net asset value is measured in Wei
        Dispute disputeInfo;
        // Only populated once the contract enters a frozen state.
        int256 defaultPenaltyAmount;
        WithdrawThrottle withdrawThrottle;
    }
}


/**
 * @dev Implements the functionality of `TokenizedDerivative` by operating on the data contained in a `TDS.Storage`.
 */
library TokenizedDerivativeUtils {
    using TokenizedDerivativeUtils for TDS.Storage;
    using SafeMath for uint256;
    using SignedSafeMath for int256;
    using FixedPoint for FixedPoint.Unsigned;

    uint256 private constant SECONDS_PER_DAY = 86400;
    uint256 private constant SECONDS_PER_YEAR = 31536000;
    uint256 private constant INT_MAX = 2**255 - 1;
    uint256 private constant UINT_FP_SCALING_FACTOR = 10**18;
    int256 private constant INT_FP_SCALING_FACTOR = 10**18;

    // Note that we can't have the symbol parameter be `indexed` due to:
    // TypeError: Indexed reference types cannot yet be used with ABIEncoderV2.
    // An event emitted when the NAV of the contract changes.
    event NavUpdated(string symbol, int256 newNav, int256 newTokenPrice);
    // An event emitted when the contract enters the Default state on a remargin.
    event Default(string symbol, uint256 defaultTime, int256 defaultNav);
    // An event emitted when the contract settles.
    event Settled(string symbol, uint256 settleTime, int256 finalNav);
    // An event emitted when the contract expires.
    event Expired(string symbol, uint256 expiryTime);
    // An event emitted when the contract's NAV is disputed by the sponsor.
    event Disputed(string symbol, uint256 timeDisputed, int256 navDisputed);
    // An event emitted when the contract enters emergency shutdown.
    event EmergencyShutdownTransition(string symbol, uint256 shutdownTime);
    // An event emitted when tokens are created.
    event TokensCreated(string symbol, uint256 numTokensCreated);
    // An event emitted when tokens are redeemed.
    event TokensRedeemed(string symbol, uint256 numTokensRedeemed);
    // An event emitted when margin currency is deposited.
    event Deposited(string symbol, uint256 amount);
    // An event emitted when margin currency is withdrawn.
    event Withdrawal(string symbol, uint256 amount);

    modifier onlySponsor(TDS.Storage storage s) {
        require(msg.sender == s.externalAddresses.sponsor);
        _;
    }

    modifier onlyAdmin(TDS.Storage storage s) {
        require(msg.sender == _getAdminAddress(s));
        _;
    }

    modifier onlySponsorOrAdmin(TDS.Storage storage s) {
        require(msg.sender == s.externalAddresses.sponsor || msg.sender == _getAdminAddress(s));
        _;
    }

    modifier onlySponsorOrApDelegate(TDS.Storage storage s) {
        require(msg.sender == s.externalAddresses.sponsor || msg.sender == s.externalAddresses.apDelegate);
        _;
    }

    function _depositAndCreateTokens(
        TDS.Storage storage s,
        uint256 marginForPurchase,
        uint256 tokensToPurchase
    ) external onlySponsorOrApDelegate(s) {
        s._remarginInternal();

        int256 newTokenNav = _computeNavForTokens(s.currentTokenState.tokenPrice, tokensToPurchase);

        if (newTokenNav < 0) {
            newTokenNav = 0;
        }

        uint256 positiveTokenNav = _safeUintCast(newTokenNav);

        // Get any refund due to sending more margin than the argument indicated (should only be able to happen in the
        // ETH case).
        uint256 refund = s._pullSentMargin(marginForPurchase);

        // Subtract newTokenNav from amount sent.
        uint256 depositAmount = marginForPurchase.sub(positiveTokenNav);

        // Deposit additional margin into the short account.
        s._depositInternal(depositAmount);

        // The _createTokensInternal call returns any refund due to the amount sent being larger than the amount
        // required to purchase the tokens, so we add that to the running refund. This should be 0 in this case,
        // but we leave this here in case of some refund being generated due to rounding errors or any bugs to ensure
        // the sender never loses money.
        refund = refund.add(s._createTokensInternal(tokensToPurchase, positiveTokenNav));

        // Send the accumulated refund.
        s._sendMargin(refund);
    }

    function _redeemTokens(TDS.Storage storage s, uint256 tokensToRedeem) external {
        require(s.state == TDS.State.Live || s.state == TDS.State.Settled);
        require(tokensToRedeem > 0);

        if (s.state == TDS.State.Live) {
            require(msg.sender == s.externalAddresses.sponsor || msg.sender == s.externalAddresses.apDelegate);
            s._remarginInternal();
            require(s.state == TDS.State.Live);
        }

        ExpandedIERC20 thisErc20Token = ExpandedIERC20(address(this));

        uint256 initialSupply = _totalSupply();
        require(initialSupply > 0);

        _pullAuthorizedTokens(thisErc20Token, tokensToRedeem);
        thisErc20Token.burn(tokensToRedeem);
        emit TokensRedeemed(s.fixedParameters.symbol, tokensToRedeem);

        // Value of the tokens is just the percentage of all the tokens multiplied by the balance of the investor
        // margin account.
        uint256 tokenPercentage = tokensToRedeem.mul(UINT_FP_SCALING_FACTOR).div(initialSupply);
        uint256 tokenMargin = _takePercentage(_safeUintCast(s.longBalance), tokenPercentage);

        s.longBalance = s.longBalance.sub(_safeIntCast(tokenMargin));
        assert(s.longBalance >= 0);
        s.nav = _computeNavForTokens(s.currentTokenState.tokenPrice, _totalSupply());

        s._sendMargin(tokenMargin);
    }

    function _dispute(TDS.Storage storage s, uint256 depositMargin) external onlySponsor(s) {
        require(s.state == TDS.State.Live, "Contract must be Live to dispute");

        uint256 requiredDeposit = _safeUintCast(
            _takePercentage(s._getRequiredMargin(s.currentTokenState), s.fixedParameters.disputeDeposit)
        );

        uint256 sendInconsistencyRefund = s._pullSentMargin(depositMargin);

        require(depositMargin >= requiredDeposit);
        uint256 overpaymentRefund = depositMargin.sub(requiredDeposit);

        s.state = TDS.State.Disputed;
        s.endTime = s.currentTokenState.time;
        s.disputeInfo.disputedNav = s.nav;
        s.disputeInfo.deposit = requiredDeposit;

        // Store the default penalty in case the dispute pushes the sponsor into default.
        s.defaultPenaltyAmount = s._computeDefaultPenalty();
        emit Disputed(s.fixedParameters.symbol, s.endTime, s.nav);

        s._requestOraclePrice(s.endTime);

        // Add the two types of refunds:
        // 1. The refund for ETH sent if it was > depositMargin.
        // 2. The refund for depositMargin > requiredDeposit.
        s._sendMargin(sendInconsistencyRefund.add(overpaymentRefund));
    }

    function _withdraw(TDS.Storage storage s, uint256 amount) external onlySponsor(s) {
        // Remargin before allowing a withdrawal, but only if in the live state.
        if (s.state == TDS.State.Live) {
            s._remarginInternal();
        }

        // Make sure either in Live or Settled after any necessary remargin.
        require(s.state == TDS.State.Live || s.state == TDS.State.Settled);

        // If the contract has been settled or is in prefunded state then can
        // withdraw up to full balance. If the contract is in live state then
        // must leave at least the required margin. Not allowed to withdraw in
        // other states.
        int256 withdrawableAmount;
        if (s.state == TDS.State.Settled) {
            withdrawableAmount = s.shortBalance;
        } else {
            // Update throttling snapshot and verify that this withdrawal doesn't go past the throttle limit.
            uint256 currentTime = s.currentTokenState.time;
            if (s.withdrawThrottle.startTime <= currentTime.sub(SECONDS_PER_DAY)) {
                // We've passed the previous s.withdrawThrottle window. Start new one.
                s.withdrawThrottle.startTime = currentTime;
                s.withdrawThrottle.remainingWithdrawal = _takePercentage(
                    _safeUintCast(s.shortBalance),
                    s.fixedParameters.withdrawLimit
                );
            }

            int256 marginMaxWithdraw = s.shortBalance.sub(s._getRequiredMargin(s.currentTokenState));
            int256 throttleMaxWithdraw = _safeIntCast(s.withdrawThrottle.remainingWithdrawal);

            // Take the smallest of the two withdrawal limits.
            withdrawableAmount = throttleMaxWithdraw < marginMaxWithdraw ? throttleMaxWithdraw : marginMaxWithdraw;

            // Note: this line alone implicitly ensures the withdrawal throttle is not violated, but the above
            // ternary is more explicit.
            s.withdrawThrottle.remainingWithdrawal = s.withdrawThrottle.remainingWithdrawal.sub(amount);
        }

        // Can only withdraw the allowed amount.
        require(withdrawableAmount >= _safeIntCast(amount), "Attempting to withdraw more than allowed");

        // Transfer amount - Note: important to `-=` before the send so that the
        // function can not be called multiple times while waiting for transfer
        // to return.
        s.shortBalance = s.shortBalance.sub(_safeIntCast(amount));
        emit Withdrawal(s.fixedParameters.symbol, amount);
        s._sendMargin(amount);
    }

    function _acceptPriceAndSettle(TDS.Storage storage s) external onlySponsor(s) {
        // Right now, only confirming prices in the defaulted state.
        require(s.state == TDS.State.Defaulted);

        // Remargin on agreed upon price.
        s._settleAgreedPrice();
    }

    function _setApDelegate(TDS.Storage storage s, address _apDelegate) external onlySponsor(s) {
        s.externalAddresses.apDelegate = _apDelegate;
    }

    // Moves the contract into the Emergency state, where it waits on an Oracle price for the most recent remargin time.
    function _emergencyShutdown(TDS.Storage storage s) external onlyAdmin(s) {
        require(s.state == TDS.State.Live);
        s.state = TDS.State.Emergency;
        s.endTime = s.currentTokenState.time;
        s.defaultPenaltyAmount = s._computeDefaultPenalty();
        emit EmergencyShutdownTransition(s.fixedParameters.symbol, s.endTime);
        s._requestOraclePrice(s.endTime);
    }

    function _settle(TDS.Storage storage s) external {
        s._settleInternal();
    }

    function _createTokens(
        TDS.Storage storage s,
        uint256 marginForPurchase,
        uint256 tokensToPurchase
    ) external onlySponsorOrApDelegate(s) {
        // Returns any refund due to sending more margin than the argument indicated (should only be able to happen in
        // the ETH case).
        uint256 refund = s._pullSentMargin(marginForPurchase);

        // The _createTokensInternal call returns any refund due to the amount sent being larger than the amount
        // required to purchase the tokens, so we add that to the running refund.
        refund = refund.add(s._createTokensInternal(tokensToPurchase, marginForPurchase));

        // Send the accumulated refund.
        s._sendMargin(refund);
    }

    function _deposit(TDS.Storage storage s, uint256 marginToDeposit) external onlySponsor(s) {
        // Only allow the s.externalAddresses.sponsor to deposit margin.
        uint256 refund = s._pullSentMargin(marginToDeposit);
        s._depositInternal(marginToDeposit);

        // Send any refund due to sending more margin than the argument indicated (should only be able to happen in the
        // ETH case).
        s._sendMargin(refund);
    }

    function _remargin(TDS.Storage storage s) external onlySponsorOrAdmin(s) {
        s._remarginInternal();
    }

    function _withdrawUnexpectedErc20(
        TDS.Storage storage s,
        address erc20Address,
        uint256 amount
    ) external onlySponsor(s) {
        if (address(s.externalAddresses.marginCurrency) == erc20Address) {
            uint256 currentBalance = s.externalAddresses.marginCurrency.balanceOf(address(this));
            int256 totalBalances = s.shortBalance.add(s.longBalance);
            assert(totalBalances >= 0);
            uint256 withdrawableAmount = currentBalance.sub(_safeUintCast(totalBalances)).sub(s.disputeInfo.deposit);
            require(withdrawableAmount >= amount);
        }

        IERC20 erc20 = IERC20(erc20Address);
        require(erc20.transfer(msg.sender, amount));
    }

    // Returns the expected net asset value (NAV) of the contract using the latest available Price Feed price.
    function _calcNAV(TDS.Storage storage s) external view returns (int256 navNew) {
        (TDS.TokenState memory newTokenState, ) = s._calcNewTokenStateAndBalance();
        navNew = _computeNavForTokens(newTokenState.tokenPrice, _totalSupply());
    }

    // Returns the expected value of each the outstanding tokens of the contract using the latest available Price Feed
    // price.
    function _calcTokenValue(TDS.Storage storage s) external view returns (int256 newTokenValue) {
        (TDS.TokenState memory newTokenState, ) = s._calcNewTokenStateAndBalance();
        newTokenValue = newTokenState.tokenPrice;
    }

    // Returns the expected balance of the short margin account using the latest available Price Feed price.
    function _calcShortMarginBalance(TDS.Storage storage s) external view returns (int256 newShortMarginBalance) {
        (, newShortMarginBalance) = s._calcNewTokenStateAndBalance();
    }

    function _calcExcessMargin(TDS.Storage storage s) external view returns (int256 newExcessMargin) {
        (TDS.TokenState memory newTokenState, int256 newShortMarginBalance) = s._calcNewTokenStateAndBalance();
        // If the contract is in/will be moved to a settled state, the margin requirement will be 0.
        int256 requiredMargin = newTokenState.time >= s.endTime ? 0 : s._getRequiredMargin(newTokenState);
        return newShortMarginBalance.sub(requiredMargin);
    }

    function _getCurrentRequiredMargin(TDS.Storage storage s) external view returns (int256 requiredMargin) {
        if (s.state == TDS.State.Settled) {
            // No margin needs to be maintained when the contract is settled.
            return 0;
        }

        return s._getRequiredMargin(s.currentTokenState);
    }

    function _canBeSettled(TDS.Storage storage s) external view returns (bool canBeSettled) {
        TDS.State currentState = s.state;

        if (currentState == TDS.State.Settled) {
            return false;
        }

        // Technically we should also check if price will default the contract, but that isn't a normal flow of
        // operations that we want to simulate: we want to discourage the sponsor remargining into a default.
        (uint256 priceFeedTime, ) = s._getLatestPrice();
        if (currentState == TDS.State.Live && (priceFeedTime < s.endTime)) {
            return false;
        }

        return OracleInterface(_getOracleAddress(s)).hasPrice(s.fixedParameters.product, s.endTime);
    }

    function _getUpdatedUnderlyingPrice(TDS.Storage storage s)
        external
        view
        returns (int256 underlyingPrice, uint256 time)
    {
        (TDS.TokenState memory newTokenState, ) = s._calcNewTokenStateAndBalance();
        return (newTokenState.underlyingPrice, newTokenState.time);
    }

    // Contract initializer. Should only be called at construction.
    // Note: Must be a public function because structs cannot be passed as calldata (required data type for external
    // functions).
    function _initialize(
        TDS.Storage storage s,
        TokenizedDerivativeParams.ConstructorParams memory params,
        string memory symbol
    ) public {
        s._setFixedParameters(params, symbol);
        s._setExternalAddresses(params);

        // Keep the starting token price relatively close to FP_SCALING_FACTOR to prevent users from unintentionally
        // creating rounding or overflow errors.
        require(params.startingTokenPrice >= UINT_FP_SCALING_FACTOR.div(10**9));
        require(params.startingTokenPrice <= UINT_FP_SCALING_FACTOR.mul(10**9));

        // TODO(mrice32): we should have an ideal start time rather than blindly polling.
        (uint256 latestTime, int256 latestUnderlyingPrice) = s.externalAddresses.priceFeed.latestPrice(
            s.fixedParameters.product
        );

        // If nonzero, take the user input as the starting price.
        if (params.startingUnderlyingPrice != 0) {
            latestUnderlyingPrice = _safeIntCast(params.startingUnderlyingPrice);
        }

        require(latestUnderlyingPrice > 0);
        require(latestTime != 0);

        // Keep the ratio in case it's needed for margin computation.
        s.fixedParameters.initialTokenUnderlyingRatio = params.startingTokenPrice.mul(UINT_FP_SCALING_FACTOR).div(
            _safeUintCast(latestUnderlyingPrice)
        );
        require(s.fixedParameters.initialTokenUnderlyingRatio != 0);

        // Set end time to max value of uint256 to implement no expiry.
        if (params.expiry == 0) {
            s.endTime = ~uint256(0);
        } else {
            require(params.expiry >= latestTime);
            s.endTime = params.expiry;
        }

        s.nav = s._computeInitialNav(latestUnderlyingPrice, latestTime, params.startingTokenPrice);

        s.state = TDS.State.Live;
    }

    function _getOracleAddress(TDS.Storage storage s) internal view returns (address) {
        return s.externalAddresses.finder.getImplementationAddress(OracleInterfaces.Oracle);
    }

    function _getIdentifierWhitelistAddress(TDS.Storage storage s) internal view returns (address) {
        return s.externalAddresses.finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist);
    }

    function _getStoreAddress(TDS.Storage storage s) internal view returns (address) {
        return s.externalAddresses.finder.getImplementationAddress(OracleInterfaces.Store);
    }

    function _getAdminAddress(TDS.Storage storage s) internal view returns (address) {
        return s.externalAddresses.finder.getImplementationAddress(OracleInterfaces.FinancialContractsAdmin);
    }

    function _calcNewTokenStateAndBalance(TDS.Storage storage s)
        internal
        view
        returns (TDS.TokenState memory newTokenState, int256 newShortMarginBalance)
    {
        // TODO: there's a lot of repeated logic in this method from elsewhere in the contract. It should be extracted
        // so the logic can be written once and used twice. However, much of this was written post-audit, so it was
        // deemed preferable not to modify any state changing code that could potentially introduce new security
        // bugs. This should be done before the next contract audit.

        if (s.state == TDS.State.Settled) {
            // If the contract is Settled, just return the current contract state.
            return (s.currentTokenState, s.shortBalance);
        }

        // Grab the price feed pricetime.
        (uint256 priceFeedTime, int256 priceFeedPrice) = s._getLatestPrice();

        bool isContractLive = s.state == TDS.State.Live;
        bool isContractPostExpiry = priceFeedTime >= s.endTime;

        // If the time hasn't advanced since the last remargin, short circuit and return the most recently computed
        // values.
        if (isContractLive && priceFeedTime <= s.currentTokenState.time) {
            return (s.currentTokenState, s.shortBalance);
        }

        // Determine which previous price state to use when computing the new NAV.
        // If the contract is live, we use the reference for the linear return type or if the contract will immediately
        // move to expiry.
        bool shouldUseReferenceTokenState = isContractLive &&
            (s.fixedParameters.returnType == TokenizedDerivativeParams.ReturnType.Linear || isContractPostExpiry);
        TDS.TokenState memory lastTokenState = (
            shouldUseReferenceTokenState ? s.referenceTokenState : s.currentTokenState
        );

        // Use the oracle settlement price/time if the contract is frozen or will move to expiry on the next remargin.
        (uint256 recomputeTime, int256 recomputePrice) = !isContractLive || isContractPostExpiry
            ? (s.endTime, OracleInterface(_getOracleAddress(s)).getPrice(s.fixedParameters.product, s.endTime))
            : (priceFeedTime, priceFeedPrice);

        // Init the returned short balance to the current short balance.
        newShortMarginBalance = s.shortBalance;

        // Subtract the oracle fees from the short balance.
        newShortMarginBalance = isContractLive
            ? newShortMarginBalance.sub(
                _safeIntCast(s._computeExpectedOracleFees(s.currentTokenState.time, recomputeTime))
            )
            : newShortMarginBalance;

        // Compute the new NAV
        newTokenState = s._computeNewTokenState(lastTokenState, recomputePrice, recomputeTime);
        int256 navNew = _computeNavForTokens(newTokenState.tokenPrice, _totalSupply());
        newShortMarginBalance = newShortMarginBalance.sub(_getLongDiff(navNew, s.longBalance, newShortMarginBalance));

        bool inDefault = !s._satisfiesMarginRequirement(newShortMarginBalance, newTokenState);
        // If the contract is about to enter a frozen state (i.e., either expiry or default), then an Oracle final fee
        // will need to be paid.
        if (isContractLive && (isContractPostExpiry || inDefault)) {
            uint256 oracleFinalFee = s._computeOracleFinalFee(newShortMarginBalance);
            newShortMarginBalance = newShortMarginBalance.sub(_safeIntCast(oracleFinalFee));
        }

        // If the contract is frozen or will move into expiry, we need to settle it, which means adding the default
        // penalty and dispute deposit if necessary.
        if (!isContractLive || isContractPostExpiry) {
            // Subtract default penalty (if necessary) from the short balance.
            if (inDefault) {
                int256 expectedDefaultPenalty = isContractLive ? s._computeDefaultPenalty() : s._getDefaultPenalty();
                int256 defaultPenalty = (newShortMarginBalance < expectedDefaultPenalty)
                    ? newShortMarginBalance
                    : expectedDefaultPenalty;
                newShortMarginBalance = newShortMarginBalance.sub(defaultPenalty);
            }

            // Add the dispute deposit to the short balance if necessary.
            if (s.state == TDS.State.Disputed && navNew != s.disputeInfo.disputedNav) {
                int256 depositValue = _safeIntCast(s.disputeInfo.deposit);
                newShortMarginBalance = newShortMarginBalance.add(depositValue);
            }
        }
    }

    function _computeInitialNav(
        TDS.Storage storage s,
        int256 latestUnderlyingPrice,
        uint256 latestTime,
        uint256 startingTokenPrice
    ) internal returns (int256 navNew) {
        int256 unitNav = _safeIntCast(startingTokenPrice);
        s.referenceTokenState = TDS.TokenState(latestUnderlyingPrice, unitNav, latestTime);
        s.currentTokenState = TDS.TokenState(latestUnderlyingPrice, unitNav, latestTime);
        // Starting NAV is always 0 in the TokenizedDerivative case.
        navNew = 0;
    }

    function _setExternalAddresses(TDS.Storage storage s, TokenizedDerivativeParams.ConstructorParams memory params)
        internal
    {
        // Note: not all "ERC20" tokens conform exactly to this interface (BNB, OMG, etc). The most common way that
        // tokens fail to conform is that they do not return a bool from certain state-changing operations. This
        // contract was not designed to work with those tokens because of the additional complexity they would
        // introduce.
        s.externalAddresses.marginCurrency = IERC20(params.marginCurrency);

        s.externalAddresses.returnCalculator = ReturnCalculatorInterface(params.returnCalculator);
        s.externalAddresses.finder = FinderInterface(params.finderAddress);
        s.externalAddresses.priceFeed = PriceFeedInterface(params.priceFeedAddress);

        // Verify that the price feed and Oracle support the given s.fixedParameters.product.
        IdentifierWhitelistInterface supportedIdentifiers = IdentifierWhitelistInterface(
            _getIdentifierWhitelistAddress(s)
        );
        require(supportedIdentifiers.isIdentifierSupported(params.product));
        require(s.externalAddresses.priceFeed.isIdentifierSupported(params.product));

        s.externalAddresses.sponsor = params.sponsor;
    }

    function _setFixedParameters(
        TDS.Storage storage s,
        TokenizedDerivativeParams.ConstructorParams memory params,
        string memory symbol
    ) internal {
        // Ensure only valid enum values are provided.
        require(
            params.returnType == TokenizedDerivativeParams.ReturnType.Compound ||
                params.returnType == TokenizedDerivativeParams.ReturnType.Linear
        );

        // Fee must be 0 if the returnType is linear.
        require(params.returnType == TokenizedDerivativeParams.ReturnType.Compound || params.fixedYearlyFee == 0);

        // The default penalty must be less than the required margin.
        require(params.defaultPenalty <= UINT_FP_SCALING_FACTOR);

        s.fixedParameters.returnType = params.returnType;
        s.fixedParameters.defaultPenalty = params.defaultPenalty;
        s.fixedParameters.product = params.product;
        s.fixedParameters.fixedFeePerSecond = params.fixedYearlyFee.div(SECONDS_PER_YEAR);
        s.fixedParameters.disputeDeposit = params.disputeDeposit;
        s.fixedParameters.supportedMove = params.supportedMove;
        s.fixedParameters.withdrawLimit = params.withdrawLimit;
        s.fixedParameters.creationTime = params.creationTime;
        s.fixedParameters.symbol = symbol;
    }

    // _remarginInternal() allows other functions to call remargin internally without satisfying permission checks for
    // _remargin().
    function _remarginInternal(TDS.Storage storage s) internal {
        // If the state is not live, remargining does not make sense.
        require(s.state == TDS.State.Live);

        (uint256 latestTime, int256 latestPrice) = s._getLatestPrice();
        // Checks whether contract has ended.
        if (latestTime <= s.currentTokenState.time) {
            // If the price feed hasn't advanced, remargining should be a no-op.
            return;
        }

        // Save the penalty using the current state in case it needs to be used.
        int256 potentialPenaltyAmount = s._computeDefaultPenalty();

        if (latestTime >= s.endTime) {
            s.state = TDS.State.Expired;
            emit Expired(s.fixedParameters.symbol, s.endTime);

            // Applies the same update a second time to effectively move the current state to the reference state.
            int256 recomputedNav = s._computeNav(s.currentTokenState.underlyingPrice, s.currentTokenState.time);
            assert(recomputedNav == s.nav);

            uint256 feeAmount = s._deductOracleFees(s.currentTokenState.time, s.endTime);

            // Save the precomputed default penalty in case the expiry price pushes the sponsor into default.
            s.defaultPenaltyAmount = potentialPenaltyAmount;

            // We have no idea what the price was, exactly at s.endTime, so we can't set
            // s.currentTokenState, or update the nav, or do anything.
            s._requestOraclePrice(s.endTime);
            s._payOracleFees(feeAmount);
            return;
        }
        uint256 feeAmount = s._deductOracleFees(s.currentTokenState.time, latestTime);

        // Update nav of contract.
        int256 navNew = s._computeNav(latestPrice, latestTime);

        // Update the balances of the contract.
        s._updateBalances(navNew);

        // Make sure contract has not moved into default.
        bool inDefault = !s._satisfiesMarginRequirement(s.shortBalance, s.currentTokenState);
        if (inDefault) {
            s.state = TDS.State.Defaulted;
            s.defaultPenaltyAmount = potentialPenaltyAmount;
            s.endTime = latestTime; // Change end time to moment when default occurred.
            emit Default(s.fixedParameters.symbol, latestTime, s.nav);
            s._requestOraclePrice(latestTime);
        }

        s._payOracleFees(feeAmount);
    }

    function _createTokensInternal(
        TDS.Storage storage s,
        uint256 tokensToPurchase,
        uint256 navSent
    ) internal returns (uint256 refund) {
        s._remarginInternal();

        // Verify that remargining didn't push the contract into expiry or default.
        require(s.state == TDS.State.Live);

        int256 purchasedNav = _computeNavForTokens(s.currentTokenState.tokenPrice, tokensToPurchase);

        if (purchasedNav < 0) {
            purchasedNav = 0;
        }

        // Ensures that requiredNav >= navSent.
        refund = navSent.sub(_safeUintCast(purchasedNav));

        s.longBalance = s.longBalance.add(purchasedNav);

        ExpandedIERC20 thisErc20Token = ExpandedIERC20(address(this));

        require(thisErc20Token.mint(msg.sender, tokensToPurchase), "Token minting failed");
        emit TokensCreated(s.fixedParameters.symbol, tokensToPurchase);

        s.nav = _computeNavForTokens(s.currentTokenState.tokenPrice, _totalSupply());

        // Make sure this still satisfies the margin requirement.
        require(s._satisfiesMarginRequirement(s.shortBalance, s.currentTokenState));
    }

    function _depositInternal(TDS.Storage storage s, uint256 value) internal {
        // Make sure that we are in a "depositable" state.
        require(s.state == TDS.State.Live);
        s.shortBalance = s.shortBalance.add(_safeIntCast(value));
        emit Deposited(s.fixedParameters.symbol, value);
    }

    function _settleInternal(TDS.Storage storage s) internal {
        TDS.State startingState = s.state;
        require(
            startingState == TDS.State.Disputed ||
                startingState == TDS.State.Expired ||
                startingState == TDS.State.Defaulted ||
                startingState == TDS.State.Emergency
        );
        s._settleVerifiedPrice();
        if (startingState == TDS.State.Disputed) {
            int256 depositValue = _safeIntCast(s.disputeInfo.deposit);
            if (s.nav != s.disputeInfo.disputedNav) {
                s.shortBalance = s.shortBalance.add(depositValue);
            } else {
                s.longBalance = s.longBalance.add(depositValue);
            }
        }
    }

    // Deducts the fees from the margin account.
    function _deductOracleFees(
        TDS.Storage storage s,
        uint256 lastTimeOracleFeesPaid,
        uint256 currentTime
    ) internal returns (uint256 feeAmount) {
        feeAmount = s._computeExpectedOracleFees(lastTimeOracleFeesPaid, currentTime);
        s.shortBalance = s.shortBalance.sub(_safeIntCast(feeAmount));
        // If paying the Oracle fee reduces the held margin below requirements, the rest of remargin() will default the
        // contract.
    }

    // Pays out the fees to the Oracle.
    function _payOracleFees(TDS.Storage storage s, uint256 feeAmount) internal {
        if (feeAmount == 0) {
            return;
        }

        StoreInterface store = StoreInterface(_getStoreAddress(s));
        if (address(s.externalAddresses.marginCurrency) == address(0x0)) {
            store.payOracleFees.value(feeAmount)();
        } else {
            require(s.externalAddresses.marginCurrency.approve(address(store), feeAmount));
            store.payOracleFeesErc20(address(s.externalAddresses.marginCurrency), FixedPoint.Unsigned(feeAmount));
        }
    }

    function _computeExpectedOracleFees(
        TDS.Storage storage s,
        uint256 lastTimeOracleFeesPaid,
        uint256 currentTime
    ) internal view returns (uint256 feeAmount) {
        StoreInterface store = StoreInterface(_getStoreAddress(s));
        // The profit from corruption is set as the max(longBalance, shortBalance).
        int256 pfc = s.shortBalance < s.longBalance ? s.longBalance : s.shortBalance;
        (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory delayFee) = store.computeRegularFee(
            lastTimeOracleFeesPaid,
            currentTime,
            FixedPoint.Unsigned(_safeUintCast(pfc))
        );
        // TODO(ptare): Implement a keeper system, but for now, pay the delay fee to the Oracle.
        uint256 expectedFeeAmount = regularFee.add(delayFee).rawValue;

        // Ensure the fee returned can actually be paid by the short margin account.
        uint256 shortBalance = _safeUintCast(s.shortBalance);
        return (shortBalance < expectedFeeAmount) ? shortBalance : expectedFeeAmount;
    }

    function _computeNewTokenState(
        TDS.Storage storage s,
        TDS.TokenState memory beginningTokenState,
        int256 latestUnderlyingPrice,
        uint256 recomputeTime
    ) internal view returns (TDS.TokenState memory newTokenState) {
        int256 underlyingReturn = s.externalAddresses.returnCalculator.computeReturn(
            beginningTokenState.underlyingPrice,
            latestUnderlyingPrice
        );
        int256 tokenReturn = underlyingReturn.sub(
            _safeIntCast(s.fixedParameters.fixedFeePerSecond.mul(recomputeTime.sub(beginningTokenState.time)))
        );
        int256 tokenMultiplier = tokenReturn.add(INT_FP_SCALING_FACTOR);

        // In the compound case, don't allow the token price to go below 0.
        if (s.fixedParameters.returnType == TokenizedDerivativeParams.ReturnType.Compound && tokenMultiplier < 0) {
            tokenMultiplier = 0;
        }

        int256 newTokenPrice = _takePercentage(beginningTokenState.tokenPrice, tokenMultiplier);
        newTokenState = TDS.TokenState(latestUnderlyingPrice, newTokenPrice, recomputeTime);
    }

    function _satisfiesMarginRequirement(
        TDS.Storage storage s,
        int256 balance,
        TDS.TokenState memory tokenState
    ) internal view returns (bool doesSatisfyRequirement) {
        return s._getRequiredMargin(tokenState) <= balance;
    }

    function _requestOraclePrice(TDS.Storage storage s, uint256 requestedTime) internal {
        uint256 finalFee = s._computeOracleFinalFee(s.shortBalance);
        s.shortBalance = s.shortBalance.sub(_safeIntCast(finalFee));
        s._payOracleFees(finalFee);

        OracleInterface oracle = OracleInterface(_getOracleAddress(s));
        bool availablePrice = oracle.hasPrice(s.fixedParameters.product, requestedTime);
        if (availablePrice) {
            // The Oracle price is already available, settle the contract right away.
            s._settleInternal();
        } else {
            oracle.requestPrice(s.fixedParameters.product, requestedTime);
        }
    }

    function _computeOracleFinalFee(TDS.Storage storage s, int256 shortBalance)
        internal
        view
        returns (uint256 actualFeeAmount)
    {
        StoreInterface store = StoreInterface(_getStoreAddress(s));
        FixedPoint.Unsigned memory expectedFee = store.computeFinalFee(address(s.externalAddresses.marginCurrency));
        uint256 expectedFeeAmount = expectedFee.rawValue;
        // Ensure the fee returned can actually be paid by the short margin account.
        uint256 shortBalanceuint256 = _safeUintCast(shortBalance);
        actualFeeAmount = (shortBalanceuint256 < expectedFeeAmount) ? shortBalanceuint256 : expectedFeeAmount;
    }

    function _getLatestPrice(TDS.Storage storage s)
        internal
        view
        returns (uint256 latestTime, int256 latestUnderlyingPrice)
    {
        (latestTime, latestUnderlyingPrice) = s.externalAddresses.priceFeed.latestPrice(s.fixedParameters.product);
        require(latestTime != 0);
    }

    function _computeNav(
        TDS.Storage storage s,
        int256 latestUnderlyingPrice,
        uint256 latestTime
    ) internal returns (int256 navNew) {
        if (s.fixedParameters.returnType == TokenizedDerivativeParams.ReturnType.Compound) {
            navNew = s._computeCompoundNav(latestUnderlyingPrice, latestTime);
        } else {
            assert(s.fixedParameters.returnType == TokenizedDerivativeParams.ReturnType.Linear);
            navNew = s._computeLinearNav(latestUnderlyingPrice, latestTime);
        }
    }

    function _computeCompoundNav(
        TDS.Storage storage s,
        int256 latestUnderlyingPrice,
        uint256 latestTime
    ) internal returns (int256 navNew) {
        s.referenceTokenState = s.currentTokenState;
        s.currentTokenState = s._computeNewTokenState(s.currentTokenState, latestUnderlyingPrice, latestTime);
        navNew = _computeNavForTokens(s.currentTokenState.tokenPrice, _totalSupply());
        emit NavUpdated(s.fixedParameters.symbol, navNew, s.currentTokenState.tokenPrice);
    }

    function _computeLinearNav(
        TDS.Storage storage s,
        int256 latestUnderlyingPrice,
        uint256 latestTime
    ) internal returns (int256 navNew) {
        // Only update the time - don't update the prices becuase all price changes are relative to the initial price.
        s.referenceTokenState.time = s.currentTokenState.time;
        s.currentTokenState = s._computeNewTokenState(s.referenceTokenState, latestUnderlyingPrice, latestTime);
        navNew = _computeNavForTokens(s.currentTokenState.tokenPrice, _totalSupply());
        emit NavUpdated(s.fixedParameters.symbol, navNew, s.currentTokenState.tokenPrice);
    }

    function _recomputeNav(
        TDS.Storage storage s,
        int256 oraclePrice,
        uint256 recomputeTime
    ) internal returns (int256 navNew) {
        // We're updating `last` based on what the Oracle has told us.
        assert(s.endTime == recomputeTime);
        s.currentTokenState = s._computeNewTokenState(s.referenceTokenState, oraclePrice, recomputeTime);
        navNew = _computeNavForTokens(s.currentTokenState.tokenPrice, _totalSupply());
        emit NavUpdated(s.fixedParameters.symbol, navNew, s.currentTokenState.tokenPrice);
    }

    // Function is internally only called by `_settleAgreedPrice` or `_settleVerifiedPrice`. This function handles all
    // of the settlement logic including assessing penalties and then moves the state to `Settled`.
    function _settleWithPrice(TDS.Storage storage s, int256 price) internal {
        // Remargin at whatever price we're using (verified or unverified).
        s._updateBalances(s._recomputeNav(price, s.endTime));

        bool inDefault = !s._satisfiesMarginRequirement(s.shortBalance, s.currentTokenState);

        if (inDefault) {
            int256 expectedDefaultPenalty = s._getDefaultPenalty();
            int256 penalty = (s.shortBalance < expectedDefaultPenalty) ? s.shortBalance : expectedDefaultPenalty;

            s.shortBalance = s.shortBalance.sub(penalty);
            s.longBalance = s.longBalance.add(penalty);
        }

        s.state = TDS.State.Settled;
        emit Settled(s.fixedParameters.symbol, s.endTime, s.nav);
    }

    function _updateBalances(TDS.Storage storage s, int256 navNew) internal {
        // Compute difference -- Add the difference to owner and subtract
        // from counterparty. Then update nav state variable.
        int256 longDiff = _getLongDiff(navNew, s.longBalance, s.shortBalance);
        s.nav = navNew;

        s.longBalance = s.longBalance.add(longDiff);
        s.shortBalance = s.shortBalance.sub(longDiff);
    }

    function _getDefaultPenalty(TDS.Storage storage s) internal view returns (int256 penalty) {
        return s.defaultPenaltyAmount;
    }

    function _computeDefaultPenalty(TDS.Storage storage s) internal view returns (int256 penalty) {
        return _takePercentage(s._getRequiredMargin(s.currentTokenState), s.fixedParameters.defaultPenalty);
    }

    function _getRequiredMargin(TDS.Storage storage s, TDS.TokenState memory tokenState)
        internal
        view
        returns (int256 requiredMargin)
    {
        int256 leverageMagnitude = _absoluteValue(s.externalAddresses.returnCalculator.leverage());

        int256 effectiveNotional;
        if (s.fixedParameters.returnType == TokenizedDerivativeParams.ReturnType.Linear) {
            int256 effectiveUnitsOfUnderlying = _safeIntCast(
                _totalSupply().mul(s.fixedParameters.initialTokenUnderlyingRatio).div(UINT_FP_SCALING_FACTOR)
            )
                .mul(leverageMagnitude);
            effectiveNotional = effectiveUnitsOfUnderlying.mul(tokenState.underlyingPrice).div(INT_FP_SCALING_FACTOR);
        } else {
            int256 currentNav = _computeNavForTokens(tokenState.tokenPrice, _totalSupply());
            effectiveNotional = currentNav.mul(leverageMagnitude);
        }

        // Take the absolute value of the notional since a negative notional has similar risk properties to a positive
        // notional of the same size, and, therefore, requires the same margin.
        requiredMargin = _takePercentage(_absoluteValue(effectiveNotional), s.fixedParameters.supportedMove);
    }

    function _pullSentMargin(TDS.Storage storage s, uint256 expectedMargin) internal returns (uint256 refund) {
        if (address(s.externalAddresses.marginCurrency) == address(0x0)) {
            // Refund is any amount of ETH that was sent that was above the amount that was expected.
            // Note: SafeMath will force a revert if msg.value < expectedMargin.
            return msg.value.sub(expectedMargin);
        } else {
            // If we expect an ERC20 token, no ETH should be sent.
            require(msg.value == 0);
            _pullAuthorizedTokens(s.externalAddresses.marginCurrency, expectedMargin);

            // There is never a refund in the ERC20 case since we use the argument to determine how much to "pull".
            return 0;
        }
    }

    function _sendMargin(TDS.Storage storage s, uint256 amount) internal {
        // There's no point in attempting a send if there's nothing to send.
        if (amount == 0) {
            return;
        }

        if (address(s.externalAddresses.marginCurrency) == address(0x0)) {
            msg.sender.transfer(amount);
        } else {
            require(s.externalAddresses.marginCurrency.transfer(msg.sender, amount));
        }
    }

    function _settleAgreedPrice(TDS.Storage storage s) internal {
        int256 agreedPrice = s.currentTokenState.underlyingPrice;

        s._settleWithPrice(agreedPrice);
    }

    function _settleVerifiedPrice(TDS.Storage storage s) internal {
        OracleInterface oracle = OracleInterface(_getOracleAddress(s));
        int256 oraclePrice = oracle.getPrice(s.fixedParameters.product, s.endTime);
        s._settleWithPrice(oraclePrice);
    }

    function _pullAuthorizedTokens(IERC20 erc20, uint256 amountToPull) private {
        // If nothing is being pulled, there's no point in calling a transfer.
        if (amountToPull > 0) {
            require(erc20.transferFrom(msg.sender, address(this), amountToPull));
        }
    }

    // Gets the change in balance for the long side.
    // Note: there's a function for this because signage is tricky here, and it must be done the same everywhere.
    function _getLongDiff(
        int256 navNew,
        int256 longBalance,
        int256 shortBalance
    ) private pure returns (int256 longDiff) {
        int256 newLongBalance = navNew;

        // Long balance cannot go below zero.
        if (newLongBalance < 0) {
            newLongBalance = 0;
        }

        longDiff = newLongBalance.sub(longBalance);

        // Cannot pull more margin from the short than is available.
        if (longDiff > shortBalance) {
            longDiff = shortBalance;
        }
    }

    function _computeNavForTokens(int256 tokenPrice, uint256 numTokens) private pure returns (int256 navNew) {
        int256 navPreDivision = _safeIntCast(numTokens).mul(tokenPrice);
        navNew = navPreDivision.div(INT_FP_SCALING_FACTOR);

        // The navNew division above truncates by default. Instead, we prefer to ceil this value to ensure tokens
        // cannot be purchased or backed with less than their true value.
        if ((navPreDivision % INT_FP_SCALING_FACTOR) != 0) {
            navNew = navNew.add(1);
        }
    }

    function _totalSupply() private view returns (uint256 totalSupply) {
        ExpandedIERC20 thisErc20Token = ExpandedIERC20(address(this));
        return thisErc20Token.totalSupply();
    }

    function _takePercentage(uint256 value, uint256 percentage) private pure returns (uint256 result) {
        return value.mul(percentage).div(UINT_FP_SCALING_FACTOR);
    }

    function _takePercentage(int256 value, uint256 percentage) private pure returns (int256 result) {
        return value.mul(_safeIntCast(percentage)).div(INT_FP_SCALING_FACTOR);
    }

    function _takePercentage(int256 value, int256 percentage) private pure returns (int256 result) {
        return value.mul(percentage).div(INT_FP_SCALING_FACTOR);
    }

    function _absoluteValue(int256 value) private pure returns (int256 result) {
        return value < 0 ? value.mul(-1) : value;
    }

    function _safeIntCast(uint256 value) private pure returns (int256 result) {
        require(value <= INT_MAX);
        return int256(value);
    }

    function _safeUintCast(int256 value) private pure returns (uint256 result) {
        require(value >= 0);
        return uint256(value);
    }
}


/**
 * @title A synthetic token whose value tracks an arbitrary price feed.
 */
contract TokenizedDerivative is ERC20, AdministrateeInterface, ExpandedIERC20 {
    using TokenizedDerivativeUtils for TDS.Storage;

    TDS.Storage public derivativeStorage;

    // These events are actually emitted by TokenizedDerivativeUtils, but we unfortunately have to define the events
    // here as well.
    event NavUpdated(string symbol, int256 newNav, int256 newTokenPrice);
    event Default(string symbol, uint256 defaultTime, int256 defaultNav);
    event Settled(string symbol, uint256 settleTime, int256 finalNav);
    event Expired(string symbol, uint256 expiryTime);
    event Disputed(string symbol, uint256 timeDisputed, int256 navDisputed);
    event EmergencyShutdownTransition(string symbol, uint256 shutdownTime);
    event TokensCreated(string symbol, uint256 numTokensCreated);
    event TokensRedeemed(string symbol, uint256 numTokensRedeemed);
    event Deposited(string symbol, uint256 amount);
    event Withdrawal(string symbol, uint256 amount);

    constructor(
        TokenizedDerivativeParams.ConstructorParams memory params,
        string memory _name,
        string memory _symbol
    ) public ERC20(_name, _symbol) {
        // Initialize the contract.
        derivativeStorage._initialize(params, _symbol);
    }

    /**
     * @notice Creates tokens with sent margin and sends the caller back any additional margin.
     * @param marginForPurchase Maximum amount of margin currency to use to create tokens.
     * @param tokensToPurchase Number of tokens to create.
     */
    function createTokens(uint256 marginForPurchase, uint256 tokensToPurchase) external payable {
        derivativeStorage._createTokens(marginForPurchase, tokensToPurchase);
    }

    /**
     * @notice Creates tokens with sent margin and deposits additional margin in short account.
     * @param marginForPurchase Maximum amount of margin currency to use to create tokens.
     * @param tokensToPurchase Number of tokens to create.
     */
    function depositAndCreateTokens(uint256 marginForPurchase, uint256 tokensToPurchase) external payable {
        derivativeStorage._depositAndCreateTokens(marginForPurchase, tokensToPurchase);
    }

    /**
     * @notice Redeems tokens for margin currency.
     */
    function redeemTokens(uint256 tokensToRedeem) external {
        derivativeStorage._redeemTokens(tokensToRedeem);
    }

    /**
     * @notice Triggers a price dispute for the most recent remargin time.
     * @param depositMargin Must be at least `disputeDeposit` percent of the required margin.
     */
    function dispute(uint256 depositMargin) external payable {
        derivativeStorage._dispute(depositMargin);
    }

    /**
     * @notice Withdraws `amount` from short margin account.
     */
    function withdraw(uint256 amount) external {
        derivativeStorage._withdraw(amount);
    }

    /**
     * @notice Pays (Oracle and service) fees for the previous period, updates the contract NAV, moves margin between
     * long and short accounts to reflect the new NAV, and checks if both accounts meet minimum requirements.
     */
    function remargin() external override {
        derivativeStorage._remargin();
    }

    /**
     * @notice Forgo the Oracle verified price and settle the contract with last remargin price.
     * @dev This method is only callable on contracts in the `Defaulted` state, and the default penalty is always
     * transferred from the short to the long account.
     */
    function acceptPriceAndSettle() external {
        derivativeStorage._acceptPriceAndSettle();
    }

    /**
     * @notice Assigns an address to be the contract's Delegate AP that can create and redeem.
     * @dev Replaces previous value. Set to 0x0 to indicate there is no Delegate AP.
     */
    function setApDelegate(address apDelegate) external {
        derivativeStorage._setApDelegate(apDelegate);
    }

    /**
     * @notice Moves the contract into the Emergency state, where it waits on an Oracle price for the most recent
     * remargin time.
     */
    function emergencyShutdown() external override {
        derivativeStorage._emergencyShutdown();
    }

    /**
     * @notice Performs a final remargin, assesses any penalties, and moves the contract into the `Settled` state. An
     * Oracle price must be available.
     */
    function settle() external {
        derivativeStorage._settle();
    }

    /**
     * @notice Adds the margin to the short account.
     * @dev For ETH-margined contracts, send ETH along with the call. In the case of an ERC20 margin currency, authorize
     * before calling this method.
     */
    function deposit(uint256 amountToDeposit) external payable {
        derivativeStorage._deposit(amountToDeposit);
    }

    /**
     * @notice Withdraw any ERC20 balance that is not the margin token. Only callable by the sponsor.
     */
    function withdrawUnexpectedErc20(address erc20Address, uint256 amount) external {
        derivativeStorage._withdrawUnexpectedErc20(erc20Address, amount);
    }

    // ExpandedIERC20 methods.
    modifier onlyThis {
        require(msg.sender == address(this));
        _;
    }

    /**
     * @notice Destroys `value` tokens from the caller.
     * @dev Only this contract or its libraries are allowed to burn tokens.
     */
    function burn(uint256 value) external override onlyThis {
        _burn(msg.sender, value);
    }

    /**
     * @notice Creates `value` tokens and assigns them to `to`, increasing the total supply.
     * @dev Only this contract or its libraries are allowed to mint tokens.
     */
    function mint(address to, uint256 value) external override onlyThis returns (bool) {
        _mint(to, value);
        return true;
    }

    /**
     * @notice Returns the expected net asset value (NAV) of the contract using the latest available Price Feed price.
     */
    function calcNAV() external view returns (int256 navNew) {
        return derivativeStorage._calcNAV();
    }

    /**
     * @notice Returns the expected value of each the outstanding tokens of the contract using the latest available
     * Price Feed price.
     */
    function calcTokenValue() external view returns (int256 newTokenValue) {
        return derivativeStorage._calcTokenValue();
    }

    /**
     * @notice Returns the expected balance of the short margin account using the latest available Price Feed price.
     */
    function calcShortMarginBalance() external view returns (int256 newShortMarginBalance) {
        return derivativeStorage._calcShortMarginBalance();
    }

    /**
     * @notice Returns the expected short margin in excess of the margin requirement using the latest available Price
     * Feed price.
     * @dev Value will be negative if the short margin is expected to be below the margin requirement.
     */
    function calcExcessMargin() external view returns (int256 excessMargin) {
        return derivativeStorage._calcExcessMargin();
    }

    /**
     * @notice Returns the required margin, as of the last remargin.
     * @dev Note that `calcExcessMargin` uses updated values using the latest available Price Feed price.
     */
    function getCurrentRequiredMargin() external view returns (int256 requiredMargin) {
        return derivativeStorage._getCurrentRequiredMargin();
    }

    /**
     * @notice Returns whether the contract can be settled, i.e., is it valid to call settle() now.
     */
    function canBeSettled() external view returns (bool canContractBeSettled) {
        return derivativeStorage._canBeSettled();
    }

    /**
     * @notice Returns the updated underlying price that was used in the calc* methods above.
     * @dev It will be a price feed price if the contract is Live and will remain Live, or an Oracle price if the
     * contract is settled/about to be settled.  Reverts if no Oracle price is available but an Oracle price is
     * required.
     */
    function getUpdatedUnderlyingPrice() external view returns (int256 underlyingPrice, uint256 time) {
        return derivativeStorage._getUpdatedUnderlyingPrice();
    }
}

File 103 of 117: TokenizedDerivativeCreator.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./Testable.sol";
import "./AddressWhitelist.sol";
import "./ContractCreator.sol";
import "./TokenizedDerivative.sol";


/**
 * @title Contract creator for TokenizedDerivative.
 */
contract TokenizedDerivativeCreator is ContractCreator, Testable {
    struct Params {
        address priceFeedAddress;
        uint256 defaultPenalty; // Percentage of mergin requirement * 10^18
        uint256 supportedMove; // Expected percentage move in the underlying that the long is protected against.
        bytes32 product;
        uint256 fixedYearlyFee; // Percentage of nav * 10^18
        uint256 disputeDeposit; // Percentage of mergin requirement * 10^18
        address returnCalculator;
        uint256 startingTokenPrice;
        uint256 expiry;
        address marginCurrency;
        uint256 withdrawLimit; // Percentage of shortBalance * 10^18
        TokenizedDerivativeParams.ReturnType returnType;
        uint256 startingUnderlyingPrice;
        string name;
        string symbol;
    }

    AddressWhitelist public returnCalculatorWhitelist;
    AddressWhitelist public marginCurrencyWhitelist;

    event CreatedTokenizedDerivative(address contractAddress);

    constructor(
        address _finderAddress,
        address _returnCalculatorWhitelist,
        address _marginCurrencyWhitelist,
        address _timerAddress
    ) public ContractCreator(_finderAddress) Testable(_timerAddress) {
        returnCalculatorWhitelist = AddressWhitelist(_returnCalculatorWhitelist);
        marginCurrencyWhitelist = AddressWhitelist(_marginCurrencyWhitelist);
    }

    /**
     * @notice Creates a new instance of `TokenizedDerivative` with the provided `params`.
     */
    function createTokenizedDerivative(Params memory params) public returns (address derivativeAddress) {
        TokenizedDerivative derivative = new TokenizedDerivative(_convertParams(params), params.name, params.symbol);

        address[] memory parties = new address[](1);
        parties[0] = msg.sender;

        _registerContract(parties, address(derivative));

        emit CreatedTokenizedDerivative(address(derivative));

        return address(derivative);
    }

    // Converts createTokenizedDerivative params to TokenizedDerivative constructor params.
    function _convertParams(Params memory params)
        private
        view
        returns (TokenizedDerivativeParams.ConstructorParams memory constructorParams)
    {
        // Copy and verify externally provided variables.
        constructorParams.sponsor = msg.sender;

        require(returnCalculatorWhitelist.isOnWhitelist(params.returnCalculator));
        constructorParams.returnCalculator = params.returnCalculator;

        require(marginCurrencyWhitelist.isOnWhitelist(params.marginCurrency));
        constructorParams.marginCurrency = params.marginCurrency;

        constructorParams.priceFeedAddress = params.priceFeedAddress;
        constructorParams.defaultPenalty = params.defaultPenalty;
        constructorParams.supportedMove = params.supportedMove;
        constructorParams.product = params.product;
        constructorParams.fixedYearlyFee = params.fixedYearlyFee;
        constructorParams.disputeDeposit = params.disputeDeposit;
        constructorParams.startingTokenPrice = params.startingTokenPrice;
        constructorParams.expiry = params.expiry;
        constructorParams.withdrawLimit = params.withdrawLimit;
        constructorParams.returnType = params.returnType;
        constructorParams.startingUnderlyingPrice = params.startingUnderlyingPrice;

        // Copy internal variables.
        constructorParams.finderAddress = finderAddress;
        constructorParams.creationTime = getCurrentTime();
    }
}

File 104 of 117: TokenMigrator.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./FixedPoint.sol";
import "./ExpandedIERC20.sol";
import "./VotingToken.sol";


/**
 * @title Migration contract for VotingTokens.
 * @dev Handles migrating token holders from one token to the next.
 */
contract TokenMigrator {
    using FixedPoint for FixedPoint.Unsigned;

    /****************************************
     *    INTERNAL VARIABLES AND STORAGE    *
     ****************************************/

    VotingToken public oldToken;
    ExpandedIERC20 public newToken;

    uint256 public snapshotId;
    FixedPoint.Unsigned public rate;

    mapping(address => bool) public hasMigrated;

    /**
     * @notice Construct the TokenMigrator contract.
     * @dev This function triggers the snapshot upon which all migrations will be based.
     * @param _rate the number of old tokens it takes to generate one new token.
     * @param _oldToken address of the token being migrated from.
     * @param _newToken address of the token being migrated to.
     */
    constructor(
        FixedPoint.Unsigned memory _rate,
        address _oldToken,
        address _newToken
    ) public {
        // Prevents division by 0 in migrateTokens().
        // Also it doesn’t make sense to have “0 old tokens equate to 1 new token”.
        require(_rate.isGreaterThan(0), "Rate can't be 0");
        rate = _rate;
        newToken = ExpandedIERC20(_newToken);
        oldToken = VotingToken(_oldToken);
        snapshotId = oldToken.snapshot();
    }

    /**
     * @notice Migrates the tokenHolder's old tokens to new tokens.
     * @dev This function can only be called once per `tokenHolder`. Anyone can call this method
     * on behalf of any other token holder since there is no disadvantage to receiving the tokens earlier.
     * @param tokenHolder address of the token holder to migrate.
     */
    function migrateTokens(address tokenHolder) external {
        require(!hasMigrated[tokenHolder], "Already migrated tokens");
        hasMigrated[tokenHolder] = true;

        FixedPoint.Unsigned memory oldBalance = FixedPoint.Unsigned(oldToken.balanceOfAt(tokenHolder, snapshotId));

        if (!oldBalance.isGreaterThan(0)) {
            return;
        }

        FixedPoint.Unsigned memory newBalance = oldBalance.div(rate);
        require(newToken.mint(tokenHolder, newBalance.rawValue), "Mint failed");
    }
}

File 105 of 117: TokenTimelock.sol
pragma solidity ^0.6.0;

import "./SafeERC20.sol";

/**
 * @dev A token holder contract that will allow a beneficiary to extract the
 * tokens after a given release time.
 *
 * Useful for simple vesting schedules like "advisors get all of their tokens
 * after 1 year".
 *
 * For a more complete vesting schedule, see {TokenVesting}.
 */
contract TokenTimelock {
    using SafeERC20 for IERC20;

    // ERC20 basic token contract being held
    IERC20 private _token;

    // beneficiary of tokens after they are released
    address private _beneficiary;

    // timestamp when token release is enabled
    uint256 private _releaseTime;

    constructor (IERC20 token, address beneficiary, uint256 releaseTime) public {
        // solhint-disable-next-line not-rely-on-time
        require(releaseTime > block.timestamp, "TokenTimelock: release time is before current time");
        _token = token;
        _beneficiary = beneficiary;
        _releaseTime = releaseTime;
    }

    /**
     * @return the token being held.
     */
    function token() public view returns (IERC20) {
        return _token;
    }

    /**
     * @return the beneficiary of the tokens.
     */
    function beneficiary() public view returns (address) {
        return _beneficiary;
    }

    /**
     * @return the time when the tokens are released.
     */
    function releaseTime() public view returns (uint256) {
        return _releaseTime;
    }

    /**
     * @notice Transfers tokens held by timelock to beneficiary.
     */
    function release() public virtual {
        // solhint-disable-next-line not-rely-on-time
        require(block.timestamp >= _releaseTime, "TokenTimelock: current time is before release time");

        uint256 amount = _token.balanceOf(address(this));
        require(amount > 0, "TokenTimelock: no tokens to release");

        _token.safeTransfer(_beneficiary, amount);
    }
}

File 106 of 117: TokenVesting.sol
pragma solidity ^0.6.0;

import "./SafeERC20.sol";
import "./Ownable.sol";
import "./SafeMath.sol";

/**
 * @title TokenVesting
 * @dev A token holder contract that can release its token balance gradually like a
 * typical vesting scheme, with a cliff and vesting period. Optionally revocable by the
 * owner.
 */
contract TokenVesting is Ownable {
    // The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and is
    // therefore sensitive to timestamp manipulation (which is something miners can do, to a certain degree). Therefore,
    // it is recommended to avoid using short time durations (less than a minute). Typical vesting schemes, with a
    // cliff period of a year and a duration of four years, are safe to use.
    // solhint-disable not-rely-on-time

    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    event TokensReleased(address token, uint256 amount);
    event TokenVestingRevoked(address token);

    // beneficiary of tokens after they are released
    address private _beneficiary;

    // Durations and timestamps are expressed in UNIX time, the same units as block.timestamp.
    uint256 private _cliff;
    uint256 private _start;
    uint256 private _duration;

    bool private _revocable;

    mapping (address => uint256) private _released;
    mapping (address => bool) private _revoked;

    /**
     * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
     * beneficiary, gradually in a linear fashion until start + duration. By then all
     * of the balance will have vested.
     * @param beneficiary address of the beneficiary to whom vested tokens are transferred
     * @param cliffDuration duration in seconds of the cliff in which tokens will begin to vest
     * @param start the time (as Unix time) at which point vesting starts
     * @param duration duration in seconds of the period in which the tokens will vest
     * @param revocable whether the vesting is revocable or not
     */
    constructor (address beneficiary, uint256 start, uint256 cliffDuration, uint256 duration, bool revocable) public {
        require(beneficiary != address(0), "TokenVesting: beneficiary is the zero address");
        // solhint-disable-next-line max-line-length
        require(cliffDuration <= duration, "TokenVesting: cliff is longer than duration");
        require(duration > 0, "TokenVesting: duration is 0");
        // solhint-disable-next-line max-line-length
        require(start.add(duration) > block.timestamp, "TokenVesting: final time is before current time");

        _beneficiary = beneficiary;
        _revocable = revocable;
        _duration = duration;
        _cliff = start.add(cliffDuration);
        _start = start;
    }

    /**
     * @return the beneficiary of the tokens.
     */
    function beneficiary() public view returns (address) {
        return _beneficiary;
    }

    /**
     * @return the cliff time of the token vesting.
     */
    function cliff() public view returns (uint256) {
        return _cliff;
    }

    /**
     * @return the start time of the token vesting.
     */
    function start() public view returns (uint256) {
        return _start;
    }

    /**
     * @return the duration of the token vesting.
     */
    function duration() public view returns (uint256) {
        return _duration;
    }

    /**
     * @return true if the vesting is revocable.
     */
    function revocable() public view returns (bool) {
        return _revocable;
    }

    /**
     * @return the amount of the token released.
     */
    function released(address token) public view returns (uint256) {
        return _released[token];
    }

    /**
     * @return true if the token is revoked.
     */
    function revoked(address token) public view returns (bool) {
        return _revoked[token];
    }

    /**
     * @notice Transfers vested tokens to beneficiary.
     * @param token ERC20 token which is being vested
     */
    function release(IERC20 token) public {
        uint256 unreleased = _releasableAmount(token);

        require(unreleased > 0, "TokenVesting: no tokens are due");

        _released[address(token)] = _released[address(token)].add(unreleased);

        token.safeTransfer(_beneficiary, unreleased);

        emit TokensReleased(address(token), unreleased);
    }

    /**
     * @notice Allows the owner to revoke the vesting. Tokens already vested
     * remain in the contract, the rest are returned to the owner.
     * @param token ERC20 token which is being vested
     */
    function revoke(IERC20 token) public onlyOwner {
        require(_revocable, "TokenVesting: cannot revoke");
        require(!_revoked[address(token)], "TokenVesting: token already revoked");

        uint256 balance = token.balanceOf(address(this));

        uint256 unreleased = _releasableAmount(token);
        uint256 refund = balance.sub(unreleased);

        _revoked[address(token)] = true;

        token.safeTransfer(owner(), refund);

        emit TokenVestingRevoked(address(token));
    }

    /**
     * @dev Calculates the amount that has already vested but hasn't been released yet.
     * @param token ERC20 token which is being vested
     */
    function _releasableAmount(IERC20 token) private view returns (uint256) {
        return _vestedAmount(token).sub(_released[address(token)]);
    }

    /**
     * @dev Calculates the amount that has already vested.
     * @param token ERC20 token which is being vested
     */
    function _vestedAmount(IERC20 token) private view returns (uint256) {
        uint256 currentBalance = token.balanceOf(address(this));
        uint256 totalBalance = currentBalance.add(_released[address(token)]);

        if (block.timestamp < _cliff) {
            return 0;
        } else if (block.timestamp >= _start.add(_duration) || _revoked[address(token)]) {
            return totalBalance;
        } else {
            return totalBalance.mul(block.timestamp.sub(_start)).div(_duration);
        }
    }
}

File 107 of 117: Umip3Upgrader.sol
pragma solidity ^0.6.0;

import "./Finder.sol";
import "./Constants.sol";
import "./Voting.sol";


/**
 * @title A contract to track a whitelist of addresses.
 */
contract Umip3Upgrader {
    // Existing governor is the only one who can initiate the upgrade.
    address public existingGovernor;

    // Existing Voting contract needs to be informed of the address of the new Voting contract.
    Voting public existingVoting;

    // New governor will be the new owner of the finder.
    address public newGovernor;

    // Finder contract to push upgrades to.
    Finder public finder;

    // Addresses to upgrade.
    address public voting;
    address public identifierWhitelist;
    address public store;
    address public financialContractsAdmin;
    address public registry;

    constructor(
        address _existingGovernor,
        address _existingVoting,
        address _finder,
        address _voting,
        address _identifierWhitelist,
        address _store,
        address _financialContractsAdmin,
        address _registry,
        address _newGovernor
    ) public {
        existingGovernor = _existingGovernor;
        existingVoting = Voting(_existingVoting);
        finder = Finder(_finder);
        voting = _voting;
        identifierWhitelist = _identifierWhitelist;
        store = _store;
        financialContractsAdmin = _financialContractsAdmin;
        registry = _registry;
        newGovernor = _newGovernor;
    }

    function upgrade() external {
        require(msg.sender == existingGovernor, "Upgrade can only be initiated by the existing governor.");

        // Change the addresses in the Finder.
        finder.changeImplementationAddress(OracleInterfaces.Oracle, voting);
        finder.changeImplementationAddress(OracleInterfaces.IdentifierWhitelist, identifierWhitelist);
        finder.changeImplementationAddress(OracleInterfaces.Store, store);
        finder.changeImplementationAddress(OracleInterfaces.FinancialContractsAdmin, financialContractsAdmin);
        finder.changeImplementationAddress(OracleInterfaces.Registry, registry);

        // Transfer the ownership of the Finder to the new Governor now that all the addresses have been updated.
        finder.transferOwnership(newGovernor);

        // Inform the existing Voting contract of the address of the new Voting contract and transfer its
        // ownership to the new governor to allow for any future changes to the migrated contract.
        existingVoting.setMigrated(voting);
        existingVoting.transferOwnership(newGovernor);
    }
}

File 108 of 117: Uniswap.sol
pragma solidity ^0.6.0;


/**
 * @title Interface for Uniswap v2.
 * @dev This only contains the methods/events that we use in our contracts or offchain infrastructure.
 */
abstract contract Uniswap {
    // Called after every swap showing the new uniswap "price" for this token pair.
    event Sync(uint112 reserve0, uint112 reserve1);
}

File 109 of 117: UniswapMock.sol
pragma solidity ^0.6.0;

import "./Uniswap.sol";


/**
 * @title Uniswap v2 Mock that allows manual price injection.
 */
contract UniswapMock is Uniswap {
    function setPrice(uint112 reserve0, uint112 reserve1) external {
        emit Sync(reserve0, reserve1);
    }
}

File 110 of 117: VoteTiming.sol
pragma solidity ^0.6.0;

import "./SafeMath.sol";
import "./VotingInterface.sol";


/**
 * @title Library to compute rounds and phases for an equal length commit-reveal voting cycle.
 */
library VoteTiming {
    using SafeMath for uint256;

    struct Data {
        uint256 phaseLength;
    }

    /**
     * @notice Initializes the data object. Sets the phase length based on the input.
     */
    function init(Data storage data, uint256 phaseLength) internal {
        // This should have a require message but this results in an internal Solidity error.
        require(phaseLength > 0);
        data.phaseLength = phaseLength;
    }

    /**
     * @notice Computes the roundID based off the current time as floor(timestamp/phaseLength).
     * @dev The round ID depends on the global timestamp but not on the lifetime of the system.
     * The consequence is that the initial round ID starts at an arbitrary number (that increments, as expected, for subsequent rounds) instead of zero or one.
     * @param data input data object.
     * @param currentTime input unix timestamp used to compute the current roundId.
     * @return roundId defined as a function of the currentTime and `phaseLength` from `data`.
     */
    function computeCurrentRoundId(Data storage data, uint256 currentTime) internal view returns (uint256) {
        uint256 roundLength = data.phaseLength.mul(uint256(VotingInterface.Phase.NUM_PHASES_PLACEHOLDER));
        return currentTime.div(roundLength);
    }

    /**
     * @notice compute the round end time as a function of the round Id.
     * @param data input data object.
     * @param roundId uniquely identifies the current round.
     * @return timestamp unix time of when the current round will end.
     */
    function computeRoundEndTime(Data storage data, uint256 roundId) internal view returns (uint256) {
        uint256 roundLength = data.phaseLength.mul(uint256(VotingInterface.Phase.NUM_PHASES_PLACEHOLDER));
        return roundLength.mul(roundId.add(1));
    }

    /**
     * @notice Computes the current phase based only on the current time.
     * @param data input data object.
     * @param currentTime input unix timestamp used to compute the current roundId.
     * @return current voting phase based on current time and vote phases configuration.
     */
    function computeCurrentPhase(Data storage data, uint256 currentTime) internal view returns (VotingInterface.Phase) {
        // This employs some hacky casting. We could make this an if-statement if we're worried about type safety.
        return
            VotingInterface.Phase(
                currentTime.div(data.phaseLength).mod(uint256(VotingInterface.Phase.NUM_PHASES_PLACEHOLDER))
            );
    }
}

File 111 of 117: VoteTimingTest.sol
pragma solidity ^0.6.0;

import "./VotingInterface.sol";
import "./VoteTiming.sol";


// Wraps the library VoteTiming for testing purposes.
contract VoteTimingTest {
    using VoteTiming for VoteTiming.Data;

    VoteTiming.Data public voteTiming;

    constructor(uint256 phaseLength) public {
        wrapInit(phaseLength);
    }

    function wrapComputeCurrentRoundId(uint256 currentTime) external view returns (uint256) {
        return voteTiming.computeCurrentRoundId(currentTime);
    }

    function wrapComputeCurrentPhase(uint256 currentTime) external view returns (VotingInterface.Phase) {
        return voteTiming.computeCurrentPhase(currentTime);
    }

    function wrapInit(uint256 phaseLength) public {
        voteTiming.init(phaseLength);
    }
}

File 112 of 117: VotingInterface.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./FixedPoint.sol";


/**
 * @title Interface that voters must use to Vote on price request resolutions.
 */
abstract contract VotingInterface {
    struct PendingRequest {
        bytes32 identifier;
        uint256 time;
    }

    // Captures the necessary data for making a commitment.
    // Used as a parameter when making batch commitments.
    // Not used as a data structure for storage.
    struct Commitment {
        bytes32 identifier;
        uint256 time;
        bytes32 hash;
        bytes encryptedVote;
    }

    // Captures the necessary data for revealing a vote.
    // Used as a parameter when making batch reveals.
    // Not used as a data structure for storage.
    struct Reveal {
        bytes32 identifier;
        uint256 time;
        int256 price;
        int256 salt;
    }

    // Note: the phases must be in order. Meaning the first enum value must be the first phase, etc.
    // `NUM_PHASES_PLACEHOLDER` is to get the number of phases. It isn't an actual phase, and it should always be last.
    enum Phase { Commit, Reveal, NUM_PHASES_PLACEHOLDER }

    /**
     * @notice Commit a vote for a price request for `identifier` at `time`.
     * @dev `identifier`, `time` must correspond to a price request that's currently in the commit phase.
     * Commits can be changed.
     * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s expected behavior,
     * voters should never reuse salts. If someone else is able to guess the voted price and knows that a salt will be reused, then
     * they can determine the vote pre-reveal.
     * @param identifier uniquely identifies the committed vote. EG BTC/USD price pair.
     * @param time unix timestamp of the price being voted on.
     * @param hash keccak256 hash of the `price`, `salt`, voter `address`, `time`, current `roundId`, and `identifier`.
     */
    function commitVote(
        bytes32 identifier,
        uint256 time,
        bytes32 hash
    ) external virtual;

    /**
     * @notice Submit a batch of commits in a single transaction.
     * @dev Using `encryptedVote` is optional. If included then commitment is stored on chain.
     * Look at `project-root/common/Constants.js` for the tested maximum number of
     * commitments that can fit in one transaction.
     * @param commits array of structs that encapsulate an `identifier`, `time`, `hash` and optional `encryptedVote`.
     */
    function batchCommit(Commitment[] calldata commits) external virtual;

    /**
     * @notice snapshot the current round's token ballances and lock in the inflation rate and GAT.
     * @dev This function can be called multiple times but each round will only every have one snapshot at the
     * time of calling `_freezeRoundVariables`.
     */
    function snapshotCurrentRound() external virtual;

    /**
     * @notice Reveal a previously committed vote for `identifier` at `time`.
     * @dev The revealed `price`, `salt`, `time`, `address`, `roundId`, and `identifier`, must hash to the latest `hash`
     * that `commitVote()` was called with. Only the committer can reveal their vote.
     * @param identifier voted on in the commit phase. EG BTC/USD price pair.
     * @param time specifies the unix timestamp of the price is being voted on.
     * @param price voted on during the commit phase.
     * @param salt value used to hide the commitment price during the commit phase.
     */
    function revealVote(
        bytes32 identifier,
        uint256 time,
        int256 price,
        int256 salt
    ) external virtual;

    /**
     * @notice Reveal multiple votes in a single transaction.
     * Look at `project-root/common/Constants.js` for the tested maximum number of reveals.
     * that can fit in one transaction.
     * @dev For more information on reveals, review the comment for `revealVote`.
     * @param reveals array of the Reveal struct which contains an identifier, time, price and salt.
     */
    function batchReveal(Reveal[] calldata reveals) external virtual;

    /**
     * @notice Gets the queries that are being voted on this round.
     * @return pendingRequests `PendingRequest` array containing identifiers
     * and timestamps for all pending requests.
     */
    function getPendingRequests() external virtual view returns (PendingRequest[] memory);

    /**
     * @notice Returns the current voting phase, as a function of the current time.
     * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES_PLACEHOLDER }.
     */
    function getVotePhase() external virtual view returns (Phase);

    /**
     * @notice Returns the current round ID, as a function of the current time.
     * @return uint256 representing the unique round ID.
     */
    function getCurrentRoundId() external virtual view returns (uint256);

    /**
     * @notice Retrieves rewards owed for a set of resolved price requests.
     * @dev Can only retrieve rewards if calling for a valid round and if the
     * call is done within the timeout threshold (not expired).
     * @param voterAddress voter for which rewards will be retrieved. Does not have to be the caller.
     * @param roundId the round from which voting rewards will be retrieved from.
     * @param toRetrieve array of PendingRequests which rewards are retrieved from.
     * @return total amount of rewards returned to the voter.
     */
    function retrieveRewards(
        address voterAddress,
        uint256 roundId,
        PendingRequest[] memory toRetrieve
    ) public virtual returns (FixedPoint.Unsigned memory);
}

File 113 of 117: VotingTest.sol
pragma solidity ^0.6.0;

pragma experimental ABIEncoderV2;

import "./Voting.sol";
import "./FixedPoint.sol";


// Test contract used to access internal variables in the Voting contract.
contract VotingTest is Voting {
    constructor(
        uint256 _phaseLength,
        FixedPoint.Unsigned memory _gatPercentage,
        FixedPoint.Unsigned memory _inflationRate,
        uint256 _rewardsExpirationTimeout,
        address _votingToken,
        address _finder,
        address _timerAddress
    )
        public
        Voting(
            _phaseLength,
            _gatPercentage,
            _inflationRate,
            _rewardsExpirationTimeout,
            _votingToken,
            _finder,
            _timerAddress
        )
    {}

    function getPendingPriceRequestsArray() external view returns (bytes32[] memory) {
        return pendingPriceRequests;
    }
}

File 114 of 117: VotingToken.sol
pragma solidity ^0.6.0;

import "./ExpandedERC20.sol";
import "./ERC20Snapshot.sol";


/**
 * @title Ownership of this token allows a voter to respond to price requests.
 * @dev Supports snapshotting and allows the Oracle to mint new tokens as rewards.
 */
contract VotingToken is ExpandedERC20, ERC20Snapshot {
    /**
     * @notice Constructs the VotingToken.
     */
    constructor() public ExpandedERC20("UMA Voting Token v1", "UMA", 18) {}

    /**
     * @notice Creates a new snapshot ID.
     * @return uint256 Thew new snapshot ID.
     */
    function snapshot() external returns (uint256) {
        return _snapshot();
    }

    // _transfer, _mint and _burn are ERC20 internal methods that are overridden by ERC20Snapshot,
    // therefore the compiler will complain that VotingToken must override these methods
    // because the two base classes (ERC20 and ERC20Snapshot) both define the same functions

    function _transfer(
        address from,
        address to,
        uint256 value
    ) internal override(ERC20, ERC20Snapshot) {
        super._transfer(from, to, value);
    }

    function _mint(address account, uint256 value) internal override(ERC20, ERC20Snapshot) {
        super._mint(account, value);
    }

    function _burn(address account, uint256 value) internal override(ERC20, ERC20Snapshot) {
        super._burn(account, value);
    }
}

File 115 of 117: WETH9.sol
/**
 *Submitted for verification at Etherscan.io on 2017-12-12
 */

// Copyright (C) 2015, 2016, 2017 Dapphub

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.6.0;


// Copied from the verified code from Etherscan:
// https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
// And then updated for Solidity version 0.6. Specific changes:
// * Change `function() public` into `receive() external` and `fallback() external`
// * Change `this.balance` to `address(this).balance`
// * Ran prettier
contract WETH9 {
    string public name = "Wrapped Ether";
    string public symbol = "WETH";
    uint8 public decimals = 18;

    event Approval(address indexed src, address indexed guy, uint256 wad);
    event Transfer(address indexed src, address indexed dst, uint256 wad);
    event Deposit(address indexed dst, uint256 wad);
    event Withdrawal(address indexed src, uint256 wad);

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    receive() external payable {
        deposit();
    }

    fallback() external payable {
        deposit();
    }

    function deposit() public payable {
        balanceOf[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(uint256 wad) public {
        require(balanceOf[msg.sender] >= wad);
        balanceOf[msg.sender] -= wad;
        msg.sender.transfer(wad);
        emit Withdrawal(msg.sender, wad);
    }

    function totalSupply() public view returns (uint256) {
        return address(this).balance;
    }

    function approve(address guy, uint256 wad) public returns (bool) {
        allowance[msg.sender][guy] = wad;
        emit Approval(msg.sender, guy, wad);
        return true;
    }

    function transfer(address dst, uint256 wad) public returns (bool) {
        return transferFrom(msg.sender, dst, wad);
    }

    function transferFrom(
        address src,
        address dst,
        uint256 wad
    ) public returns (bool) {
        require(balanceOf[src] >= wad);

        if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }

        balanceOf[src] -= wad;
        balanceOf[dst] += wad;

        emit Transfer(src, dst, wad);

        return true;
    }
}

/*
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

*/

File 116 of 117: Withdrawable.sol
/**
 * Withdrawable contract.
 */

pragma solidity ^0.6.0;

import "./Address.sol";
import "./IERC20.sol";
import "./SafeERC20.sol";

import "./MultiRole.sol";


/**
 * @title Base contract that allows a specific role to withdraw any ETH and/or ERC20 tokens that the contract holds.
 */
abstract contract Withdrawable is MultiRole {
    using SafeERC20 for IERC20;

    uint256 private roleId;

    /**
     * @notice Withdraws ETH from the contract.
     */
    function withdraw(uint256 amount) external onlyRoleHolder(roleId) {
        Address.sendValue(msg.sender, amount);
    }

    /**
     * @notice Withdraws ERC20 tokens from the contract.
     * @param erc20Address ERC20 token to withdraw.
     * @param amount amount of tokens to withdraw.
     */
    function withdrawErc20(address erc20Address, uint256 amount) external onlyRoleHolder(roleId) {
        IERC20 erc20 = IERC20(erc20Address);
        erc20.safeTransfer(msg.sender, amount);
    }

    /**
     * @notice Internal method that allows derived contracts to create a role for withdrawal.
     * @dev Either this method or `_setWithdrawRole` must be called by the derived class for this contract to function
     * properly.
     * @param newRoleId ID corresponding to role whose members can withdraw.
     * @param managingRoleId ID corresponding to managing role who can modify the withdrawable role's membership.
     * @param withdrawerAddress new manager of withdrawable role.
     */
    function _createWithdrawRole(
        uint256 newRoleId,
        uint256 managingRoleId,
        address withdrawerAddress
    ) internal {
        roleId = newRoleId;
        _createExclusiveRole(newRoleId, managingRoleId, withdrawerAddress);
    }

    /**
     * @notice Internal method that allows derived contracts to choose the role for withdrawal.
     * @dev The role `setRoleId` must exist. Either this method or `_createWithdrawRole` must be
     * called by the derived class for this contract to function properly.
     * @param setRoleId ID corresponding to role whose members can withdraw.
     */
    function _setWithdrawRole(uint256 setRoleId) internal onlyValidRole(setRoleId) {
        roleId = setRoleId;
    }
}

File 117 of 117: WithdrawableTest.sol
pragma solidity ^0.6.0;

import "./Withdrawable.sol";


// WithdrawableTest is derived from the abstract contract Withdrawable for testing purposes.
contract WithdrawableTest is Withdrawable {
    enum Roles { Governance, Withdraw }

    // solhint-disable-next-line no-empty-blocks
    constructor() public {
        _createExclusiveRole(uint256(Roles.Governance), uint256(Roles.Governance), msg.sender);
        _createWithdrawRole(uint256(Roles.Withdraw), uint256(Roles.Governance), msg.sender);
    }

    function pay() external payable {
        require(msg.value > 0);
    }

    function setInternalWithdrawRole(uint256 roleId) public {
        _setWithdrawRole(roleId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_phaseLength","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"_gatPercentage","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"_inflationRate","type":"tuple"},{"internalType":"uint256","name":"_rewardsExpirationTimeout","type":"uint256"},{"internalType":"address","name":"_votingToken","type":"address"},{"internalType":"address","name":"_finder","type":"address"},{"internalType":"address","name":"_timerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"encryptedVote","type":"bytes"}],"name":"EncryptedVote","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":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"PriceRequestAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"int256","name":"price","type":"int256"}],"name":"PriceResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"RewardsRetrieved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"VoteCommitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"uint256","name":"roundId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"int256","name":"price","type":"int256"},{"indexed":false,"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"VoteRevealed","type":"event"},{"inputs":[{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"encryptedVote","type":"bytes"}],"internalType":"struct VotingInterface.Commitment[]","name":"commits","type":"tuple[]"}],"name":"batchCommit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"int256","name":"price","type":"int256"},{"internalType":"int256","name":"salt","type":"int256"}],"internalType":"struct VotingInterface.Reveal[]","name":"reveals","type":"tuple[]"}],"name":"batchReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"encryptedVote","type":"bytes"}],"name":"commitAndEmitEncryptedVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"commitVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gatPercentage","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentRoundId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingRequests","outputs":[{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"internalType":"struct VotingInterface.PendingRequest[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"internalType":"struct VotingInterface.PendingRequest[]","name":"requests","type":"tuple[]"}],"name":"getPriceRequestStatuses","outputs":[{"components":[{"internalType":"enum Voting.RequestStatus","name":"status","type":"uint8"},{"internalType":"uint256","name":"lastVotingRound","type":"uint256"}],"internalType":"struct Voting.RequestState[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVotePhase","outputs":[{"internalType":"enum VotingInterface.Phase","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"hasPrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inflationRate","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migratedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"name":"requestPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voterAddress","type":"address"},{"internalType":"uint256","name":"roundId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"}],"internalType":"struct VotingInterface.PendingRequest[]","name":"toRetrieve","type":"tuple[]"}],"name":"retrieveRewards","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"totalRewardToIssue","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"int256","name":"price","type":"int256"},{"internalType":"int256","name":"salt","type":"int256"}],"name":"revealVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsExpirationTimeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rounds","outputs":[{"internalType":"uint256","name":"snapshotId","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"inflationRate","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"gatPercentage","type":"tuple"},{"internalType":"uint256","name":"rewardsExpirationTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"newGatPercentage","type":"tuple"}],"name":"setGatPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"newInflationRate","type":"tuple"}],"name":"setInflationRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVotingAddress","type":"address"}],"name":"setMigrated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"NewRewardsExpirationTimeout","type":"uint256"}],"name":"setRewardsExpirationTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshotCurrentRound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voteTiming","outputs":[{"internalType":"uint256","name":"phaseLength","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingToken","outputs":[{"internalType":"contract VotingToken","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b50604051620039133803806200391383398101604081905262000034916200025a565b600080546001600160a01b0319166001600160a01b0383161781556200005962000149565b600180546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000c28760056200014d60201b6200352b1790919060201c565b620000dd6001876200015f60201b6200353c1790919060201c565b620001055760405162461bcd60e51b8152600401620000fc90620002e8565b60405180910390fd5b5093516006559151600755600980546001600160a01b039384166001600160a01b031991821617909155600a80549490931693169290921790556008555062000379565b3390565b600081116200015b57600080fd5b9055565b600062000175826001600160e01b036200018316565b518351111590505b92915050565b6200018d62000209565b6040518060200160405280620001ba670de0b6b3a764000085620001c260201b620026391790919060201c565b905292915050565b600082620001d3575060006200017d565b82820282848281620001e157fe5b0414620002025760405162461bcd60e51b8152600401620000fc906200031f565b9392505050565b6040518060200160405280600081525090565b6000602082840312156200022e578081fd5b604051602081016001600160401b03811182821017156200024d578283fd5b6040529151825250919050565b600080600080600080600060e0888a03121562000275578283fd5b87519650620002888960208a016200021c565b9550620002998960408a016200021c565b9450606088015193506080880151620002b28162000360565b60a0890151909350620002c58162000360565b60c0890151909250620002d88162000360565b8091505092959891949750929550565b6020808252601e908201527f4741542070657263656e74616765206d757374206265203c3d20313030250000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6001600160a01b03811681146200037657600080fd5b50565b61358a80620003896000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c8063715018a61161010f5780638da5cb5b116100a2578063b90fd48011610071578063b90fd480146103d2578063c9280f06146103da578063d8651ad0146103ed578063f2fde38b14610400576101e5565b80638da5cb5b1461039a578063a03e881a146103a2578063a1f4c666146103c2578063b0340123146103ca576101e5565b806383c6aaca116100de57806383c6aaca146103315780638558d4f3146103445780638876e8a0146103645780638c65c81f14610377576101e5565b8063715018a6146102f757806371b7db53146102ff57806374dd278c1461030757806380a1f7121461031c576101e5565b806331f9e35b116101875780635727e25d116101565780635727e25d146102b65780636852eea0146102be57806368ad8ae3146102d157806370a0cf2c146102e4576101e5565b806331f9e35b146102805780634000851f146102885780634666cb0c146102905780634c7a2603146102a3576101e5565b806322f8e566116101c357806322f8e5661461023d57806326af73bf146102505780632960b5af1461026557806329cb924d14610278576101e5565b80630d434e7e146101ea57806313e56d6a146102135780631c39c38d14610228575b600080fd5b6101fd6101f8366004612acb565b610413565b60405161020a919061341f565b60405180910390f35b610226610221366004612d65565b6109a7565b005b610230610a0f565b60405161020a9190612e3f565b61022661024b366004612d8a565b610a1e565b610258610a98565b60405161020a9190612f12565b610226610273366004612a93565b610a9e565b610258610af5565b610258610b99565b610230610b9f565b61022661029e366004612c8b565b610bae565b6102266102b1366004612d34565b610c22565b610258610e95565b6102266102cc366004612bc1565b610ea7565b6102266102df366004612c3f565b610f1f565b6102266102f2366004612b22565b611282565b610226611405565b610258611484565b61030f61148a565b60405161020a9190612f29565b6103246114a5565b60405161020a9190612e6c565b61022661033f366004612d65565b611669565b610357610352366004612b8e565b6116a4565b60405161020a9190612ebb565b610226610372366004612d8a565b6117f1565b61038a610385366004612d8a565b61182b565b60405161020a9493929190613458565b610230611865565b6103b56103b0366004612c3f565b611874565b60405161020a9190612f07565b6102266119f9565b610230611a8b565b610258611a9a565b6102586103e8366004612c3f565b611aa0565b6102266103fb366004612c60565b611c41565b61022661040e366004612a93565b611d91565b61041b6129b0565b600b546001600160a01b03161561045f57600b546001600160a01b0316331461045f5760405162461bcd60e51b81526004016104569061303b565b60405180910390fd5b6000610469610af5565b905061047c60058263ffffffff611e4816565b841061049a5760405162461bcd60e51b815260040161045690613072565b6000848152600260205260409020600381015482116104b76129b0565b604080516020810191829052600954855463277166bf60e11b909352909182916001600160a01b031690634ee2cd7e906104f6908d9060248601612e53565b60206040518083038186803b15801561050e57600080fd5b505afa158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190612da2565b905290506105526129b0565b6040805160208101918290526009548654630981b24d60e41b909352909182916001600160a01b03169063981b24d09061058f9060248501612f12565b60206040518083038186803b1580156105a757600080fd5b505afa1580156105bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105df9190612da2565b905290506105eb6129b0565b60408051602081019091526001860154815261060d908363ffffffff611e7916565b604080516020810190915260008082529098509091505b88518110156108e25760006106678a838151811061063e57fe5b6020026020010151600001518b848151811061065657fe5b602002602001015160200151611ebc565b6003810154600081815260028301602052604090209192508c1461069d5760405162461bcd60e51b81526004016104569061337a565b6106a78282611ee2565b6001600160a01b038d166000908152602082905260409020600101546106ce5750506108da565b861561074d578a83815181106106e057fe5b6020026020010151600001518c8e6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8e878151811061072457fe5b6020026020010151602001516000604051610740929190612f1b565b60405180910390a46108bb565b6001600160a01b038d16600090815260208290526040902060019081015461077d9183019063ffffffff61202916565b156108465761078a6129b0565b6107b561079983600101612060565b6107a9898863ffffffff611e7916565b9063ffffffff61208c16565b90506107c78b8263ffffffff6120d616565b9a508b84815181106107d557fe5b6020026020010151600001518d8f6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8f888151811061081957fe5b6020026020010151602001518560000151604051610838929190612f1b565b60405180910390a4506108bb565b8a838151811061085257fe5b6020026020010151600001518c8e6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8e878151811061089657fe5b60200260200101516020015160006040516108b2929190612f1b565b60405180910390a45b6001600160a01b038d1660009081526020919091526040812060010155505b600101610624565b506108f487600063ffffffff6120ff16565b1561099a5760095487516040516340c10f1960e01b81526001600160a01b03909216916340c10f199161092c918e9190600401612e53565b602060405180830381600087803b15801561094657600080fd5b505af115801561095a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097e9190612c1f565b61099a5760405162461bcd60e51b81526004016104569061318d565b5050505050509392505050565b6109af612116565b6001546001600160a01b039081169116146109dc5760405162461bcd60e51b815260040161045690613121565b6109ed81600163ffffffff61211a16565b610a095760405162461bcd60e51b815260040161045690613269565b51600655565b6000546001600160a01b031681565b6000546001600160a01b0316610a3357600080fd5b60005460405163117c72b360e11b81526001600160a01b03909116906322f8e56690610a63908490600401612f12565b600060405180830381600087803b158015610a7d57600080fd5b505af1158015610a91573d6000803e3d6000fd5b5050505050565b60085481565b610aa6612116565b6001546001600160a01b03908116911614610ad35760405162461bcd60e51b815260040161045690613121565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b031615610b93576000809054906101000a90046001600160a01b03166001600160a01b03166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5457600080fd5b505afa158015610b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8c9190612da2565b9050610b96565b50425b90565b60075481565b600b546001600160a01b031681565b610bb9848484611c41565b6000610bd4610bc6610af5565b60059063ffffffff611e4816565b90508481336001600160a01b03167f6992efdd7b69c1a8d79212d5ef5fe92118ed053fb7195808a858fa6889a117e98786604051610c13929190613429565b60405180910390a45050505050565b600b546001600160a01b031615610c4b5760405162461bcd60e51b815260040161045690613343565b6000610c55610af5565b90506001610c6a60058363ffffffff61213116565b6002811115610c7557fe5b14610c925760405162461bcd60e51b815260040161045690613004565b6000610ca560058363ffffffff611e4816565b90506000610cb38787611ebc565b600083815260028201602090815260408083203384529182905290912080549293509091610cf35760405162461bcd60e51b8152600401610456906131fb565b80600001548787338b888e604051602001610d1396959493929190612e05565b6040516020818303038152906040528051906020012014610d465760405162461bcd60e51b815260040161045690612f50565b60008155610d5384612169565b600084815260026020526040902054610d6a6129b0565b60408051602081019182905260095463277166bf60e11b9092529081906001600160a01b0316634ee2cd7e610da3338760248601612e53565b60206040518083038186803b158015610dbb57600080fd5b505afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190612da2565b815250905088604051602001610e099190612f12565b60408051601f198184030181529190528051602090910120600180850191909155610e3d9085018a8363ffffffff61226016565b8a86336001600160a01b03167fd04931ad32b4f942a0f169443ebd7f85a7d42c8b4310b4792243a065348836078d8d8660000151604051610e8093929190613442565b60405180910390a45050505050505050505050565b6000610ea2610bc6610af5565b905090565b60005b81811015610f1a57610f12838383818110610ec157fe5b90506080020160000135848484818110610ed757fe5b90506080020160200135858585818110610eed57fe5b90506080020160400135868686818110610f0357fe5b90506080020160600135610c22565b600101610eaa565b505050565b600b546001600160a01b031615610f5f57600b546001600160a01b03163314610f5a5760405162461bcd60e51b8152600401610456906133e8565b611088565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090610f9b9067526567697374727960c01b90600401612f12565b60206040518083038186803b158015610fb357600080fd5b505afa158015610fc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610feb9190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b9061101a903390600401612e3f565b60206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106a9190612c1f565b6110865760405162461bcd60e51b8152600401610456906132d5565b505b6000611092610af5565b9050808211156110b45760405162461bcd60e51b815260040161045690613232565b6110bc612327565b6001600160a01b03166390978d1b846040518263ffffffff1660e01b81526004016110e79190612f12565b60206040518083038186803b1580156110ff57600080fd5b505afa158015611113573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111379190612c1f565b6111535760405162461bcd60e51b8152600401610456906130a9565b600061115f84846123c8565b600081815260036020526040812091925061118160058563ffffffff611e4816565b9050600061118f83836123fb565b9050600081600381111561119f57fe5b14156112795760006111b883600163ffffffff61248816565b604080516080810182528a815260208082018b8152828401858152600480546060860190815260008d815260039586905287812096518755935160018088019190915592519486019490945592519383019390935581549283018255527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0187905551909150889082907f5d80f93c41e95cacea0b9ce9bb825092d709fa503a70bb26ea3f536bf16946bd9061126f908b90612f12565b60405180910390a3505b50505050505050565b60005b81811015610f1a5782828281811061129957fe5b90506020028101906112ab91906134c1565b6112b9906060810190613473565b151590506113315761132c8383838181106112d057fe5b90506020028101906112e291906134c1565b358484848181106112ef57fe5b905060200281019061130191906134c1565b6020013585858581811061131157fe5b905060200281019061132391906134c1565b60400135611c41565b6113fd565b6113fd83838381811061134057fe5b905060200281019061135291906134c1565b3584848481811061135f57fe5b905060200281019061137191906134c1565b6020013585858581811061138157fe5b905060200281019061139391906134c1565b604001358686868181106113a357fe5b90506020028101906113b591906134c1565b6113c3906060810190613473565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bae92505050565b600101611285565b61140d612116565b6001546001600160a01b0390811691161461143a5760405162461bcd60e51b815260040161045690613121565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60055481565b6000610ea2611497610af5565b60059063ffffffff61213116565b606060006114b1610af5565b905060006114c660058363ffffffff611e4816565b60045490915060609067ffffffffffffffff811180156114e557600080fd5b5060405190808252806020026020018201604052801561151f57816020015b61150c6129c3565b8152602001906001900390816115045790505b5090506000805b6004548110156115ca576000600360006004848154811061154357fe5b9060005260206000200154815260200190815260200160002090506001600381111561156b57fe5b61157582876123fb565b600381111561158057fe5b14156115c15760405180604001604052808260000154815260200182600101548152508484815181106115af57fe5b60209081029190910101526001909201915b50600101611526565b5060608167ffffffffffffffff811180156115e457600080fd5b5060405190808252806020026020018201604052801561161e57816020015b61160b6129c3565b8152602001906001900390816116035790505b50905060005b8281101561165f5783818151811061163857fe5b602002602001015182828151811061164c57fe5b6020908102919091010152600101611624565b5094505050505090565b611671612116565b6001546001600160a01b0390811691161461169e5760405162461bcd60e51b815260040161045690613121565b51600755565b606080825167ffffffffffffffff811180156116bf57600080fd5b506040519080825280602002602001820160405280156116f957816020015b6116e66129c3565b8152602001906001900390816116de5790505b5090506000611709610bc6610af5565b905060005b84518110156117e657600061174086838151811061172857fe5b60200260200101516000015187848151811061065657fe5b9050600061174e82856123fb565b9050600181600381111561175e57fe5b1415611786578385848151811061177157fe5b602002602001015160200181815250506117a8565b816003015485848151811061179757fe5b602002602001015160200181815250505b808584815181106117b557fe5b60200260200101516000019060038111156117cc57fe5b908160038111156117d957fe5b905250505060010161170e565b50909150505b919050565b6117f9612116565b6001546001600160a01b039081169116146118265760405162461bcd60e51b815260040161045690613121565b600855565b6002602081815260009283526040928390208054845180840186526001830154815285519384019095529281015482526003015491929184565b6001546001600160a01b031690565b600b546000906001600160a01b0316156118b757600b546001600160a01b031633146118b25760405162461bcd60e51b8152600401610456906133e8565b6119e0565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e40906118f39067526567697374727960c01b90600401612f12565b60206040518083038186803b15801561190b57600080fd5b505afa15801561191f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119439190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b90611972903390600401612e3f565b60206040518083038186803b15801561198a57600080fd5b505afa15801561199e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c29190612c1f565b6119de5760405162461bcd60e51b8152600401610456906132d5565b505b60006119ec84846124ad565b5090925050505b92915050565b600b546001600160a01b031615611a225760405162461bcd60e51b815260040161045690613343565b6000611a2c610af5565b90506001611a4160058363ffffffff61213116565b6002811115611a4c57fe5b14611a695760405162461bcd60e51b8152600401610456906133b1565b6000611a7c60058363ffffffff611e4816565b9050611a8781612169565b5050565b6009546001600160a01b031681565b60065481565b600b546000906001600160a01b031615611ae357600b546001600160a01b03163314611ade5760405162461bcd60e51b8152600401610456906133e8565b611c0c565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090611b1f9067526567697374727960c01b90600401612f12565b60206040518083038186803b158015611b3757600080fd5b505afa158015611b4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6f9190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b90611b9e903390600401612e3f565b60206040518083038186803b158015611bb657600080fd5b505afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190612c1f565b611c0a5760405162461bcd60e51b8152600401610456906132d5565b505b6000806060611c1b86866124ad565b9250925092508281906119ec5760405162461bcd60e51b81526004016104569190612f3d565b600b546001600160a01b031615611c6a5760405162461bcd60e51b815260040161045690613343565b80611c875760405162461bcd60e51b8152600401610456906131c4565b6000611c91610af5565b90506000611ca660058363ffffffff61213116565b6002811115611cb157fe5b14611cce5760405162461bcd60e51b81526004016104569061330c565b6000611ce160058363ffffffff611e4816565b90506000611cef8686611ebc565b90506001611cfd82846123fb565b6003811115611d0857fe5b14611d255760405162461bcd60e51b815260040161045690613156565b600381018290556000828152600282016020908152604080832033808552928190529281902087905551889185917f879c67d036f174a10ea491cf7281d05af9b906660b4f26727d866aec0cf9147c90611d80908b90612f12565b60405180910390a450505050505050565b611d99612116565b6001546001600160a01b03908116911614611dc65760405162461bcd60e51b815260040161045690613121565b6001600160a01b038116611dec5760405162461bcd60e51b815260040161045690612f87565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080611e5f60025b85549063ffffffff61263916565b9050611e71838263ffffffff61267316565b949350505050565b611e816129b0565b6040805160208101909152825184518291670de0b6b3a764000091611eab9163ffffffff61263916565b81611eb257fe5b0490529392505050565b600060036000611ecc85856123c8565b8152602001908152602001600020905092915050565b60048201546000191415611ef557611a87565b600080611f18611f0885600301546126b5565b600185019063ffffffff6127ad16565b9150915081611f395760405162461bcd60e51b8152600401610456906132a0565b60048054600019810191600091600391839185908110611f5557fe5b9060005260206000200154815260200190815260200160002090508560040154816004018190555060048281548110611f8a57fe5b90600052602060002001546004876004015481548110611fa657fe5b6000918252602090912001556004805480611fbd57fe5b60008281526020812082016000199081019190915590810190915560048701558554600387015460018801546040517f67565e6a3e804c4e180134cb2885e32142229de3ca125701318af11658ee498891612019918890612f1b565b60405180910390a3505050505050565b600082600201546040516020016120409190612f12565b604051602081830303815290604052805190602001208214905092915050565b6120686129b0565b50600281015460009081526020918252604090819020815192830190915254815290565b6120946129b0565b60408051602081019091528251845182916120cd916120c190670de0b6b3a764000063ffffffff61263916565b9063ffffffff61267316565b90529392505050565b6120de6129b0565b60408051602081019091528251845182916120cd919063ffffffff61248816565b600061210a82612871565b51835111905092915050565b3390565b600061212582612871565b51835110905092915050565b60006121576002845461214b90859063ffffffff61267316565b9063ffffffff6128a516565b600281111561216257fe5b9392505050565b60008181526002602052604090208054611a8757600960009054906101000a90046001600160a01b03166001600160a01b0316639711715a6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156121cd57600080fd5b505af11580156121e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122059190612da2565b81556000828152600260208190526040909120600754600182015560065491015560085461224a9061223e60058563ffffffff6128e716565b9063ffffffff61248816565b6000838152600260205260409020600301555050565b604080516020810190915260018401548152612282908263ffffffff6120d616565b516001840155600082815260208481526040918290208251918201909252905481526122b4908263ffffffff6120d616565b600083815260208590526040902090519055600283015482148015906123185750600283015460009081526020848152604080832081518084018352905481528584528683529281902081519283019091525481526123189163ffffffff61291716565b15610f1a575060029190910155565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090612378907f4964656e74696669657257686974656c6973740000000000000000000000000090600401612f12565b60206040518083038186803b15801561239057600080fd5b505afa1580156123a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea29190612aaf565b600082826040516020016123dd929190612f1b565b60405160208183030381529060405280519060200120905092915050565b6000826003015460001415612412575060006119f3565b818360030154101561246c576003830154600081815260028501602052604081209161245190612441906126b5565b600184019063ffffffff6127ad16565b50905080612460576001612463565b60025b925050506119f3565b8183600301541415612480575060016119f3565b5060036119f3565b6000828201838110156121625760405162461bcd60e51b815260040161045690612fcd565b600080606060006124be8686611ebc565b905060006124cd610bc6610af5565b905060006124db83836123fb565b905060018160038111156124eb57fe5b141561253757505060408051808201909152601e81527f43757272656e7420766f74696e6720726f756e64206e6f7420656e646564000060208201526000945084935091506126329050565b600281600381111561254557fe5b1415612592576003830154600081815260028501602052604081209161256e90612441906126b5565b60408051602081019091526000815260019a50909850965061263295505050505050565b60038160038111156125a057fe5b14156125ec57505060408051808201909152601d81527f5072696365206973207374696c6c20746f20626520766f746564206f6e00000060208201526000945084935091506126329050565b505060408051808201909152601981527f507269636520776173206e65766572207265717565737465640000000000000060208201526000945084935091506126329050565b9250925092565b600082612648575060006119f3565b8282028284828161265557fe5b04146121625760405162461bcd60e51b8152600401610456906130e0565b600061216283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061291e565b6126bd6129b0565b600082815260026020526040902054806126e8575050604080516020810190915260001981526117ec565b6126f06129b0565b604080516020810191829052600954630981b24d60e41b9092529081906001600160a01b031663981b24d06127288660248501612f12565b60206040518083038186803b15801561274057600080fd5b505afa158015612754573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127789190612da2565b905260008581526002602081815260409283902083519182019093529101548152909150611e7190829063ffffffff611e7916565b6000806127b86129b0565b6127d360646127c76032612871565b9063ffffffff61295516565b6040805160208101909152600187015481529091506127f8908563ffffffff61291716565b801561284f57506040805160208082018352600188015482526002880154600090815288825283902083519182019093529154825261284f918391612843919063ffffffff61208c16565b9063ffffffff61291716565b15612864576001925084600201549150612869565b600092505b509250929050565b6128796129b0565b60408051602081019091528061289d84670de0b6b3a764000063ffffffff61263916565b905292915050565b600061216283836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f000000000000000081525061297c565b6000806128f46002611e51565b9050611e7161290a84600163ffffffff61248816565b829063ffffffff61263916565b5190511190565b6000818361293f5760405162461bcd60e51b81526004016104569190612f3d565b50600083858161294b57fe5b0495945050505050565b61295d6129b0565b6040805160208101909152835181906120cd908563ffffffff61267316565b6000818361299d5760405162461bcd60e51b81526004016104569190612f3d565b508284816129a757fe5b06949350505050565b6040518060200160405280600081525090565b604080518082019091526000808252602082015290565b600082601f8301126129ea578081fd5b813567ffffffffffffffff811115612a00578182fd5b6020612a0f81828402016134e0565b8281529250808301848201604080850287018401881015612a2f57600080fd5b60005b85811015612a5657612a448984612a62565b84529284019291810191600101612a32565b50505050505092915050565b600060408284031215612a73578081fd5b612a7d60406134e0565b9050813581526020820135602082015292915050565b600060208284031215612aa4578081fd5b813561216281613513565b600060208284031215612ac0578081fd5b815161216281613513565b600080600060608486031215612adf578182fd5b8335612aea81613513565b925060208401359150604084013567ffffffffffffffff811115612b0c578182fd5b612b18868287016129da565b9150509250925092565b60008060208385031215612b34578182fd5b823567ffffffffffffffff80821115612b4b578384fd5b81850186601f820112612b5c578485fd5b8035925081831115612b6c578485fd5b8660208085028301011115612b7f578485fd5b60200196919550909350505050565b600060208284031215612b9f578081fd5b813567ffffffffffffffff811115612bb5578182fd5b611e71848285016129da565b60008060208385031215612bd3578182fd5b823567ffffffffffffffff80821115612bea578384fd5b81850186601f820112612bfb578485fd5b8035925081831115612c0b578485fd5b866020608085028301011115612b7f578485fd5b600060208284031215612c30578081fd5b81518015158114612162578182fd5b60008060408385031215612c51578182fd5b50508035926020909101359150565b600080600060608486031215612c74578283fd5b505081359360208301359350604090920135919050565b60008060008060808587031215612ca0578081fd5b843593506020850135925060408501359150606085013567ffffffffffffffff80821115612ccc578283fd5b81870188601f820112612cdd578384fd5b8035925081831115612ced578384fd5b612d00601f8401601f19166020016134e0565b9150828252886020848301011115612d16578384fd5b612d27836020840160208401613507565b5094979396509194505050565b60008060008060808587031215612d49578081fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215612d76578081fd5b612d8060206134e0565b9135825250919050565b600060208284031215612d9b578081fd5b5035919050565b600060208284031215612db3578081fd5b5051919050565b60008151808452815b81811015612ddf57602081850181015186830182015201612dc3565b81811115612df05782602083870101525b50601f01601f19169290920160200192915050565b958652602086019490945260609290921b6bffffffffffffffffffffffff1916604085015260548401526074830152609482015260b40190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000919060409081850190868401855b82811015612eae57815180518552860151868501529284019290850190600101612e89565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015612eae578151805160048110612eee57fe5b8552860151868501529284019290850190600101612ed8565b901515815260200190565b90815260200190565b918252602082015260400190565b6020810160038310612f3757fe5b91905290565b6000602082526121626020830184612dba565b6020808252601c908201527f52657665616c6564206461746120213d20636f6d6d6974206861736800000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f43616e6e6f742072657665616c20696e20636f6d6d6974207068617365000000604082015260600190565b6020808252601b908201527f43616e206f6e6c792063616c6c2066726f6d206d696772617465640000000000604082015260600190565b6020808252600f908201527f496e76616c696420726f756e6449640000000000000000000000000000000000604082015260600190565b6020808252601e908201527f556e737570706f72746564206964656e74696669657220726571756573740000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601e908201527f43616e6e6f7420636f6d6d697420696e61637469766520726571756573740000604082015260600190565b6020808252601c908201527f566f74696e6720746f6b656e2069737375616e6365206661696c656400000000604082015260600190565b60208082526015908201527f496e76616c69642070726f766964656420686173680000000000000000000000604082015260600190565b60208082526013908201527f496e76616c696420686173682072657665616c00000000000000000000000000604082015260600190565b60208082526018908201527f43616e206f6e6c79207265717565737420696e20706173740000000000000000604082015260600190565b6020808252601d908201527f4741542070657263656e74616765206d757374206265203c2031303025000000604082015260600190565b6020808252818101527f43616e2774207265736f6c766520756e7265736f6c7665642072657175657374604082015260600190565b60208082526019908201527f43616c6c6564206d757374206265207265676973746572656400000000000000604082015260600190565b6020808252601d908201527f43616e6e6f7420636f6d6d697420696e2072657665616c207068617365000000604082015260600190565b6020808252601e908201527f4f6e6c792063616c6c2074686973206966206e6f74206d696772617465640000604082015260600190565b6020808252601d908201527f526574726965766520666f7220766f7465732073616d6520726f756e64000000604082015260600190565b6020808252601d908201527f4f6e6c7920736e617073686f7420696e2072657665616c207068617365000000604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206d69677261746564206164647265737300604082015260600190565b9051815260200190565b600083825260406020830152611e716040830184612dba565b9283526020830191909152604082015260600190565b93845291516020840152516040830152606082015260800190565b6000808335601e19843603018112613489578283fd5b8084018035925067ffffffffffffffff8311156134a4578384fd5b602001925050368190038213156134ba57600080fd5b9250929050565b60008235607e198336030181126134d6578182fd5b9190910192915050565b60405181810167ffffffffffffffff811182821017156134ff57600080fd5b604052919050565b82818337506000910152565b6001600160a01b038116811461352857600080fd5b50565b6000811161353857600080fd5b9055565b600061354782612871565b518351111590509291505056fea2646970667358221220894082513f5f7034400c32948565d69048f772378ce7f5199fff61a8ce4950cf64736f6c63430006060033000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000000000000012750000000000000000000000000004fa0d235c4abf4bcf4787af4cf447de572ef82800000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c30000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c8063715018a61161010f5780638da5cb5b116100a2578063b90fd48011610071578063b90fd480146103d2578063c9280f06146103da578063d8651ad0146103ed578063f2fde38b14610400576101e5565b80638da5cb5b1461039a578063a03e881a146103a2578063a1f4c666146103c2578063b0340123146103ca576101e5565b806383c6aaca116100de57806383c6aaca146103315780638558d4f3146103445780638876e8a0146103645780638c65c81f14610377576101e5565b8063715018a6146102f757806371b7db53146102ff57806374dd278c1461030757806380a1f7121461031c576101e5565b806331f9e35b116101875780635727e25d116101565780635727e25d146102b65780636852eea0146102be57806368ad8ae3146102d157806370a0cf2c146102e4576101e5565b806331f9e35b146102805780634000851f146102885780634666cb0c146102905780634c7a2603146102a3576101e5565b806322f8e566116101c357806322f8e5661461023d57806326af73bf146102505780632960b5af1461026557806329cb924d14610278576101e5565b80630d434e7e146101ea57806313e56d6a146102135780631c39c38d14610228575b600080fd5b6101fd6101f8366004612acb565b610413565b60405161020a919061341f565b60405180910390f35b610226610221366004612d65565b6109a7565b005b610230610a0f565b60405161020a9190612e3f565b61022661024b366004612d8a565b610a1e565b610258610a98565b60405161020a9190612f12565b610226610273366004612a93565b610a9e565b610258610af5565b610258610b99565b610230610b9f565b61022661029e366004612c8b565b610bae565b6102266102b1366004612d34565b610c22565b610258610e95565b6102266102cc366004612bc1565b610ea7565b6102266102df366004612c3f565b610f1f565b6102266102f2366004612b22565b611282565b610226611405565b610258611484565b61030f61148a565b60405161020a9190612f29565b6103246114a5565b60405161020a9190612e6c565b61022661033f366004612d65565b611669565b610357610352366004612b8e565b6116a4565b60405161020a9190612ebb565b610226610372366004612d8a565b6117f1565b61038a610385366004612d8a565b61182b565b60405161020a9493929190613458565b610230611865565b6103b56103b0366004612c3f565b611874565b60405161020a9190612f07565b6102266119f9565b610230611a8b565b610258611a9a565b6102586103e8366004612c3f565b611aa0565b6102266103fb366004612c60565b611c41565b61022661040e366004612a93565b611d91565b61041b6129b0565b600b546001600160a01b03161561045f57600b546001600160a01b0316331461045f5760405162461bcd60e51b81526004016104569061303b565b60405180910390fd5b6000610469610af5565b905061047c60058263ffffffff611e4816565b841061049a5760405162461bcd60e51b815260040161045690613072565b6000848152600260205260409020600381015482116104b76129b0565b604080516020810191829052600954855463277166bf60e11b909352909182916001600160a01b031690634ee2cd7e906104f6908d9060248601612e53565b60206040518083038186803b15801561050e57600080fd5b505afa158015610522573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105469190612da2565b905290506105526129b0565b6040805160208101918290526009548654630981b24d60e41b909352909182916001600160a01b03169063981b24d09061058f9060248501612f12565b60206040518083038186803b1580156105a757600080fd5b505afa1580156105bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105df9190612da2565b905290506105eb6129b0565b60408051602081019091526001860154815261060d908363ffffffff611e7916565b604080516020810190915260008082529098509091505b88518110156108e25760006106678a838151811061063e57fe5b6020026020010151600001518b848151811061065657fe5b602002602001015160200151611ebc565b6003810154600081815260028301602052604090209192508c1461069d5760405162461bcd60e51b81526004016104569061337a565b6106a78282611ee2565b6001600160a01b038d166000908152602082905260409020600101546106ce5750506108da565b861561074d578a83815181106106e057fe5b6020026020010151600001518c8e6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8e878151811061072457fe5b6020026020010151602001516000604051610740929190612f1b565b60405180910390a46108bb565b6001600160a01b038d16600090815260208290526040902060019081015461077d9183019063ffffffff61202916565b156108465761078a6129b0565b6107b561079983600101612060565b6107a9898863ffffffff611e7916565b9063ffffffff61208c16565b90506107c78b8263ffffffff6120d616565b9a508b84815181106107d557fe5b6020026020010151600001518d8f6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8f888151811061081957fe5b6020026020010151602001518560000151604051610838929190612f1b565b60405180910390a4506108bb565b8a838151811061085257fe5b6020026020010151600001518c8e6001600160a01b03167ff8da7bdb1837995e872689b605d1a2b076db111cb4b15351f835ebd275be423f8e878151811061089657fe5b60200260200101516020015160006040516108b2929190612f1b565b60405180910390a45b6001600160a01b038d1660009081526020919091526040812060010155505b600101610624565b506108f487600063ffffffff6120ff16565b1561099a5760095487516040516340c10f1960e01b81526001600160a01b03909216916340c10f199161092c918e9190600401612e53565b602060405180830381600087803b15801561094657600080fd5b505af115801561095a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097e9190612c1f565b61099a5760405162461bcd60e51b81526004016104569061318d565b5050505050509392505050565b6109af612116565b6001546001600160a01b039081169116146109dc5760405162461bcd60e51b815260040161045690613121565b6109ed81600163ffffffff61211a16565b610a095760405162461bcd60e51b815260040161045690613269565b51600655565b6000546001600160a01b031681565b6000546001600160a01b0316610a3357600080fd5b60005460405163117c72b360e11b81526001600160a01b03909116906322f8e56690610a63908490600401612f12565b600060405180830381600087803b158015610a7d57600080fd5b505af1158015610a91573d6000803e3d6000fd5b5050505050565b60085481565b610aa6612116565b6001546001600160a01b03908116911614610ad35760405162461bcd60e51b815260040161045690613121565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b031615610b93576000809054906101000a90046001600160a01b03166001600160a01b03166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5457600080fd5b505afa158015610b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8c9190612da2565b9050610b96565b50425b90565b60075481565b600b546001600160a01b031681565b610bb9848484611c41565b6000610bd4610bc6610af5565b60059063ffffffff611e4816565b90508481336001600160a01b03167f6992efdd7b69c1a8d79212d5ef5fe92118ed053fb7195808a858fa6889a117e98786604051610c13929190613429565b60405180910390a45050505050565b600b546001600160a01b031615610c4b5760405162461bcd60e51b815260040161045690613343565b6000610c55610af5565b90506001610c6a60058363ffffffff61213116565b6002811115610c7557fe5b14610c925760405162461bcd60e51b815260040161045690613004565b6000610ca560058363ffffffff611e4816565b90506000610cb38787611ebc565b600083815260028201602090815260408083203384529182905290912080549293509091610cf35760405162461bcd60e51b8152600401610456906131fb565b80600001548787338b888e604051602001610d1396959493929190612e05565b6040516020818303038152906040528051906020012014610d465760405162461bcd60e51b815260040161045690612f50565b60008155610d5384612169565b600084815260026020526040902054610d6a6129b0565b60408051602081019182905260095463277166bf60e11b9092529081906001600160a01b0316634ee2cd7e610da3338760248601612e53565b60206040518083038186803b158015610dbb57600080fd5b505afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190612da2565b815250905088604051602001610e099190612f12565b60408051601f198184030181529190528051602090910120600180850191909155610e3d9085018a8363ffffffff61226016565b8a86336001600160a01b03167fd04931ad32b4f942a0f169443ebd7f85a7d42c8b4310b4792243a065348836078d8d8660000151604051610e8093929190613442565b60405180910390a45050505050505050505050565b6000610ea2610bc6610af5565b905090565b60005b81811015610f1a57610f12838383818110610ec157fe5b90506080020160000135848484818110610ed757fe5b90506080020160200135858585818110610eed57fe5b90506080020160400135868686818110610f0357fe5b90506080020160600135610c22565b600101610eaa565b505050565b600b546001600160a01b031615610f5f57600b546001600160a01b03163314610f5a5760405162461bcd60e51b8152600401610456906133e8565b611088565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090610f9b9067526567697374727960c01b90600401612f12565b60206040518083038186803b158015610fb357600080fd5b505afa158015610fc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610feb9190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b9061101a903390600401612e3f565b60206040518083038186803b15801561103257600080fd5b505afa158015611046573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106a9190612c1f565b6110865760405162461bcd60e51b8152600401610456906132d5565b505b6000611092610af5565b9050808211156110b45760405162461bcd60e51b815260040161045690613232565b6110bc612327565b6001600160a01b03166390978d1b846040518263ffffffff1660e01b81526004016110e79190612f12565b60206040518083038186803b1580156110ff57600080fd5b505afa158015611113573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111379190612c1f565b6111535760405162461bcd60e51b8152600401610456906130a9565b600061115f84846123c8565b600081815260036020526040812091925061118160058563ffffffff611e4816565b9050600061118f83836123fb565b9050600081600381111561119f57fe5b14156112795760006111b883600163ffffffff61248816565b604080516080810182528a815260208082018b8152828401858152600480546060860190815260008d815260039586905287812096518755935160018088019190915592519486019490945592519383019390935581549283018255527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0187905551909150889082907f5d80f93c41e95cacea0b9ce9bb825092d709fa503a70bb26ea3f536bf16946bd9061126f908b90612f12565b60405180910390a3505b50505050505050565b60005b81811015610f1a5782828281811061129957fe5b90506020028101906112ab91906134c1565b6112b9906060810190613473565b151590506113315761132c8383838181106112d057fe5b90506020028101906112e291906134c1565b358484848181106112ef57fe5b905060200281019061130191906134c1565b6020013585858581811061131157fe5b905060200281019061132391906134c1565b60400135611c41565b6113fd565b6113fd83838381811061134057fe5b905060200281019061135291906134c1565b3584848481811061135f57fe5b905060200281019061137191906134c1565b6020013585858581811061138157fe5b905060200281019061139391906134c1565b604001358686868181106113a357fe5b90506020028101906113b591906134c1565b6113c3906060810190613473565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bae92505050565b600101611285565b61140d612116565b6001546001600160a01b0390811691161461143a5760405162461bcd60e51b815260040161045690613121565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60055481565b6000610ea2611497610af5565b60059063ffffffff61213116565b606060006114b1610af5565b905060006114c660058363ffffffff611e4816565b60045490915060609067ffffffffffffffff811180156114e557600080fd5b5060405190808252806020026020018201604052801561151f57816020015b61150c6129c3565b8152602001906001900390816115045790505b5090506000805b6004548110156115ca576000600360006004848154811061154357fe5b9060005260206000200154815260200190815260200160002090506001600381111561156b57fe5b61157582876123fb565b600381111561158057fe5b14156115c15760405180604001604052808260000154815260200182600101548152508484815181106115af57fe5b60209081029190910101526001909201915b50600101611526565b5060608167ffffffffffffffff811180156115e457600080fd5b5060405190808252806020026020018201604052801561161e57816020015b61160b6129c3565b8152602001906001900390816116035790505b50905060005b8281101561165f5783818151811061163857fe5b602002602001015182828151811061164c57fe5b6020908102919091010152600101611624565b5094505050505090565b611671612116565b6001546001600160a01b0390811691161461169e5760405162461bcd60e51b815260040161045690613121565b51600755565b606080825167ffffffffffffffff811180156116bf57600080fd5b506040519080825280602002602001820160405280156116f957816020015b6116e66129c3565b8152602001906001900390816116de5790505b5090506000611709610bc6610af5565b905060005b84518110156117e657600061174086838151811061172857fe5b60200260200101516000015187848151811061065657fe5b9050600061174e82856123fb565b9050600181600381111561175e57fe5b1415611786578385848151811061177157fe5b602002602001015160200181815250506117a8565b816003015485848151811061179757fe5b602002602001015160200181815250505b808584815181106117b557fe5b60200260200101516000019060038111156117cc57fe5b908160038111156117d957fe5b905250505060010161170e565b50909150505b919050565b6117f9612116565b6001546001600160a01b039081169116146118265760405162461bcd60e51b815260040161045690613121565b600855565b6002602081815260009283526040928390208054845180840186526001830154815285519384019095529281015482526003015491929184565b6001546001600160a01b031690565b600b546000906001600160a01b0316156118b757600b546001600160a01b031633146118b25760405162461bcd60e51b8152600401610456906133e8565b6119e0565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e40906118f39067526567697374727960c01b90600401612f12565b60206040518083038186803b15801561190b57600080fd5b505afa15801561191f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119439190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b90611972903390600401612e3f565b60206040518083038186803b15801561198a57600080fd5b505afa15801561199e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c29190612c1f565b6119de5760405162461bcd60e51b8152600401610456906132d5565b505b60006119ec84846124ad565b5090925050505b92915050565b600b546001600160a01b031615611a225760405162461bcd60e51b815260040161045690613343565b6000611a2c610af5565b90506001611a4160058363ffffffff61213116565b6002811115611a4c57fe5b14611a695760405162461bcd60e51b8152600401610456906133b1565b6000611a7c60058363ffffffff611e4816565b9050611a8781612169565b5050565b6009546001600160a01b031681565b60065481565b600b546000906001600160a01b031615611ae357600b546001600160a01b03163314611ade5760405162461bcd60e51b8152600401610456906133e8565b611c0c565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090611b1f9067526567697374727960c01b90600401612f12565b60206040518083038186803b158015611b3757600080fd5b505afa158015611b4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6f9190612aaf565b60405163f9f6b49b60e01b81529091506001600160a01b0382169063f9f6b49b90611b9e903390600401612e3f565b60206040518083038186803b158015611bb657600080fd5b505afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee9190612c1f565b611c0a5760405162461bcd60e51b8152600401610456906132d5565b505b6000806060611c1b86866124ad565b9250925092508281906119ec5760405162461bcd60e51b81526004016104569190612f3d565b600b546001600160a01b031615611c6a5760405162461bcd60e51b815260040161045690613343565b80611c875760405162461bcd60e51b8152600401610456906131c4565b6000611c91610af5565b90506000611ca660058363ffffffff61213116565b6002811115611cb157fe5b14611cce5760405162461bcd60e51b81526004016104569061330c565b6000611ce160058363ffffffff611e4816565b90506000611cef8686611ebc565b90506001611cfd82846123fb565b6003811115611d0857fe5b14611d255760405162461bcd60e51b815260040161045690613156565b600381018290556000828152600282016020908152604080832033808552928190529281902087905551889185917f879c67d036f174a10ea491cf7281d05af9b906660b4f26727d866aec0cf9147c90611d80908b90612f12565b60405180910390a450505050505050565b611d99612116565b6001546001600160a01b03908116911614611dc65760405162461bcd60e51b815260040161045690613121565b6001600160a01b038116611dec5760405162461bcd60e51b815260040161045690612f87565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080611e5f60025b85549063ffffffff61263916565b9050611e71838263ffffffff61267316565b949350505050565b611e816129b0565b6040805160208101909152825184518291670de0b6b3a764000091611eab9163ffffffff61263916565b81611eb257fe5b0490529392505050565b600060036000611ecc85856123c8565b8152602001908152602001600020905092915050565b60048201546000191415611ef557611a87565b600080611f18611f0885600301546126b5565b600185019063ffffffff6127ad16565b9150915081611f395760405162461bcd60e51b8152600401610456906132a0565b60048054600019810191600091600391839185908110611f5557fe5b9060005260206000200154815260200190815260200160002090508560040154816004018190555060048281548110611f8a57fe5b90600052602060002001546004876004015481548110611fa657fe5b6000918252602090912001556004805480611fbd57fe5b60008281526020812082016000199081019190915590810190915560048701558554600387015460018801546040517f67565e6a3e804c4e180134cb2885e32142229de3ca125701318af11658ee498891612019918890612f1b565b60405180910390a3505050505050565b600082600201546040516020016120409190612f12565b604051602081830303815290604052805190602001208214905092915050565b6120686129b0565b50600281015460009081526020918252604090819020815192830190915254815290565b6120946129b0565b60408051602081019091528251845182916120cd916120c190670de0b6b3a764000063ffffffff61263916565b9063ffffffff61267316565b90529392505050565b6120de6129b0565b60408051602081019091528251845182916120cd919063ffffffff61248816565b600061210a82612871565b51835111905092915050565b3390565b600061212582612871565b51835110905092915050565b60006121576002845461214b90859063ffffffff61267316565b9063ffffffff6128a516565b600281111561216257fe5b9392505050565b60008181526002602052604090208054611a8757600960009054906101000a90046001600160a01b03166001600160a01b0316639711715a6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156121cd57600080fd5b505af11580156121e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122059190612da2565b81556000828152600260208190526040909120600754600182015560065491015560085461224a9061223e60058563ffffffff6128e716565b9063ffffffff61248816565b6000838152600260205260409020600301555050565b604080516020810190915260018401548152612282908263ffffffff6120d616565b516001840155600082815260208481526040918290208251918201909252905481526122b4908263ffffffff6120d616565b600083815260208590526040902090519055600283015482148015906123185750600283015460009081526020848152604080832081518084018352905481528584528683529281902081519283019091525481526123189163ffffffff61291716565b15610f1a575060029190910155565b600a546040516302abf57960e61b81526000916001600160a01b03169063aafd5e4090612378907f4964656e74696669657257686974656c6973740000000000000000000000000090600401612f12565b60206040518083038186803b15801561239057600080fd5b505afa1580156123a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea29190612aaf565b600082826040516020016123dd929190612f1b565b60405160208183030381529060405280519060200120905092915050565b6000826003015460001415612412575060006119f3565b818360030154101561246c576003830154600081815260028501602052604081209161245190612441906126b5565b600184019063ffffffff6127ad16565b50905080612460576001612463565b60025b925050506119f3565b8183600301541415612480575060016119f3565b5060036119f3565b6000828201838110156121625760405162461bcd60e51b815260040161045690612fcd565b600080606060006124be8686611ebc565b905060006124cd610bc6610af5565b905060006124db83836123fb565b905060018160038111156124eb57fe5b141561253757505060408051808201909152601e81527f43757272656e7420766f74696e6720726f756e64206e6f7420656e646564000060208201526000945084935091506126329050565b600281600381111561254557fe5b1415612592576003830154600081815260028501602052604081209161256e90612441906126b5565b60408051602081019091526000815260019a50909850965061263295505050505050565b60038160038111156125a057fe5b14156125ec57505060408051808201909152601d81527f5072696365206973207374696c6c20746f20626520766f746564206f6e00000060208201526000945084935091506126329050565b505060408051808201909152601981527f507269636520776173206e65766572207265717565737465640000000000000060208201526000945084935091506126329050565b9250925092565b600082612648575060006119f3565b8282028284828161265557fe5b04146121625760405162461bcd60e51b8152600401610456906130e0565b600061216283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061291e565b6126bd6129b0565b600082815260026020526040902054806126e8575050604080516020810190915260001981526117ec565b6126f06129b0565b604080516020810191829052600954630981b24d60e41b9092529081906001600160a01b031663981b24d06127288660248501612f12565b60206040518083038186803b15801561274057600080fd5b505afa158015612754573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127789190612da2565b905260008581526002602081815260409283902083519182019093529101548152909150611e7190829063ffffffff611e7916565b6000806127b86129b0565b6127d360646127c76032612871565b9063ffffffff61295516565b6040805160208101909152600187015481529091506127f8908563ffffffff61291716565b801561284f57506040805160208082018352600188015482526002880154600090815288825283902083519182019093529154825261284f918391612843919063ffffffff61208c16565b9063ffffffff61291716565b15612864576001925084600201549150612869565b600092505b509250929050565b6128796129b0565b60408051602081019091528061289d84670de0b6b3a764000063ffffffff61263916565b905292915050565b600061216283836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f000000000000000081525061297c565b6000806128f46002611e51565b9050611e7161290a84600163ffffffff61248816565b829063ffffffff61263916565b5190511190565b6000818361293f5760405162461bcd60e51b81526004016104569190612f3d565b50600083858161294b57fe5b0495945050505050565b61295d6129b0565b6040805160208101909152835181906120cd908563ffffffff61267316565b6000818361299d5760405162461bcd60e51b81526004016104569190612f3d565b508284816129a757fe5b06949350505050565b6040518060200160405280600081525090565b604080518082019091526000808252602082015290565b600082601f8301126129ea578081fd5b813567ffffffffffffffff811115612a00578182fd5b6020612a0f81828402016134e0565b8281529250808301848201604080850287018401881015612a2f57600080fd5b60005b85811015612a5657612a448984612a62565b84529284019291810191600101612a32565b50505050505092915050565b600060408284031215612a73578081fd5b612a7d60406134e0565b9050813581526020820135602082015292915050565b600060208284031215612aa4578081fd5b813561216281613513565b600060208284031215612ac0578081fd5b815161216281613513565b600080600060608486031215612adf578182fd5b8335612aea81613513565b925060208401359150604084013567ffffffffffffffff811115612b0c578182fd5b612b18868287016129da565b9150509250925092565b60008060208385031215612b34578182fd5b823567ffffffffffffffff80821115612b4b578384fd5b81850186601f820112612b5c578485fd5b8035925081831115612b6c578485fd5b8660208085028301011115612b7f578485fd5b60200196919550909350505050565b600060208284031215612b9f578081fd5b813567ffffffffffffffff811115612bb5578182fd5b611e71848285016129da565b60008060208385031215612bd3578182fd5b823567ffffffffffffffff80821115612bea578384fd5b81850186601f820112612bfb578485fd5b8035925081831115612c0b578485fd5b866020608085028301011115612b7f578485fd5b600060208284031215612c30578081fd5b81518015158114612162578182fd5b60008060408385031215612c51578182fd5b50508035926020909101359150565b600080600060608486031215612c74578283fd5b505081359360208301359350604090920135919050565b60008060008060808587031215612ca0578081fd5b843593506020850135925060408501359150606085013567ffffffffffffffff80821115612ccc578283fd5b81870188601f820112612cdd578384fd5b8035925081831115612ced578384fd5b612d00601f8401601f19166020016134e0565b9150828252886020848301011115612d16578384fd5b612d27836020840160208401613507565b5094979396509194505050565b60008060008060808587031215612d49578081fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215612d76578081fd5b612d8060206134e0565b9135825250919050565b600060208284031215612d9b578081fd5b5035919050565b600060208284031215612db3578081fd5b5051919050565b60008151808452815b81811015612ddf57602081850181015186830182015201612dc3565b81811115612df05782602083870101525b50601f01601f19169290920160200192915050565b958652602086019490945260609290921b6bffffffffffffffffffffffff1916604085015260548401526074830152609482015260b40190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000919060409081850190868401855b82811015612eae57815180518552860151868501529284019290850190600101612e89565b5091979650505050505050565b602080825282518282018190526000919060409081850190868401855b82811015612eae578151805160048110612eee57fe5b8552860151868501529284019290850190600101612ed8565b901515815260200190565b90815260200190565b918252602082015260400190565b6020810160038310612f3757fe5b91905290565b6000602082526121626020830184612dba565b6020808252601c908201527f52657665616c6564206461746120213d20636f6d6d6974206861736800000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601d908201527f43616e6e6f742072657665616c20696e20636f6d6d6974207068617365000000604082015260600190565b6020808252601b908201527f43616e206f6e6c792063616c6c2066726f6d206d696772617465640000000000604082015260600190565b6020808252600f908201527f496e76616c696420726f756e6449640000000000000000000000000000000000604082015260600190565b6020808252601e908201527f556e737570706f72746564206964656e74696669657220726571756573740000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601e908201527f43616e6e6f7420636f6d6d697420696e61637469766520726571756573740000604082015260600190565b6020808252601c908201527f566f74696e6720746f6b656e2069737375616e6365206661696c656400000000604082015260600190565b60208082526015908201527f496e76616c69642070726f766964656420686173680000000000000000000000604082015260600190565b60208082526013908201527f496e76616c696420686173682072657665616c00000000000000000000000000604082015260600190565b60208082526018908201527f43616e206f6e6c79207265717565737420696e20706173740000000000000000604082015260600190565b6020808252601d908201527f4741542070657263656e74616765206d757374206265203c2031303025000000604082015260600190565b6020808252818101527f43616e2774207265736f6c766520756e7265736f6c7665642072657175657374604082015260600190565b60208082526019908201527f43616c6c6564206d757374206265207265676973746572656400000000000000604082015260600190565b6020808252601d908201527f43616e6e6f7420636f6d6d697420696e2072657665616c207068617365000000604082015260600190565b6020808252601e908201527f4f6e6c792063616c6c2074686973206966206e6f74206d696772617465640000604082015260600190565b6020808252601d908201527f526574726965766520666f7220766f7465732073616d6520726f756e64000000604082015260600190565b6020808252601d908201527f4f6e6c7920736e617073686f7420696e2072657665616c207068617365000000604082015260600190565b6020808252601f908201527f43616c6c6572206d757374206265206d69677261746564206164647265737300604082015260600190565b9051815260200190565b600083825260406020830152611e716040830184612dba565b9283526020830191909152604082015260600190565b93845291516020840152516040830152606082015260800190565b6000808335601e19843603018112613489578283fd5b8084018035925067ffffffffffffffff8311156134a4578384fd5b602001925050368190038213156134ba57600080fd5b9250929050565b60008235607e198336030181126134d6578182fd5b9190910192915050565b60405181810167ffffffffffffffff811182821017156134ff57600080fd5b604052919050565b82818337506000910152565b6001600160a01b038116811461352857600080fd5b50565b6000811161353857600080fd5b9055565b600061354782612871565b518351111590509291505056fea2646970667358221220894082513f5f7034400c32948565d69048f772378ce7f5199fff61a8ce4950cf64736f6c63430006060033

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

000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000001c6bf52634000000000000000000000000000000000000000000000000000000000000012750000000000000000000000000004fa0d235c4abf4bcf4787af4cf447de572ef82800000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c30000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _phaseLength (uint256): 86400
Arg [1] : _gatPercentage (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [2] : _inflationRate (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [3] : _rewardsExpirationTimeout (uint256): 1209600
Arg [4] : _votingToken (address): 0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828
Arg [5] : _finder (address): 0x40f941E48A552bF496B154Af6bf55725f18D77c3
Arg [6] : _timerAddress (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [1] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [2] : 0000000000000000000000000000000000000000000000000001c6bf52634000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000127500
Arg [4] : 00000000000000000000000004fa0d235c4abf4bcf4787af4cf447de572ef828
Arg [5] : 00000000000000000000000040f941e48a552bf496b154af6bf55725f18d77c3
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

578:34602:110:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;578:34602:110;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;21708:3612:110;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;28819:219;;;;;;;;;:::i;:::-;;348:27:95;;;:::i;:::-;;;;;;;;1062:115;;;;;;;;;:::i;4445:39:110:-;;;:::i;:::-;;;;;;;;27967:117;;;;;;;;;:::i;1422:256:95:-;;;:::i;4262:40:110:-;;;:::i;4781:30::-;;;:::i;19143:369::-;;;;;;;;;:::i;16267:2184::-;;;;;;;;;:::i;27464:144::-;;;:::i;20882:237::-;;;;;;;;;:::i;8627:1278::-;;;;;;;;;:::i;19940:543::-;;;;;;;;;:::i;1651:145:73:-;;;:::i;3781:33:110:-;;;:::i;27170:135::-;;;:::i;:::-;;;;;;;;25684:1277;;;:::i;:::-;;;;;;;;28383:137;;;;;;;;;:::i;11916:974::-;;;;;;;;;:::i;:::-;;;;;;;;29298:162;;;;;;;;;:::i;3436:39::-;;;;;;;;;:::i;:::-;;;;;;;;;;;1028:77:73;;;:::i;10360:215:110:-;;;;;;;;;:::i;:::-;;;;;;;;15323:344;;;:::i;4529:30::-;;;:::i;3947:40::-;;;:::i;11037:404::-;;;;;;;;;:::i;13851:1106::-;;;;;;;;;:::i;1945:240:73:-;;;;;;;;;:::i;21708:3612:110:-;21863:45;;:::i;:::-;21924:15;;-1:-1:-1;;;;;21924:15:110;:29;21920:129;;21991:15;;-1:-1:-1;;;;;21991:15:110;21977:10;:29;21969:69;;;;-1:-1:-1;;;21969:69:110;;;;;;;;;;;;;;;;;22058:17;22078:16;:14;:16::i;:::-;22058:36;-1:-1:-1;22122:43:110;:10;22058:36;22122:43;:32;:43;:::i;:::-;22112:7;:53;22104:81;;;;-1:-1:-1;;;22104:81:110;;;;;;;;;22196:19;22218:15;;;:6;:15;;;;;22272:27;;;;22260:39;;22309:42;;:::i;:::-;22354:98;;;;;;;;;;22387:11;;22425:16;;-1:-1:-1;;;22387:55:110;;;22354:98;;;;-1:-1:-1;;;;;22387:11:110;;:23;;:55;;22411:12;;22387:55;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;22387:55:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;22387:55:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;22387:55:110;;;;;;;;;22354:98;;22309:143;-1:-1:-1;22565:46:110;;:::i;:::-;22614:86;;;;;;;;;;22647:11;;22673:16;;-1:-1:-1;;;22647:43:110;;;22614:86;;;;-1:-1:-1;;;;;22647:11:110;;:25;;:43;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;22647:43:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;22647:43:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;22647:43:110;;;;;;;;;22614:86;;22565:135;-1:-1:-1;22710:45:110;;:::i;:::-;22758:23;;;;;;;;;:19;;;:23;;;:44;;22782:19;22758:44;:23;:44;:::i;:::-;22897:22;;;;;;;;;-1:-1:-1;22897:22:110;;;;;-1:-1:-1;22710:92:110;;-1:-1:-1;22930:2166:110;22954:10;:17;22950:1;:21;22930:2166;;;22992:33;23028:62;23045:10;23056:1;23045:13;;;;;;;;;;;;;;:24;;;23071:10;23082:1;23071:13;;;;;;;;;;;;;;:18;;;23028:16;:62::i;:::-;23167:28;;;;23104:33;23140:56;;;:26;;;:56;;;;;22992:98;;-1:-1:-1;23288:39:110;;23280:81;;;;-1:-1:-1;;;23280:81:110;;;;;;;;;23376:48;23397:12;23411;23376:20;:48::i;:::-;-1:-1:-1;;;;;23443:42:110;;:28;:42;;;;;;;;;;:53;;;23439:1491;;23521:8;;;;23439:1491;23554:9;23550:1380;;;23692:10;23703:1;23692:13;;;;;;;;;;;;;;:24;;;23683:7;23669:12;-1:-1:-1;;;;;23652:88:110;;23718:10;23729:1;23718:13;;;;;;;;;;;;;;:18;;;23738:1;23652:88;;;;;;;;;;;;;;;;23550:1380;;;-1:-1:-1;;;;;23828:42:110;;:28;:42;;;;;;;;;;:53;;;;;23782:100;;:30;;;:100;:45;:100;:::i;:::-;23761:1169;;;24170:33;;:::i;:::-;24206:144;24271:61;:12;:30;;:59;:61::i;:::-;24206:39;:15;24226:18;24206:39;:19;:39;:::i;:::-;:43;:144;:43;:144;:::i;:::-;24170:180;-1:-1:-1;24389:30:110;:18;24170:180;24389:30;:22;:30;:::i;:::-;24368:51;;24600:10;24611:1;24600:13;;;;;;;;;;;;;;:24;;;24571:7;24537:12;-1:-1:-1;;;;;24499:220:110;;24646:10;24657:1;24646:13;;;;;;;;;;;;;;:18;;;24686:6;:15;;;24499:220;;;;;;;;;;;;;;;;23761:1169;;;;24867:10;24878:1;24867:13;;;;;;;;;;;;;;:24;;;24858:7;24844:12;-1:-1:-1;;;;;24827:88:110;;24893:10;24904:1;24893:13;;;;;;;;;;;;;;:18;;;24913:1;24827:88;;;;;;;;;;;;;;;;23761:1169;-1:-1:-1;;;;;25032:42:110;;:28;:42;;;;;;;;;;;:53;;25025:60;-1:-1:-1;22930:2166:110;22973:3;;22930:2166;;;-1:-1:-1;25152:35:110;:18;25185:1;25152:35;:32;:35;:::i;:::-;25148:166;;;25211:11;;25242:27;;25211:59;;-1:-1:-1;;;25211:59:110;;-1:-1:-1;;;;;25211:11:110;;;;:16;;:59;;25228:12;;25242:27;25211:59;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;25211:59:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;25211:59:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;25211:59:110;;;;;;;;;25203:100;;;;-1:-1:-1;;;25203:100:110;;;;;;;;;21708:3612;;;;;;;;;;;:::o;28819:219::-;1242:12:73;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;28925:30:110::1;:16:::0;28953:1:::1;28925:30;:27;:30;:::i;:::-;28917:72;;;;-1:-1:-1::0;;;28917:72:110::1;;;;;;;;;28999:32:::0;:13:::1;:32:::0;28819:219::o;348:27:95:-;;;-1:-1:-1;;;;;348:27:95;;:::o;1062:115::-;865:3;841:12;-1:-1:-1;;;;;841:12:95;833:37;;12:1:-1;9;2:12;833:37:95;1136:12:::1;::::0;1130:40:::1;::::0;-1:-1:-1;;;1130:40:95;;-1:-1:-1;;;;;1136:12:95;;::::1;::::0;1130:34:::1;::::0;:40:::1;::::0;1165:4;;1130:40:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;1130:40:95;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1130:40:95;;;;1062:115:::0;:::o;4445:39:110:-;;;;:::o;27967:117::-;1242:12:73;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;28043:15:110::1;:34:::0;;-1:-1:-1;;;;;;28043:34:110::1;-1:-1:-1::0;;;;;28043:34:110;;;::::1;::::0;;;::::1;::::0;;27967:117::o;1422:256:95:-;1469:7;1492:12;;-1:-1:-1;;;;;1492:12:95;:28;1488:184;;1549:12;;;;;;;;;-1:-1:-1;;;;;1549:12:95;-1:-1:-1;;;;;1543:34:95;;:36;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1543:36:95;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1543:36:95;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;1543:36:95;;;;;;;;;1536:43;;;;1488:184;-1:-1:-1;1617:3:95;1488:184;1422:256;:::o;4262:40:110:-;;;;:::o;4781:30::-;;;-1:-1:-1;;;;;4781:30:110;;:::o;19143:369::-;19310:34;19321:10;19333:4;19339;19310:10;:34::i;:::-;19355:15;19373:50;19406:16;:14;:16::i;:::-;19373:10;;:50;:32;:50;:::i;:::-;19355:68;;19473:10;19464:7;19452:10;-1:-1:-1;;;;;19438:67:110;;19485:4;19491:13;19438:67;;;;;;;;;;;;;;;;19143:369;;;;;:::o;16267:2184::-;8021:15;;-1:-1:-1;;;;;8021:15:110;:29;8013:72;;;;-1:-1:-1;;;8013:72:110;;;;;;;;;16432:17:::1;16452:16;:14;:16::i;:::-;16432:36:::0;-1:-1:-1;16531:12:110::1;16486:41;:10;16517:9:::0;16486:41:::1;:30;:41;:::i;:::-;:57;;;;;;;;;16478:99;;;;-1:-1:-1::0;;;16478:99:110::1;;;;;;;;;16728:15;16746:43;:10;16779:9:::0;16746:43:::1;:32;:43;:::i;:::-;16728:61;;16800:33;16836:34;16853:10;16865:4;16836:16;:34::i;:::-;16880:33;16916:35:::0;;;:26:::1;::::0;::::1;:35;::::0;;;;;;;17030:10:::1;17001:40:::0;;;;;;;;;17220:21;;16800:70;;-1:-1:-1;16916:35:110;;17212:67:::1;;;;-1:-1:-1::0;;;17212:67:110::1;;;;;;;;;17393:14;:21;;;17337:5;17344:4;17350:10;17362:4;17368:7;17377:10;17320:68;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;17320:68:110;;;17310:79;;;;;;:104;17289:179;;;;-1:-1:-1::0;;;17289:179:110::1;;;;;;;;;17485:21;17478:28:::0;;17725:30:::1;17747:7:::0;17725:21:::1;:30::i;:::-;17803:18;17824:15:::0;;;:6:::1;:15;::::0;;;;:26;18040:34:::1;;:::i;:::-;18077:68;::::0;;::::1;::::0;::::1;::::0;;;;18097:11:::1;::::0;-1:-1:-1;;;18097:47:110;;;18077:68;;;-1:-1:-1;;;;;18097:11:110::1;:23;:47;18121:10;18133::::0;18097:47;;;::::1;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;18097:47:110;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;18097:47:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;18097:47:110;;;;;;;;;18077:68;;::::0;18040:105:::1;;18244:5;18233:17;;;;;;;;;;;::::0;;-1:-1:-1;;26:21;;::::1;22:32:::0;6:49;;18233:17:110;;;18223:28;;49:4:-1::1;18223:28:110::0;;::::1;::::0;18195:25:::1;::::0;;::::1;:56:::0;;;;18298:54:::1;::::0;:30;::::1;18337:5:::0;18344:7;18298:54:::1;:38;:54;:::i;:::-;18402:10;18393:7;18381:10;-1:-1:-1::0;;;;;18368:76:110::1;;18414:4;18420:5;18427:7;:16;;;18368:76;;;;;;;;;;;;;;;;;8095:1;;;;;;;16267:2184:::0;;;;:::o;27464:144::-;27525:7;27551:50;27584:16;:14;:16::i;27551:50::-;27544:57;;27464:144;:::o;20882:237::-;20963:9;20958:155;20978:18;;;20958:155;;;21017:85;21028:7;;21036:1;21028:10;;;;;;;;;;;;:21;;;21051:7;;21059:1;21051:10;;;;;;;;;;;;:15;;;21068:7;;21076:1;21068:10;;;;;;;;;;;;:16;;;21086:7;;21094:1;21086:10;;;;;;;;;;;;:15;;;21017:10;:85::i;:::-;20998:3;;20958:155;;;;20882:237;;:::o;8627:1278::-;7610:15;;-1:-1:-1;;;;;7610:15:110;:29;7606:345;;7677:15;;-1:-1:-1;;;;;7677:15:110;7663:10;:29;7655:73;;;;-1:-1:-1;;;7655:73:110;;;;;;;;;7606:345;;;7788:6;;:58;;-1:-1:-1;;;7788:58:110;;7759:17;;-1:-1:-1;;;;;7788:6:110;;:31;;:58;;-1:-1:-1;;;7820:25:110;7788:58;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7788:58:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7788:58:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7788:58:110;;;;;;;;;7869:41;;-1:-1:-1;;;7869:41:110;;7759:88;;-1:-1:-1;;;;;;7869:29:110;;;;;:41;;7899:10;;7869:41;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7869:41:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7869:41:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7869:41:110;;;;;;;;;7861:79;;;;-1:-1:-1;;;7861:79:110;;;;;;;;;7606:345;;8736:17:::1;8756:16;:14;:16::i;:::-;8736:36;;8798:9;8790:4;:17;;8782:54;;;;-1:-1:-1::0;;;8782:54:110::1;;;;;;;;;8854:25;:23;:25::i;:::-;-1:-1:-1::0;;;;;8854:47:110::1;;8902:10;8854:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;8854:59:110;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;8854:59:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;8854:59:110;;;;;;;;;8846:102;;;;-1:-1:-1::0;;;8846:102:110::1;;;;;;;;;8959:22;8984:37;9004:10;9016:4;8984:19;:37::i;:::-;9031:33;9067:29:::0;;;:13:::1;:29;::::0;;;;8959:62;;-1:-1:-1;9131:43:110::1;:10;9164:9:::0;9131:43:::1;:32;:43;:::i;:::-;9106:68;;9185:27;9215:47;9233:12;9247:14;9215:17;:47::i;:::-;9185:77:::0;-1:-1:-1;9294:26:110::1;9277:13;:43;;;;;;;;;9273:626;;;9482:19;9504:21;:14:::0;9523:1:::1;9504:21;:18;:21;:::i;:::-;9572:194;::::0;;::::1;::::0;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;;;9724:20:::1;:27:::0;;9572:194;;;;;;-1:-1:-1;9540:29:110;;;:13:::1;:29:::0;;;;;;;:226;;;;;;::::1;::::0;;::::1;::::0;;;;;;;;::::1;::::0;;;;;;;;::::1;::::0;;;;27:10:-1;;23:18;;::::1;45:23:::0;;9780:41:110;;::::1;::::0;;;9840:48;9482:43;;-1:-1:-1;9615:10:110;;9482:43;;9840:48:::1;::::0;::::1;::::0;9649:4;;9840:48:::1;;;;;;;;;;9273:626;;7960:1;;;;;8627:1278:::0;;:::o;19940:543::-;20025:9;20020:457;20040:18;;;20020:457;;;20083:7;;20091:1;20083:10;;;;;;;;;;;;;;;;;;;;:24;;;;;;;;;:36;20079:388;;-1:-1:-1;20079:388:110;;20139:67;20150:7;;20158:1;20150:10;;;;;;;;;;;;;;;;;;;;:21;20173:7;;20181:1;20173:10;;;;;;;;;;;;;;;;;;;;:15;;;20190:7;;20198:1;20190:10;;;;;;;;;;;;;;;;;;;;:15;;;20139:10;:67::i;:::-;20079:388;;;20245:207;20293:7;;20301:1;20293:10;;;;;;;;;;;;;;;;;;;;:21;20336:7;;20344:1;20336:10;;;;;;;;;;;;;;;;;;;;:15;;;20373:7;;20381:1;20373:10;;;;;;;;;;;;;;;;;;;;:15;;;20410:7;;20418:1;20410:10;;;;;;;;;;;;;;;;;;;;:24;;;;;;;;;20245:207;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;20245:26:110;;-1:-1:-1;;;20245:207:110:i;:::-;20060:3;;20020:457;;1651:145:73;1242:12;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;1741:6:::1;::::0;1720:40:::1;::::0;1757:1:::1;::::0;-1:-1:-1;;;;;1741:6:73::1;::::0;1720:40:::1;::::0;1757:1;;1720:40:::1;1770:6;:19:::0;;-1:-1:-1;;;;;;1770:19:73::1;::::0;;1651:145::o;3781:33:110:-;;;;:::o;27170:135::-;27226:5;27250:48;27281:16;:14;:16::i;:::-;27250:10;;:48;:30;:48;:::i;25684:1277::-;25746:23;25781:17;25801:16;:14;:16::i;:::-;25781:36;-1:-1:-1;25827:22:110;25852:43;:10;25781:36;25852:43;:32;:43;:::i;:::-;26172:20;:27;25827:68;;-1:-1:-1;26114:34:110;;26151:49;;;2:2:-1;;;;27:1;24;17:12;2:2;26151:49:110;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;26114:86:110;-1:-1:-1;26210:21:110;;26246:477;26270:20;:27;26266:31;;26246:477;;;26318:33;26354:13;:38;26368:20;26389:1;26368:23;;;;;;;;;;;;;;;;26354:38;;;;;;;;;;;26318:74;;26461:20;26410:71;;;;;;;;:47;26428:12;26442:14;26410:17;:47::i;:::-;:71;;;;;;;;;26406:307;;;26529:136;;;;;;;;26578:12;:23;;;26529:136;;;;26629:12;:17;;;26529:136;;;26501:10;26512:13;26501:25;;;;;;;;;;;;;;;;;:164;26683:15;;;;;26406:307;-1:-1:-1;26299:3:110;;26246:477;;;;26733:39;26796:13;26775:35;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;26775:35:110;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;26733:77:110;-1:-1:-1;26825:9:110;26820:103;26844:13;26840:1;:17;26820:103;;;26899:10;26910:1;26899:13;;;;;;;;;;;;;;26878:15;26894:1;26878:18;;;;;;;;;;;;;;;;;:34;26859:3;;26820:103;;;-1:-1:-1;26939:15:110;-1:-1:-1;;;;;25684:1277:110;:::o;28383:137::-;1242:12:73;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;28481:32:110;:13:::1;:32:::0;28383:137::o;11916:974::-;12004:21;12037:35;12094:8;:15;12075:35;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12075:35:110;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;12037:73;;12120:22;12145:50;12178:16;:14;:16::i;12145:50::-;12120:75;-1:-1:-1;12210:9:110;12205:649;12229:8;:15;12225:1;:19;12205:649;;;12265:33;12301:58;12318:8;12327:1;12318:11;;;;;;;;;;;;;;:22;;;12342:8;12351:1;12342:11;;;;;;;12301:58;12265:94;;12374:20;12397:47;12415:12;12429:14;12397:17;:47::i;:::-;12374:70;-1:-1:-1;12592:20:110;12582:6;:30;;;;;;;;;12578:220;;;12667:14;12632:13;12646:1;12632:16;;;;;;;;;;;;;;:32;;:49;;;;;12578:220;;;12755:12;:28;;;12720:13;12734:1;12720:16;;;;;;;;;;;;;;:32;;:63;;;;;12578:220;12837:6;12811:13;12825:1;12811:16;;;;;;;;;;;;;;:23;;:32;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;12246:3:110;;12205:649;;;-1:-1:-1;12870:13:110;;-1:-1:-1;;11916:974:110;;;;:::o;29298:162::-;1242:12:73;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;29399:24:110::1;:54:::0;29298:162::o;3436:39::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1028:77:73:-;1092:6;;-1:-1:-1;;;;;1092:6:73;1028:77;:::o;10360:215:110:-;7610:15;;10469:4;;-1:-1:-1;;;;;7610:15:110;:29;7606:345;;7677:15;;-1:-1:-1;;;;;7677:15:110;7663:10;:29;7655:73;;;;-1:-1:-1;;;7655:73:110;;;;;;;;;7606:345;;;7788:6;;:58;;-1:-1:-1;;;7788:58:110;;7759:17;;-1:-1:-1;;;;;7788:6:110;;:31;;:58;;-1:-1:-1;;;7820:25:110;7788:58;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7788:58:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7788:58:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7788:58:110;;;;;;;;;7869:41;;-1:-1:-1;;;7869:41:110;;7759:88;;-1:-1:-1;;;;;;7869:29:110;;;;;:41;;7899:10;;7869:41;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7869:41:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7869:41:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7869:41:110;;;;;;;;;7861:79;;;;-1:-1:-1;;;7861:79:110;;;;;;;;;7606:345;;10486:14:::1;10508:34;10525:10;10537:4;10508:16;:34::i;:::-;-1:-1:-1::0;10485:57:110;;-1:-1:-1;;;7960:1:110::1;10360:215:::0;;;;:::o;15323:344::-;8021:15;;-1:-1:-1;;;;;8021:15:110;:29;8013:72;;;;-1:-1:-1;;;8013:72:110;;;;;;;;;15403:17:::1;15423:16;:14;:16::i;:::-;15403:36:::0;-1:-1:-1;15502:12:110::1;15457:41;:10;15488:9:::0;15457:41:::1;:30;:41;:::i;:::-;:57;;;;;;;;;15449:99;;;;-1:-1:-1::0;;;15449:99:110::1;;;;;;;;;15559:15;15577:43;:10;15610:9:::0;15577:43:::1;:32;:43;:::i;:::-;15559:61;;15630:30;15652:7;15630:21;:30::i;:::-;8095:1;;15323:344::o:0;4529:30::-;;;-1:-1:-1;;;;;4529:30:110;;:::o;3947:40::-;;;;:::o;11037:404::-;7610:15;;11186:6;;-1:-1:-1;;;;;7610:15:110;:29;7606:345;;7677:15;;-1:-1:-1;;;;;7677:15:110;7663:10;:29;7655:73;;;;-1:-1:-1;;;7655:73:110;;;;;;;;;7606:345;;;7788:6;;:58;;-1:-1:-1;;;7788:58:110;;7759:17;;-1:-1:-1;;;;;7788:6:110;;:31;;:58;;-1:-1:-1;;;7820:25:110;7788:58;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7788:58:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7788:58:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7788:58:110;;;;;;;;;7869:41;;-1:-1:-1;;;7869:41:110;;7759:88;;-1:-1:-1;;;;;;7869:29:110;;;;;:41;;7899:10;;7869:41;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7869:41:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7869:41:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7869:41:110;;;;;;;;;7861:79;;;;-1:-1:-1;;;7861:79:110;;;;;;;;;7606:345;;11209:14:::1;11225:12:::0;11239:21:::1;11264:34;11281:10;11293:4;11264:16;:34::i;:::-;11208:90;;;;;;11393:9;11404:7;11385:27;;;;;-1:-1:-1::0;;;11385:27:110::1;;;;;;;;;13851:1106:::0;8021:15;;-1:-1:-1;;;;;8021:15:110;:29;8013:72;;;;-1:-1:-1;;;8013:72:110;;;;;;;;;14003:18;13995:52:::1;;;;-1:-1:-1::0;;;13995:52:110::1;;;;;;;;;14122:17;14142:16;:14;:16::i;:::-;14122:36:::0;-1:-1:-1;14221:12:110::1;14176:41;:10;14207:9:::0;14176:41:::1;:30;:41;:::i;:::-;:57;;;;;;;;;14168:99;;;;-1:-1:-1::0;;;14168:99:110::1;;;;;;;;;14360:22;14385:43;:10;14418:9:::0;14385:43:::1;:32;:43;:::i;:::-;14360:68;;14439:33;14475:34;14492:10;14504:4;14475:16;:34::i;:::-;14439:70:::0;-1:-1:-1;14591:20:110::1;14540:47;14558:12;14572:14;14540:17;:47::i;:::-;:71;;;;;;;;;14519:148;;;;-1:-1:-1::0;;;14519:148:110::1;;;;;;;;;14678:28;::::0;::::1;:45:::0;;;14733:33:::1;14769:42:::0;;;:26:::1;::::0;::::1;:42;::::0;;;;;;;14850:10:::1;14821:40:::0;;;;;;;;;;;:54;;;14891:59;14933:10;;14709:14;;14891:59:::1;::::0;::::1;::::0;14945:4;;14891:59:::1;;;;;;;;;;8095:1;;;;13851:1106:::0;;;:::o;1945:240:73:-;1242:12;:10;:12::i;:::-;1232:6;;-1:-1:-1;;;;;1232:6:73;;;:22;;;1224:67;;;;-1:-1:-1;;;1224:67:73;;;;;;;;;-1:-1:-1;;;;;2033:22:73;::::1;2025:73;;;;-1:-1:-1::0;;;2025:73:73::1;;;;;;;;;2134:6;::::0;2113:38:::1;::::0;-1:-1:-1;;;;;2113:38:73;;::::1;::::0;2134:6:::1;::::0;2113:38:::1;::::0;2134:6:::1;::::0;2113:38:::1;2161:6;:17:::0;;-1:-1:-1;;;;;;2161:17:73::1;-1:-1:-1::0;;;;;2161:17:73;;;::::1;::::0;;;::::1;::::0;;1945:240::o;1230:262:108:-;1324:7;;1365:75;1394:44;1386:53;1365:16;;;:75;:20;:75;:::i;:::-;1343:97;-1:-1:-1;1457:28:108;:11;1343:97;1457:28;:15;:28;:::i;:::-;1450:35;1230:262;-1:-1:-1;;;;1230:262:108:o;7849:650:40:-;7923:15;;:::i;:::-;8436:56;;;;;;;;;8460:10;;8445;;8436:56;;409:6;;8445:26;;;:14;:26;:::i;:::-;:46;;;;;;8436:56;;8429:63;7849:650;-1:-1:-1;;;7849:650:40:o;30987:180:110:-;31069:20;31108:13;:52;31122:37;31142:10;31154:4;31122:19;:37::i;:::-;31108:52;;;;;;;;;;;31101:59;;30987:180;;;;:::o;32243:980::-;32365:18;;;;-1:-1:-1;;32365:30:110;32361:67;;;32411:7;;32361:67;32438:15;32455:20;32479:112;32540:41;32552:12;:28;;;32540:11;:41::i;:::-;32479:30;;;;:112;:47;:112;:::i;:::-;32437:154;;;;32609:10;32601:55;;;;-1:-1:-1;;;32601:55:110;;;;;;;;;32759:20;:27;;-1:-1:-1;;32759:31:110;;;32739:17;;32840:13;;32739:17;;32759:31;;32854;;;;;;;;;;;;;;32840:46;;;;;;;;;;;32800:86;;32921:12;:18;;;32896:16;:22;;:43;;;;32992:20;33013:9;32992:31;;;;;;;;;;;;;;;;32949:20;32970:12;:18;;;32949:40;;;;;;;;;;;;;;;;;:74;33033:20;:26;;;;;;;;;;;;;;;;-1:-1:-1;;33033:26:110;;;;;;;;;;;;;33070:18;;;:29;33158:23;;33128:28;;;;33033:26;33183:17;;;33114:102;;;;;;33202:13;;33114:102;;;;;;;;;;32243:980;;;;;;:::o;3579:165:84:-;3663:4;3719;:16;;;3708:28;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3708:28:84;;;3698:39;;;;;;3686:8;:51;3679:58;;3579:165;;;;:::o;4127:168::-;4207:26;;:::i;:::-;-1:-1:-1;4271:16:84;;;;4252:18;:36;;;;;;;;;;;;4245:43;;;;;;;;;;;;4127:168::o;10265:634:40:-;10339:15;;:::i;:::-;10833:59;;;;;;;;;10880:10;;10842;;10833:59;;10842:49;;:33;;409:6;10842:33;:14;:33;:::i;:::-;:37;:49;:37;:49;:::i;:::-;10833:59;;10826:66;10265:634;-1:-1:-1;;;10265:634:40:o;6096:151::-;6170:15;;:::i;:::-;6204:36;;;;;;;;;6228:10;;6213;;6204:36;;6213:26;;:10;:26;:14;:26;:::i;1911:147::-;1987:4;2023:19;2040:1;2023:16;:19::i;:::-;:28;2010:10;;:41;;-1:-1:-1;1911:147:40;;;;:::o;735:104:7:-;822:10;735:104;:::o;3847:144:40:-;3920:4;3956:19;3973:1;3956:16;:19::i;:::-;:28;3943:10;;:41;;-1:-1:-1;3847:144:40;;;;:::o;2323:411:108:-;2415:21;2621:92;2667:44;2637:16;;2621:33;;:11;;:33;:15;:33;:::i;:::-;:37;:92;:37;:92;:::i;:::-;2582:145;;;;;;;;2563:164;2323:411;-1:-1:-1;;;2323:411:108:o;31336:901:110:-;31402:19;31424:15;;;:6;:15;;;;;31537:16;;31533:698;;31652:11;;;;;;;;;-1:-1:-1;;;;;31652:11:110;-1:-1:-1;;;;;31652:20:110;;:22;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;31652:22:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;31652:22:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;31652:22:110;;;;;;;;;31633:41;;:16;31771:15;;;:6;:15;;;;;;;;31803:13;31771:45;:29;;;:45;31939:13;31907:45;:29;;:45;32182:24;;32121:99;;:39;:10;31778:7;32121:39;:30;:39;:::i;:::-;:43;:99;:43;:99;:::i;:::-;32081:15;;;;:6;:15;;;;;:37;;:139;31336:901;;:::o;1235:507:84:-;1397:19;;;;;;;;;:15;;;:19;;;:33;;1417:12;1397:33;:19;:33;:::i;:::-;1379:51;:15;;;:51;;1472:29;;;;;;;;;;;;:33;;;;;;;;;;;;:47;;1506:12;1472:47;:33;:47;:::i;:::-;1440:18;:29;;;;;;;;;;:79;;;;1559:16;;;;1546:29;;;;;:126;;-1:-1:-1;1654:16:84;;;;1635:18;:36;;;;;;;;;;;1591:81;;;;;;;;;;;:29;;;;;;;;;;:43;;;;;;;;;;;:81;;;:43;:81;:::i;:::-;1529:207;;;-1:-1:-1;1697:16:84;;;;;:28;1235:507::o;34947:231:110:-;35101:6;;:69;;-1:-1:-1;;;35101:69:110;;35004:49;;-1:-1:-1;;;;;35101:6:110;;:31;;:69;;35133:36;;35101:69;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;35101:69:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35101:69:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;35101:69:110;;;;;;;;31173:157;31258:7;31305:10;31317:4;31294:28;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;31294:28:110;;;31284:39;;;;;;31277:46;;31173:157;;;;:::o;34028:913::-;34160:13;34193:12;:28;;;34225:1;34193:33;34189:746;;;-1:-1:-1;34249:26:110;34242:33;;34189:746;34327:14;34296:12;:28;;;:45;34292:643;;;34420:28;;;;34357:33;34393:56;;;:26;;;:56;;;;;;34485:120;;34550:41;;:11;:41::i;:::-;34485:30;;;;:120;:47;:120;:::i;:::-;34463:142;;;34626:10;:58;;34664:20;34626:58;;;34639:22;34626:58;34619:65;;;;;;34292:643;34737:14;34705:12;:28;;;:46;34701:234;;;-1:-1:-1;34774:20:110;34767:27;;34701:234;-1:-1:-1;34904:20:110;34897:27;;834:176:89;892:7;923:5;;;946:6;;;;938:46;;;;-1:-1:-1;;;938:46:89;;;;;;;;29832:1149:110;29951:4;29969:6;29989:13;30027:33;30063:34;30080:10;30092:4;30063:16;:34::i;:::-;30027:70;;30107:22;30132:50;30165:16;:14;:16::i;30132:50::-;30107:75;;30193:27;30223:47;30241:12;30255:14;30223:17;:47::i;:::-;30193:77;-1:-1:-1;30301:20:110;30284:13;:37;;;;;;;;;30280:695;;;-1:-1:-1;;30337:51:110;;;;;;;;;;;;;;;;;30345:5;;-1:-1:-1;30345:5:110;;-1:-1:-1;30337:51:110;-1:-1:-1;30337:51:110;;-1:-1:-1;30337:51:110;30280:695;30426:22;30409:13;:39;;;;;;;;;30405:570;;;30527:28;;;;30464:33;30500:56;;;:26;;;:56;;;;;;30597:120;;30662:41;;:11;:41::i;30597:120::-;30731:32;;;;;;;;;-1:-1:-1;30731:32:110;;30739:4;;-1:-1:-1;30570:147:110;;-1:-1:-1;30731:32:110;-1:-1:-1;30731:32:110;;-1:-1:-1;;;;;;30731:32:110;30405:570;30801:20;30784:13;:37;;;;;;;;;30780:195;;;-1:-1:-1;;30837:50:110;;;;;;;;;;;;;;;;;30845:5;;-1:-1:-1;30845:5:110;;-1:-1:-1;30837:50:110;-1:-1:-1;30837:50:110;;-1:-1:-1;30837:50:110;30780:195;-1:-1:-1;;30918:46:110;;;;;;;;;;;;;;;;;30926:5;;-1:-1:-1;30926:5:110;;-1:-1:-1;30918:46:110;-1:-1:-1;30918:46:110;;-1:-1:-1;30918:46:110;29832:1149;;;;;;:::o;2119:459:89:-;2177:7;2418:6;2414:45;;-1:-1:-1;2447:1:89;2440:8;;2414:45;2481:5;;;2485:1;2481;:5;:1;2504:5;;;;;:10;2496:56;;;;-1:-1:-1;;;2496:56:89;;;;;;;;3033:130;3091:7;3117:39;3121:1;3124;3117:39;;;;;;;;;;;;;;;;;:3;:39::i;33229:793:110:-;33289:26;;:::i;:::-;33327:18;33348:15;;;:6;:15;;;;;:26;33388:15;33384:159;;-1:-1:-1;;33503:29:110;;;;;;;;;-1:-1:-1;;33503:29:110;;33496:36;;33384:159;33730:44;;:::i;:::-;33777:58;;;;;;;;;;33797:11;;-1:-1:-1;;;33797:37:110;;;33777:58;;;-1:-1:-1;;;;;33797:11:110;:25;:37;33823:10;33797:37;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;33797:37:110;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;33797:37:110;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;33797:37:110;;;;;;;;;33777:58;;33985:15;;;;:6;:15;;;;;;;;;33963:52;;;;;;;;33985:29;;33963:52;;;33730:105;;-1:-1:-1;33963:52:110;;33730:105;;33963:52;:21;:52;:::i;2509:699:84:-;2646:15;2663:12;2691:40;;:::i;:::-;2734;2770:3;2734:31;2762:2;2734:27;:31::i;:::-;:35;:40;:35;:40;:::i;:::-;2802:29;;;;;;;;;:15;;;:29;;;2691:83;;-1:-1:-1;2802:47:84;;2832:16;2802:47;:29;:47;:::i;:::-;:149;;;;-1:-1:-1;2865:57:84;;;;;;;;;2906:15;;;2865:57;;;2884:16;;;;-1:-1:-1;2865:36:84;;;;;;;;;:40;;;;;;;;;;;;:86;;2937:13;;2865:57;;:40;:57;:40;:57;:::i;:::-;:71;:86;:71;:86;:::i;:::-;2785:417;;;3100:4;3087:17;;3126:4;:16;;;3118:24;;2785:417;;;3186:5;3173:18;;2785:417;2509:699;;;;;;:::o;695:135:40:-;755:15;;:::i;:::-;789:34;;;;;;;;;;798:24;:1;409:6;798:24;:5;:24;:::i;:::-;789:34;;782:41;695:135;-1:-1:-1;;695:135:40:o;4420:128:89:-;4478:7;4504:37;4508:1;4511;4504:37;;;;;;;;;;;;;;;;;:3;:37::i;1757:259:108:-;1845:7;;1886:75;1915:44;1907:53;;1886:75;1864:97;-1:-1:-1;1978:31:108;1994:14;:7;2006:1;1994:14;:11;:14;:::i;:::-;1978:11;;:31;:15;:31;:::i;1605:137:40:-;1725:10;1712;;:23;;1605:137::o;3638:338:89:-;3724:7;3824:12;3817:5;3809:28;;;;-1:-1:-1;;;3809:28:89;;;;;;;;;;;3847:9;3863:1;3859;:5;;;;;;;3638:338;-1:-1:-1;;;;;3638:338:89:o;11197:134:40:-;11263:15;;:::i;:::-;11297:27;;;;;;;;;11306:10;;11297:27;;11306:17;;11321:1;11306:17;:14;:17;:::i;5012:163:89:-;5098:7;5133:12;5125:6;5117:29;;;;-1:-1:-1;;;5117:29:89;;;;;;;;;;;5167:1;5163;:5;;;;;;;5012:163;-1:-1:-1;;;;5012:163:89:o;578:34602:110:-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;578:34602:110;;;;;;;;:::o;766:806:-1:-;;916:3;909:4;901:6;897:17;893:27;883:2;;-1:-1;;924:12;883:2;971:6;958:20;43069:18;43061:6;43058:30;43055:2;;;-1:-1;;43091:12;43055:2;43136:4;993:113;43136:4;;43128:6;43124:17;43189:15;993:113;;;1134:21;;;984:122;-1:-1;1191:14;;;1166:17;;;1292:4;1280:17;;;1271:27;;;;1268:36;-1:-1;1265:2;;;1317:1;;1307:12;1265:2;1342:1;1327:239;1352:6;1349:1;1346:13;1327:239;;;1432:70;1498:3;1486:10;1432:70;;;1420:83;;1517:14;;;;1545;;;;1374:1;1367:9;1327:239;;;1331:14;;;;;;876:696;;;;;2907:481;;3029:4;3017:9;3012:3;3008:19;3004:30;3001:2;;;-1:-1;;3037:12;3001:2;3065:20;3029:4;3065:20;;;3056:29;;2222:6;2209:20;3155:16;3148:75;3284:2;3342:9;3338:22;3830:20;3284:2;3303:5;3299:16;3292:75;2995:393;;;;;4041:241;;4145:2;4133:9;4124:7;4120:23;4116:32;4113:2;;;-1:-1;;4151:12;4113:2;85:6;72:20;97:33;124:5;97:33;;4289:263;;4404:2;4392:9;4383:7;4379:23;4375:32;4372:2;;;-1:-1;;4410:12;4372:2;226:6;220:13;238:33;265:5;238:33;;4559:693;;;;4755:2;4743:9;4734:7;4730:23;4726:32;4723:2;;;-1:-1;;4761:12;4723:2;85:6;72:20;97:33;124:5;97:33;;;4813:63;-1:-1;4913:2;4952:22;;3830:20;;-1:-1;5049:2;5034:18;;5021:32;5073:18;5062:30;;5059:2;;;-1:-1;;5095:12;5059:2;5125:111;5228:7;5219:6;5208:9;5204:22;5125:111;;;5115:121;;;4717:535;;;;;;5259:459;;;5429:2;5417:9;5408:7;5404:23;5400:32;5397:2;;;-1:-1;;5435:12;5397:2;5493:17;5480:31;5531:18;;5523:6;5520:30;5517:2;;;-1:-1;;5553:12;5517:2;5685:6;5674:9;5670:22;488:3;481:4;473:6;469:17;465:27;455:2;;-1:-1;;496:12;455:2;539:6;526:20;516:30;;5531:18;558:6;555:30;552:2;;;-1:-1;;588:12;552:2;683:3;5429:2;;667:6;663:17;624:6;649:32;;646:41;643:2;;;-1:-1;;690:12;643:2;5429;620:17;;5581:121;;-1:-1;5391:327;;-1:-1;;;;5391:327;5725:443;;5887:2;5875:9;5866:7;5862:23;5858:32;5855:2;;;-1:-1;;5893:12;5855:2;5951:17;5938:31;5989:18;5981:6;5978:30;5975:2;;;-1:-1;;6011:12;5975:2;6041:111;6144:7;6135:6;6124:9;6120:22;6041:111;;6175:451;;;6341:2;6329:9;6320:7;6316:23;6312:32;6309:2;;;-1:-1;;6347:12;6309:2;6405:17;6392:31;6443:18;;6435:6;6432:30;6429:2;;;-1:-1;;6465:12;6429:2;6593:6;6582:9;6578:22;1777:3;1770:4;1762:6;1758:17;1754:27;1744:2;;-1:-1;;1785:12;1744:2;1828:6;1815:20;1805:30;;6443:18;1847:6;1844:30;1841:2;;;-1:-1;;1877:12;1841:2;1972:3;6341:2;1964:4;1956:6;1952:17;1913:6;1938:32;;1935:41;1932:2;;;-1:-1;;1979:12;6633:257;;6745:2;6733:9;6724:7;6720:23;6716:32;6713:2;;;-1:-1;;6751:12;6713:2;2088:6;2082:13;49170:5;45883:13;45876:21;49148:5;49145:32;49135:2;;-1:-1;;49181:12;6897:366;;;7018:2;7006:9;6997:7;6993:23;6989:32;6986:2;;;-1:-1;;7024:12;6986:2;-1:-1;;2209:20;;;7176:2;7215:22;;;3830:20;;-1:-1;6980:283;7270:491;;;;7408:2;7396:9;7387:7;7383:23;7379:32;7376:2;;;-1:-1;;7414:12;7376:2;-1:-1;;2209:20;;;7566:2;7605:22;;3830:20;;-1:-1;7674:2;7713:22;;;2209:20;;7370:391;-1:-1;7370:391;7768:721;;;;;7932:3;7920:9;7911:7;7907:23;7903:33;7900:2;;;-1:-1;;7939:12;7900:2;2222:6;2209:20;7991:63;;8091:2;8134:9;8130:22;3830:20;8099:63;;8199:2;8242:9;8238:22;2209:20;8207:63;;8335:2;8324:9;8320:18;8307:32;8359:18;;8351:6;8348:30;8345:2;;;-1:-1;;8381:12;8345:2;8456:6;8445:9;8441:22;2381:3;2374:4;2366:6;2362:17;2358:27;2348:2;;-1:-1;;2389:12;2348:2;2436:6;2423:20;2409:34;;8359:18;43356:6;43353:30;43350:2;;;-1:-1;;43386:12;43350:2;2458:64;43459:9;43440:17;;-1:-1;;43436:33;8091:2;43517:15;2458:64;;;2449:73;;2542:6;2535:5;2528:21;2646:3;8091:2;2637:6;2570;2628:16;;2625:25;2622:2;;;-1:-1;;2653:12;2622:2;2673:41;2707:6;8091:2;2604:5;2600:16;8091:2;2570:6;2566:17;2673:41;;;-1:-1;7894:595;;;;-1:-1;7894:595;;-1:-1;;;7894:595;8496:613;;;;;8649:3;8637:9;8628:7;8624:23;8620:33;8617:2;;;-1:-1;;8656:12;8617:2;-1:-1;;2209:20;;;8808:2;8847:22;;3830:20;;-1:-1;8916:2;8954:22;;2794:20;;9023:2;9061:22;2794:20;;-1:-1;8611:498;-1:-1;8611:498;9116:293;;9246:2;9234:9;9225:7;9221:23;9217:32;9214:2;;;-1:-1;;9252:12;9214:2;3579:20;9246:2;3579:20;;;3830;;3660:75;;-1:-1;3667:16;9208:201;-1:-1;9208:201;9416:241;;9520:2;9508:9;9499:7;9495:23;9491:32;9488:2;;;-1:-1;;9526:12;9488:2;-1:-1;3830:20;;9482:175;-1:-1;9482:175;9664:263;;9779:2;9767:9;9758:7;9754:23;9750:32;9747:2;;;-1:-1;;9785:12;9747:2;-1:-1;3978:13;;9741:186;-1:-1;9741:186;13582:343;;13724:5;44065:12;44996:6;44991:3;44984:19;-1:-1;47880:101;47894:6;47891:1;47888:13;47880:101;;;45033:4;47961:11;;;;;47955:18;47942:11;;;;;47935:39;47909:10;47880:101;;;47996:6;47993:1;47990:13;47987:2;;;-1:-1;45033:4;48052:6;45028:3;48043:16;;48036:27;47987:2;-1:-1;43459:9;48600:14;-1:-1;;48596:28;13881:39;;;;45033:4;13881:39;;13672:253;-1:-1;;13672:253;24622:963;13254:37;;;24988:2;24979:12;;13254:37;;;;48711:2;48707:14;;;;-1:-1;;48707:14;25088:12;;;10808:74;25215:12;;;13254:37;25326:12;;;13254:37;25437:12;;;13254:37;25548:12;;;24881:704;25592:213;-1:-1;;;;;46414:54;;;;10965:37;;25710:2;25695:18;;25681:124;26048:340;-1:-1;;;;;46414:54;;;;10633:58;;26374:2;26359:18;;13254:37;26202:2;26187:18;;26173:215;26726:493;26960:2;26974:47;;;44065:12;;26945:18;;;44984:19;;;26726:493;;26960:2;45024:14;;;;;;43697;;;26726:493;11678:359;11703:6;11700:1;11697:13;11678:359;;;11764:13;;22983:23;;13254:37;;23143:16;;23137:23;23214:14;;;13254:37;10220:14;;;;44660;;;;11725:1;11718:9;11678:359;;;-1:-1;27027:182;;26931:288;-1:-1;;;;;;;26931:288;27226:485;27456:2;27470:47;;;44065:12;;27441:18;;;44984:19;;;27226:485;;27456:2;45024:14;;;;;;43697;;;27226:485;12699:353;12724:6;12721:1;12718:13;12699:353;;;12791:6;12785:13;23539:16;23533:23;48936:1;48929:5;48926:12;48916:2;;48942:9;48916:2;14336:67;;23721:16;;23715:23;23792:14;;;13254:37;10526:14;;;;44660;;;;12746:1;12739:9;12699:353;;27718:201;45883:13;;45876:21;13147:34;;27830:2;27815:18;;27801:118;27926:213;13254:37;;;28044:2;28029:18;;28015:124;28146:324;13254:37;;;28456:2;28441:18;;13254:37;28292:2;28277:18;;28263:207;28739:231;28866:2;28851:18;;48819:1;48809:12;;48799:2;;48825:9;48799:2;14187:59;;;28837:133;;29193:301;;29331:2;29352:17;29345:47;29406:78;29331:2;29320:9;29316:18;29470:6;29406:78;;29501:407;29692:2;29706:47;;;15415:2;29677:18;;;44984:19;15451:30;45024:14;;;15431:51;15501:12;;;29663:245;29915:407;30106:2;30120:47;;;15752:2;30091:18;;;44984:19;15788:34;45024:14;;;15768:55;-1:-1;;;15843:12;;;15836:30;15885:12;;;30077:245;30329:407;30520:2;30534:47;;;16136:2;30505:18;;;44984:19;16172:29;45024:14;;;16152:50;16221:12;;;30491:245;30743:407;30934:2;30948:47;;;16472:2;30919:18;;;44984:19;16508:31;45024:14;;;16488:52;16559:12;;;30905:245;31157:407;31348:2;31362:47;;;16810:2;31333:18;;;44984:19;16846:29;45024:14;;;16826:50;16895:12;;;31319:245;31571:407;31762:2;31776:47;;;17146:2;31747:18;;;44984:19;17182:17;45024:14;;;17162:38;17219:12;;;31733:245;31985:407;32176:2;32190:47;;;17470:2;32161:18;;;44984:19;17506:32;45024:14;;;17486:53;17558:12;;;32147:245;32399:407;32590:2;32604:47;;;17809:2;32575:18;;;44984:19;17845:34;45024:14;;;17825:55;-1:-1;;;17900:12;;;17893:25;17937:12;;;32561:245;32813:407;33004:2;33018:47;;;32989:18;;;44984:19;18224:34;45024:14;;;18204:55;18278:12;;;32975:245;33227:407;33418:2;33432:47;;;18529:2;33403:18;;;44984:19;18565:32;45024:14;;;18545:53;18617:12;;;33389:245;33641:407;33832:2;33846:47;;;18868:2;33817:18;;;44984:19;18904:30;45024:14;;;18884:51;18954:12;;;33803:245;34055:407;34246:2;34260:47;;;19205:2;34231:18;;;44984:19;19241:23;45024:14;;;19221:44;19284:12;;;34217:245;34469:407;34660:2;34674:47;;;19535:2;34645:18;;;44984:19;19571:21;45024:14;;;19551:42;19612:12;;;34631:245;34883:407;35074:2;35088:47;;;19863:2;35059:18;;;44984:19;19899:26;45024:14;;;19879:47;19945:12;;;35045:245;35297:407;35488:2;35502:47;;;20196:2;35473:18;;;44984:19;20232:31;45024:14;;;20212:52;20283:12;;;35459:245;35711:407;35902:2;35916:47;;;35887:18;;;44984:19;20570:34;45024:14;;;20550:55;20624:12;;;35873:245;36125:407;36316:2;36330:47;;;20875:2;36301:18;;;44984:19;20911:27;45024:14;;;20891:48;20958:12;;;36287:245;36539:407;36730:2;36744:47;;;21209:2;36715:18;;;44984:19;21245:31;45024:14;;;21225:52;21296:12;;;36701:245;36953:407;37144:2;37158:47;;;21547:2;37129:18;;;44984:19;21583:32;45024:14;;;21563:53;21635:12;;;37115:245;37367:407;37558:2;37572:47;;;21886:2;37543:18;;;44984:19;21922:31;45024:14;;;21902:52;21973:12;;;37529:245;37781:407;37972:2;37986:47;;;22224:2;37957:18;;;44984:19;22260:31;45024:14;;;22240:52;22311:12;;;37943:245;38195:407;38386:2;38400:47;;;22562:2;38371:18;;;44984:19;22598:33;45024:14;;;22578:54;22651:12;;;38357:245;38609:317;24113:23;;13254:37;;38779:2;38764:18;;38750:176;39153:408;;13284:5;13261:3;13254:37;39317:2;39435;39424:9;39420:18;39413:48;39475:76;39317:2;39306:9;39302:18;39537:6;39475:76;;39895:431;13254:37;;;40229:2;40214:18;;13254:37;;;;40312:2;40297:18;;13254:37;40067:2;40052:18;;40038:288;40680:755;13254:37;;;24113:23;;41203:2;41188:18;;13254:37;24113:23;41338:2;41323:18;;13254:37;41421:2;41406:18;;13254:37;40986:3;40971:19;;40957:478;41773:506;;;41908:11;41895:25;41959:48;;41983:8;41967:14;41963:29;41959:48;41939:18;41935:73;41925:2;;-1:-1;;42012:12;41925:2;42053:18;42043:8;42039:33;42106:4;42093:18;42083:28;;42131:18;42123:6;42120:30;42117:2;;;-1:-1;;42153:12;42117:2;41998:4;42181:13;;-1:-1;;41967:14;42213:38;;;42203:49;;42200:2;;;42265:1;;42255:12;42200:2;41863:416;;;;;;42286:321;;42433:11;42420:25;42484:48;;42508:8;42492:14;42488:29;42484:48;42464:18;42460:73;42450:2;;-1:-1;;42537:12;42450:2;42564:33;;;;;42388:219;-1:-1;;42388:219;42614:256;42676:2;42670:9;42702:17;;;42777:18;42762:34;;42798:22;;;42759:62;42756:2;;;42834:1;;42824:12;42756:2;42676;42843:22;42654:216;;-1:-1;42654:216;47654:145;47735:6;47730:3;47725;47712:30;-1:-1;47791:1;47773:16;;47766:27;47705:94;48965:117;-1:-1;;;;;49052:5;46414:54;49027:5;49024:35;49014:2;;49073:1;;49063:12;49014:2;49008:74;;;590:1:108;576:11;:15;568:24;;12:1:-1;9;2:12;568:24:108;602:30;;401:238::o;4804:152:40:-;4884:4;4921:19;4938:1;4921:16;:19::i;:::-;:28;4907:10;;:42;;;-1:-1:-1;4804:152:40;;;;:::o

Swarm Source

ipfs://894082513f5f7034400c32948565d69048f772378ce7f5199fff61a8ce4950cf

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.