Contract 0x68AF80376Bc1CA0C25a83b28e5570E8c7bdD3119

 

Contract Overview

Livepeer: Target Bonding Votes
Balance:
0 ETH

ETH Value:
$0.00
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x1ee7af1ace0108ed9e85ce3c638641ab533da8f282fc40c241c600408c170f340x608060401403724832023-10-13 21:37:56132 days 5 hrs agoLivepeer: Delta Deployer IN  Create: BondingVotes0 ETH0.00086494 0.1
[ Download CSV Export 

OVERVIEW

Implementation for the BondingVotes proxied contract in the protocol. 2nd version of it on Arbitrum mainnet.

Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BondingVotes

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 24 : BondingVotes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/utils/Arrays.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";

import "./libraries/EarningsPool.sol";
import "./libraries/EarningsPoolLIP36.sol";
import "./libraries/SortedArrays.sol";

import "../ManagerProxyTarget.sol";
import "./IBondingVotes.sol";
import "./IBondingManager.sol";
import "../rounds/IRoundsManager.sol";

/**
 * @title BondingVotes
 * @dev Checkpointing logic for BondingManager state for historical stake calculations.
 */
contract BondingVotes is ManagerProxyTarget, IBondingVotes {
    using Arrays for uint256[];
    using SortedArrays for uint256[];

    struct BondingCheckpoint {
        /**
         * @dev The amount of bonded tokens to another delegate as of the lastClaimRound.
         */
        uint256 bondedAmount;
        /**
         * @dev The address of the delegate the account is bonded to. In case of transcoders this is their own address.
         */
        address delegateAddress;
        /**
         * @dev The amount of tokens delegated from delegators to this account. This is only set for transcoders, which
         * have to self-delegate first and then have tokens bonded from other delegators.
         */
        uint256 delegatedAmount;
        /**
         * @dev The last round during which the delegator claimed its earnings. This pegs the value of bondedAmount for
         * rewards calculation in {EarningsPoolLIP36-delegatorCumulativeStakeAndFees}.
         */
        uint256 lastClaimRound;
        /**
         * @dev The last round during which the checkpointed account called {BondingManager-reward}. This is needed to
         * when calculating pending rewards for a delegator to this transcoder, to find the last earning pool available
         * for a given round. In that case we start from the delegator checkpoint and then fetch its delegate address
         * checkpoint as well to find the last earning pool.
         *
         * Notice that this is the only field that comes from the Transcoder struct in BondingManager, not Delegator.
         */
        uint256 lastRewardRound;
    }

    /**
     * @dev Stores a list of checkpoints for an account, queryable and mapped by start round. To access the checkpoint
     * for a given round, find the checkpoint with the highest start round that is lower or equal to the queried round
     * ({SortedArrays-findLowerBound}) and then fetch the specific checkpoint on the data mapping.
     */
    struct BondingCheckpointsByRound {
        uint256[] startRounds;
        mapping(uint256 => BondingCheckpoint) data;
    }

    /**
     * @dev Stores a list of checkpoints for the total active stake, queryable and mapped by round. Notice that
     * differently from bonding checkpoints, it's only accessible on the specific round. To access the checkpoint for a
     * given round, look for the checkpoint in the {data}} and if it's zero ensure the round was actually checkpointed on
     * the {rounds} array ({SortedArrays-findLowerBound}).
     */
    struct TotalActiveStakeByRound {
        uint256[] rounds;
        mapping(uint256 => uint256) data;
    }

    /**
     * @dev Checkpoints by account (delegators and transcoders).
     */
    mapping(address => BondingCheckpointsByRound) private bondingCheckpoints;
    /**
     * @dev Total active stake checkpoints.
     */
    TotalActiveStakeByRound private totalStakeCheckpoints;

    /**
     * @dev Modifier to ensure the sender is BondingManager
     */
    modifier onlyBondingManager() {
        _onlyBondingManager();
        _;
    }

    /**
     * @dev Ensures that the provided round is in the past.
     */
    modifier onlyPastRounds(uint256 _round) {
        uint256 currentRound = clock();
        if (_round >= currentRound) {
            revert FutureLookup(_round, currentRound == 0 ? 0 : currentRound - 1);
        }
        _;
    }

    /**
     * @notice BondingVotes constructor. Only invokes constructor of base Manager contract with provided Controller address
     * @param _controller Address of Controller that this contract will be registered with
     */
    constructor(address _controller) Manager(_controller) {}

    // IVotes interface implementation.
    // These should not access any storage directly but proxy to the historical stake functions below.

    /**
     * @notice Returns the name of the virtual token implemented by this.
     */
    function name() external pure returns (string memory) {
        return "Livepeer Voting Power";
    }

    /**
     * @notice Returns the symbol of the token underlying the voting power.
     */
    function symbol() external pure returns (string memory) {
        return "vLPT";
    }

    /**
     * @notice Returns the decimals places of the token underlying the voting.
     */
    function decimals() external pure returns (uint8) {
        return 18;
    }

    /**
     * @notice Clock is set to match the current round, which is the checkpointing
     *  method implemented here.
     */
    function clock() public view returns (uint48) {
        return SafeCast.toUint48(roundsManager().currentRound());
    }

    /**
     * @notice Machine-readable description of the clock as specified in EIP-6372.
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() external pure returns (string memory) {
        return "mode=livepeer_round";
    }

    /**
     * @notice Returns the current amount of votes that `_account` has.
     *
     * The voting power for a delegator is the amount they are delegating to a transcoder, while for transcoders it is
     * all the stake delegated to them. If an account is not a registered transcoder
     * ({BondingManager-isRegisteredTranscoder}), the voting power of itself and of all its delegators will be zero.
     */
    function getVotes(address _account) external view returns (uint256) {
        (uint256 votes, ) = getVotesAndDelegateAtRoundStart(_account, clock() + 1);
        return votes;
    }

    /**
     * @notice Returns the amount of votes that `_account` had at the end of the provided past `_round`.
     */
    function getPastVotes(address _account, uint256 _round) external view onlyPastRounds(_round) returns (uint256) {
        (uint256 votes, ) = getVotesAndDelegateAtRoundStart(_account, _round + 1);
        return votes;
    }

    /**
     * @notice Returns the current total supply of votes available.
     * @dev This value is the sum of all *active* stake, which is not necessarily the sum of all voting power.
     * Bonded stake that is not part of the top 100 active transcoder set is still given voting power, but is not
     * considered here.
     */
    function totalSupply() external view returns (uint256) {
        return getTotalActiveStakeAt(clock() + 1);
    }

    /**
     * @notice Returns the total supply of votes available at the end of the provided past `_round`.
     * @dev This value is the sum of all *active* stake, which is not necessarily the sum of all voting power.
     * Bonded stake that is not part of the top 100 active transcoder set is still given voting power, but is not
     * considered here.
     */
    function getPastTotalSupply(uint256 _round) external view onlyPastRounds(_round) returns (uint256) {
        return getTotalActiveStakeAt(_round + 1);
    }

    /**
     * @notice Returns the delegate that _account has chosen. This means the delegated transcoder address in case of
     * delegators, and the account's own address for transcoders (self-delegated).
     */
    function delegates(address _account) external view returns (address) {
        (, address delegateAddress) = getVotesAndDelegateAtRoundStart(_account, clock() + 1);
        return delegateAddress;
    }

    /**
     * @notice Returns the delegate that _account had chosen at the end of the provided past `_round`.
     * @dev This is an addition to the IERC5805 interface to support our custom vote counting logic that allows
     * delegators to override their transcoders votes. See {GovernorCountingOverridable-_handleVoteOverrides}.
     */
    function delegatedAt(address _account, uint256 _round) external view onlyPastRounds(_round) returns (address) {
        (, address delegateAddress) = getVotesAndDelegateAtRoundStart(_account, _round + 1);
        return delegateAddress;
    }

    /**
     * @notice Delegation through BondingVotes is not supported.
     */
    function delegate(address) external pure {
        revert MustCallBondingManager("bond");
    }

    /**
     * @notice Delegation through BondingVotes is not supported.
     */
    function delegateBySig(
        address,
        uint256,
        uint256,
        uint8,
        bytes32,
        bytes32
    ) external pure {
        revert MustCallBondingManager("bondFor");
    }

    // BondingManager checkpointing hooks

    /**
     * @notice Called by the BondingManager when the bonding state of an account changes.
     * @dev Since we checkpoint "delegator" and "transcoder" states, this is called both for the delegator and for the
     * transcoder when any change is made to the bonds, including when rewards are calculated or claimed.
     * @param _account The account whose bonding state changed
     * @param _startRound The round from which the bonding state will be active. This is normally the next round.
     * @param _bondedAmount From {BondingManager-Delegator-bondedAmount}
     * @param _delegateAddress From {BondingManager-Delegator-delegateAddress}
     * @param _delegatedAmount From {BondingManager-Transcoder-delegatedAmount}
     * @param _lastClaimRound From {BondingManager-Delegator-lastClaimRound}
     * @param _lastRewardRound From {BondingManager-Transcoder-lastRewardRound}
     */
    function checkpointBondingState(
        address _account,
        uint256 _startRound,
        uint256 _bondedAmount,
        address _delegateAddress,
        uint256 _delegatedAmount,
        uint256 _lastClaimRound,
        uint256 _lastRewardRound
    ) external virtual onlyBondingManager {
        if (_startRound != clock() + 1) {
            revert InvalidStartRound(_startRound, clock() + 1);
        } else if (_lastClaimRound >= _startRound) {
            revert FutureLastClaimRound(_lastClaimRound, _startRound - 1);
        }

        BondingCheckpoint memory previous;
        if (hasCheckpoint(_account)) {
            previous = getBondingCheckpointAt(_account, _startRound);
        }

        BondingCheckpointsByRound storage checkpoints = bondingCheckpoints[_account];

        BondingCheckpoint memory bond = BondingCheckpoint({
            bondedAmount: _bondedAmount,
            delegateAddress: _delegateAddress,
            delegatedAmount: _delegatedAmount,
            lastClaimRound: _lastClaimRound,
            lastRewardRound: _lastRewardRound
        });
        checkpoints.data[_startRound] = bond;

        // now store the startRound itself in the startRounds array to allow us
        // to find it and lookup in the above mapping
        checkpoints.startRounds.pushSorted(_startRound);

        onBondingCheckpointChanged(_account, previous, bond);
    }

    /**
     * @notice Called by the BondingManager when the total active stake changes.
     * @dev This is called only from the {BondingManager-setCurrentRoundTotalActiveStake} function to set the total
     * active stake in the current round.
     * @param _totalStake From {BondingManager-currentRoundTotalActiveStake}
     * @param _round The round for which the total active stake is valid. This is normally the current round.
     */
    function checkpointTotalActiveStake(uint256 _totalStake, uint256 _round) external virtual onlyBondingManager {
        if (_round != clock()) {
            revert InvalidTotalStakeCheckpointRound(_round, clock());
        }

        totalStakeCheckpoints.data[_round] = _totalStake;
        totalStakeCheckpoints.rounds.pushSorted(_round);
    }

    /**
     * @notice Returns whether an account already has any checkpoint.
     */
    function hasCheckpoint(address _account) public view returns (bool) {
        return bondingCheckpoints[_account].startRounds.length > 0;
    }

    // Historical stake access functions

    /**
     * @notice Get the total active stake at the start of a given round.
     *
     * Notice that this function is different from the {IERC5805Upgradeable} functions above that return the state at
     * the *end* of the round. The state at the end of a round is equal to the state at the start of the next round, so
     * to get the same result here, call this function with `round+1` instead.
     * @param _round The round for which we want to get the total active stake.
     */
    function getTotalActiveStakeAt(uint256 _round) public view virtual returns (uint256) {
        if (_round > clock() + 1) {
            revert FutureLookup(_round, clock() + 1);
        }

        uint256 exactCheckpoint = totalStakeCheckpoints.data[_round];
        if (exactCheckpoint > 0) {
            return exactCheckpoint;
        }

        uint256[] storage initializedRounds = totalStakeCheckpoints.rounds;
        uint256 upper = initializedRounds.findUpperBound(_round);
        if (upper == 0) {
            // Return a zero voting power supply for any round before the first checkpoint. This also happens if there
            // are no checkpoints at all.
            return 0;
        } else if (upper < initializedRounds.length) {
            // Use the checkpoint from the next initialized round, which got the next total active stake checkpointed.
            uint256 nextInitedRound = initializedRounds[upper];
            return totalStakeCheckpoints.data[nextInitedRound];
        } else {
            // Here the _round is after any initialized round, so grab its stake from nextRoundTotalActiveStake()
            return bondingManager().nextRoundTotalActiveStake();
        }
    }

    /**
     * @notice Gets the voting power and delegate of an account at the start of a given round.
     *
     * Notice that this function is different from the {IERC5805Upgradeable} functions above that return the state at
     * the *end* of the round. The state at the end of a round is equal to the state at the start of the next round, so
     * to get the same result here, call this function with `round+1` instead.
     * @dev The value returned by this can also be calculated with the following logic using BondingManager functions at
     * the start of the corresponding round:
     * - If `isRegisteredTranscoder(_account)`, the result is `(transcoderTotalStake(_account), _account)`
     * - Otherwise, the `delegate` is obtained from `getDelegator(_account).delegateAddress`
     *  - If `isRegisteredTranscoder(delegate)`, the result is `(pendingStake(_account, 0), delegate)`
     *  - Otherwise, the result is `(0, delegate)`
     * @param _account The account to get the voting power and delegate from.
     * @param _round The round at which to get the account state (at round start).
     * @return votes The voting power of the account at the start of the given round.
     * @return delegateAddress The address the account delegated to at the start of the given round.
     */
    function getVotesAndDelegateAtRoundStart(address _account, uint256 _round)
        public
        view
        virtual
        returns (uint256 votes, address delegateAddress)
    {
        BondingCheckpoint storage bond = getBondingCheckpointAt(_account, _round);

        delegateAddress = bond.delegateAddress;

        if (bond.bondedAmount == 0) {
            votes = 0;
        } else if (isRegisteredTranscoder(_account, bond)) {
            // Address is a registered transcoder so we use its delegated amount. This includes self and delegated stake
            // as well as any accrued rewards, even unclaimed ones
            votes = bond.delegatedAmount;
        } else {
            // Address is NOT a registered transcoder so we calculate its cumulative stake for the voting power
            votes = delegatorVotesAtRoundStart(bond, _round);
        }
    }

    /**
     * @dev Reacts to changes in the bonding checkpoints of an account by emitting the corresponding events.
     */
    function onBondingCheckpointChanged(
        address _account,
        BondingCheckpoint memory previous,
        BondingCheckpoint memory current
    ) internal {
        address previousDelegate = previous.delegateAddress;
        address newDelegate = current.delegateAddress;
        if (previousDelegate != newDelegate) {
            emit DelegateChanged(_account, previousDelegate, newDelegate);
        }

        // same logic as {isRegisteredTranscoder} with the memory BondingCheckpoints
        bool isTranscoder = newDelegate == _account && current.bondedAmount > 0;
        bool wasTranscoder = previousDelegate == _account && previous.bondedAmount > 0;
        // we want to register zero "delegate votes" when the account is/was not a transcoder
        uint256 previousDelegateVotes = wasTranscoder ? previous.delegatedAmount : 0;
        uint256 currentDelegateVotes = isTranscoder ? current.delegatedAmount : 0;
        if (previousDelegateVotes != currentDelegateVotes) {
            emit DelegateVotesChanged(_account, previousDelegateVotes, currentDelegateVotes);
        }

        // Always send delegator events since transcoders are delegators themselves. The way our rewards work, the
        // delegator voting power calculated from events will only reflect their claimed stake without pending rewards.
        if (previous.bondedAmount != current.bondedAmount || previous.lastClaimRound != current.lastClaimRound) {
            emit DelegatorBondedAmountChanged(
                _account,
                previous.bondedAmount,
                previous.lastClaimRound,
                current.bondedAmount,
                current.lastClaimRound
            );
        }
    }

    /**
     * @dev Gets the checkpointed bonding state of an account at a round. This works by looking for the last checkpoint
     * at or before the given round and using the checkpoint of that round. If there hasn't been checkpoints since then
     * it means that the state hasn't changed.
     * @param _account The account whose bonding state we want to get.
     * @param _round The round for which we want to get the bonding state.
     * @return The {BondingCheckpoint} pointer to the checkpoints storage.
     */
    function getBondingCheckpointAt(address _account, uint256 _round)
        internal
        view
        returns (BondingCheckpoint storage)
    {
        if (_round > clock() + 1) {
            revert FutureLookup(_round, clock() + 1);
        }

        BondingCheckpointsByRound storage checkpoints = bondingCheckpoints[_account];

        // Most of the time we will be calling this for a transcoder which checkpoints on every round through reward().
        // On those cases we will have a checkpoint for exactly the round we want, so optimize for that.
        BondingCheckpoint storage bond = checkpoints.data[_round];
        if (bond.bondedAmount > 0) {
            return bond;
        }

        uint256 startRoundIdx = checkpoints.startRounds.findLowerBound(_round);
        if (startRoundIdx == checkpoints.startRounds.length) {
            // No checkpoint at or before _round, so return the zero BondingCheckpoint value. This also happens if there
            // are no checkpoints for _account. The voting power will be zero until the first checkpoint is made.
            return bond;
        }

        uint256 startRound = checkpoints.startRounds[startRoundIdx];
        return checkpoints.data[startRound];
    }

    /**
     * @dev Gets the voting power of a delegator at the start of the given round. This is done through cumulative
     * rewards calculation on top of the bonding state.
     *
     * Differently from the bonding manager implementation, we can calculate the stake at any round through the use of
     * the checkpointed state. It works by re-using the bonding manager logic while changing only the way that we find
     * the earning pool for the end round.
     * @param bond The {BondingCheckpoint} of the delegator at the given round.
     * @param _round The round at which we want the delegator votes (at round start).
     * @return The cumulative stake of the delegator at the start of the given round.
     */
    function delegatorVotesAtRoundStart(BondingCheckpoint storage bond, uint256 _round)
        internal
        view
        returns (uint256)
    {
        address transcoder = bond.delegateAddress;
        EarningsPool.Data memory startPool = getTranscoderEarningsPoolForRound(transcoder, bond.lastClaimRound);

        (
            BondingCheckpoint storage transcoderBond,
            EarningsPool.Data memory endPool
        ) = getLastTranscoderRewardsEarningsPool(transcoder, _round);

        if (!isRegisteredTranscoder(transcoder, transcoderBond)) {
            // Delegating to an account that is not actually a transcoder should render no voting power.
            return 0;
        }

        if (transcoderBond.lastRewardRound < bond.lastClaimRound) {
            // If the transcoder hasn't called reward() since the last time the delegator claimed earnings, there will
            // be no rewards to add to the delegator's stake so we just return the originally bonded amount.
            return bond.bondedAmount;
        }

        return EarningsPoolLIP36.delegatorCumulativeStake(startPool, endPool, bond.bondedAmount);
    }

    /**
     * @notice Returns the last initialized earning pool for a transcoder at a given round.
     * @dev Transcoders are just delegators with a self-delegation, so we find their last checkpoint before or at the
     * provided _round and use its lastRewardRound value to grab the calculated earning pool. The only case where this
     * returns a zero earning pool is if the transcoder had never called reward() before _round.
     * @param _transcoder Address of the transcoder to look for
     * @param _round Past round at which we want the valid earning pool from
     * @return bond The BondingCheckpoint from the transcoder at the given _round.
     * @return pool EarningsPool.Data struct with the last initialized earning pool.
     */
    function getLastTranscoderRewardsEarningsPool(address _transcoder, uint256 _round)
        internal
        view
        returns (BondingCheckpoint storage bond, EarningsPool.Data memory pool)
    {
        bond = getBondingCheckpointAt(_transcoder, _round);

        uint256 rewardRound = bond.lastRewardRound;
        if (rewardRound > 0) {
            pool = getTranscoderEarningsPoolForRound(_transcoder, rewardRound);

            if (pool.cumulativeRewardFactor == 0) {
                // Invalid state: a lastRewardRound is registered but there's no recorded earnings pool.
                revert MissingEarningsPool(_transcoder, rewardRound);
            }
        }
    }

    /**
     * @dev Proxy for {BondingManager-getTranscoderEarningsPoolForRound} that returns an EarningsPool.Data struct.
     */
    function getTranscoderEarningsPoolForRound(address _transcoder, uint256 _round)
        internal
        view
        returns (EarningsPool.Data memory pool)
    {
        (
            pool.totalStake,
            pool.transcoderRewardCut,
            pool.transcoderFeeShare,
            pool.cumulativeRewardFactor,
            pool.cumulativeFeeFactor
        ) = bondingManager().getTranscoderEarningsPoolForRound(_transcoder, _round);
    }

    /**
     * @dev Returns whether an account should be considered a transcoder at the given checkpoint. The logic matches what
     * is in {BondingManager-isRegisteredTranscoder}.
     */
    function isRegisteredTranscoder(address _account, BondingCheckpoint storage _bond) internal view returns (bool) {
        return _bond.delegateAddress == _account && _bond.bondedAmount > 0;
    }

    // Manager/Controller helpers

    /**
     * @dev Return BondingManager interface
     */
    function bondingManager() internal view returns (IBondingManager) {
        return IBondingManager(controller.getContract(keccak256("BondingManager")));
    }

    /**
     * @dev Return IRoundsManager interface
     */
    function roundsManager() internal view returns (IRoundsManager) {
        return IRoundsManager(controller.getContract(keccak256("RoundsManager")));
    }

    /**
     * @dev Ensure the sender is BondingManager
     */
    function _onlyBondingManager() internal view {
        if (msg.sender != address(bondingManager())) {
            revert InvalidCaller(msg.sender, address(bondingManager()));
        }
    }
}

File 2 of 24 : Arrays.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Arrays.sol)

pragma solidity ^0.8.0;

import "./StorageSlot.sol";
import "./math/Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
    using StorageSlot for bytes32;

    /**
     * @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 (unsafeAccess(array, mid).value > 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 && unsafeAccess(array, low - 1).value == element) {
            return low - 1;
        } else {
            return low;
        }
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getAddressSlot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getBytes32Slot();
    }

    /**
     * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
     *
     * WARNING: Only use if you are certain `pos` is lower than the array length.
     */
    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
        bytes32 slot;
        // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
        // following https://docs.soliditylang.org/en/v0.8.17/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

        /// @solidity memory-safe-assembly
        assembly {
            mstore(0, arr.slot)
            slot := add(keccak256(0, 0x20), pos)
        }
        return slot.getUint256Slot();
    }
}

File 3 of 24 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 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} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @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
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(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
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(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
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(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
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "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
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "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.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 4 of 24 : EarningsPool.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "../../libraries/MathUtils.sol";

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

/**
 * @title EarningsPool
 * @dev Manages reward and fee pools for delegators and transcoders
 */
library EarningsPool {
    using SafeMath for uint256;

    struct Data {
        uint256 totalStake; // Transcoder's total stake during the earnings pool's round
        uint256 transcoderRewardCut; // Transcoder's reward cut during the earnings pool's round
        uint256 transcoderFeeShare; // Transcoder's fee share during the earnings pool's round
        // LIP-36 (https://github.com/livepeer/LIPs/blob/master/LIPs/LIP-36.md) fields
        // See EarningsPoolLIP36.sol
        uint256 cumulativeRewardFactor;
        uint256 cumulativeFeeFactor;
    }

    /**
     * @dev Sets transcoderRewardCut and transcoderFeeshare for an EarningsPool
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _rewardCut Reward cut of transcoder during the earnings pool's round
     * @param _feeShare Fee share of transcoder during the earnings pool's round
     */
    function setCommission(
        EarningsPool.Data storage earningsPool,
        uint256 _rewardCut,
        uint256 _feeShare
    ) internal {
        earningsPool.transcoderRewardCut = _rewardCut;
        earningsPool.transcoderFeeShare = _feeShare;
    }

    /**
     * @dev Sets totalStake for an EarningsPool
     * @param earningsPool Storage pointer to EarningsPool struct
     * @param _stake Total stake of the transcoder during the earnings pool's round
     */
    function setStake(EarningsPool.Data storage earningsPool, uint256 _stake) internal {
        earningsPool.totalStake = _stake;
    }
}

File 5 of 24 : EarningsPoolLIP36.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./EarningsPool.sol";
import "../../libraries/PreciseMathUtils.sol";

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

library EarningsPoolLIP36 {
    using SafeMath for uint256;

    /**
     * @notice Update the cumulative fee factor stored in an earnings pool with new fees
     * @param earningsPool Storage pointer to EarningsPools.Data struct
     * @param _prevEarningsPool In-memory EarningsPool.Data struct that stores the previous cumulative reward and fee factors
     * @param _fees Amount of new fees
     */
    function updateCumulativeFeeFactor(
        EarningsPool.Data storage earningsPool,
        EarningsPool.Data memory _prevEarningsPool,
        uint256 _fees
    ) internal {
        uint256 prevCumulativeFeeFactor = _prevEarningsPool.cumulativeFeeFactor;
        uint256 prevCumulativeRewardFactor = _prevEarningsPool.cumulativeRewardFactor != 0
            ? _prevEarningsPool.cumulativeRewardFactor
            : PreciseMathUtils.percPoints(1, 1);

        // Initialize the cumulativeFeeFactor when adding fees for the first time
        if (earningsPool.cumulativeFeeFactor == 0) {
            earningsPool.cumulativeFeeFactor = prevCumulativeFeeFactor.add(
                PreciseMathUtils.percOf(prevCumulativeRewardFactor, _fees, earningsPool.totalStake)
            );
            return;
        }

        earningsPool.cumulativeFeeFactor = earningsPool.cumulativeFeeFactor.add(
            PreciseMathUtils.percOf(prevCumulativeRewardFactor, _fees, earningsPool.totalStake)
        );
    }

    /**
     * @notice Update the cumulative reward factor stored in an earnings pool with new rewards
     * @param earningsPool Storage pointer to EarningsPool.Data struct
     * @param _prevEarningsPool Storage pointer to EarningsPool.Data struct that stores the previous cumulative reward factor
     * @param _rewards Amount of new rewards
     */
    function updateCumulativeRewardFactor(
        EarningsPool.Data storage earningsPool,
        EarningsPool.Data memory _prevEarningsPool,
        uint256 _rewards
    ) internal {
        uint256 prevCumulativeRewardFactor = _prevEarningsPool.cumulativeRewardFactor != 0
            ? _prevEarningsPool.cumulativeRewardFactor
            : PreciseMathUtils.percPoints(1, 1);

        earningsPool.cumulativeRewardFactor = prevCumulativeRewardFactor.add(
            PreciseMathUtils.percOf(prevCumulativeRewardFactor, _rewards, earningsPool.totalStake)
        );
    }

    /**
     * @notice Calculates a delegator's cumulative stake and fees using the LIP-36 earnings claiming algorithm.
     * @dev This internally calls {delegatorCumulativeStake} and {delegatorCumulativeFees} to calculate stake and fees.
     * @param _startPool The earning pool from the start round for the start cumulative factors. Normally this is the
     * earning pool from the {Delegator-lastClaimRound} round, as the round where `_stake` was measured.
     * @param _endPool The earning pool from the end round for the end cumulative factors
     * @param _stake The delegator stake at the start round, before earned rewards. Normally {Delegator-bondedAmount}.
     * @param _fees The delegator's initial fees before including earned fees
     * @return cStake , cFees where cStake is the delegator's cumulative stake including earned rewards and cFees is the
     * delegator's cumulative fees including earned fees
     */
    function delegatorCumulativeStakeAndFees(
        EarningsPool.Data memory _startPool,
        EarningsPool.Data memory _endPool,
        uint256 _stake,
        uint256 _fees
    ) internal pure returns (uint256 cStake, uint256 cFees) {
        cStake = delegatorCumulativeStake(_startPool, _endPool, _stake);
        cFees = delegatorCumulativeFees(_startPool, _endPool, _stake, _fees);
    }

    /**
     * @notice Calculates a delegator's cumulative stake using the LIP-36 earnings claiming algorithm.
     * @param _startPool The earning pool from the start round for the start cumulative factors. Normally this is the
     * earning pool from the {Delegator-lastClaimRound} round, as the round where `_stake` was measured.
     * @param _endPool The earning pool from the end round for the end cumulative factors.
     * @param _stake The delegator stake at the start round, before earned rewards. Normally {Delegator-bondedAmount}.
     * @return The delegator's cumulative stake including earned rewards.
     */
    function delegatorCumulativeStake(
        EarningsPool.Data memory _startPool,
        EarningsPool.Data memory _endPool,
        uint256 _stake
    ) internal pure returns (uint256) {
        // If the start cumulativeRewardFactor is 0 set the default value to PreciseMathUtils.percPoints(1, 1)
        if (_startPool.cumulativeRewardFactor == 0) {
            _startPool.cumulativeRewardFactor = PreciseMathUtils.percPoints(1, 1);
        }

        // If the end cumulativeRewardFactor is 0 set the default value to PreciseMathUtils.percPoints(1, 1)
        if (_endPool.cumulativeRewardFactor == 0) {
            _endPool.cumulativeRewardFactor = PreciseMathUtils.percPoints(1, 1);
        }

        return PreciseMathUtils.percOf(_stake, _endPool.cumulativeRewardFactor, _startPool.cumulativeRewardFactor);
    }

    /**
     * @notice Calculates a delegator's cumulative fees using the LIP-36 earnings claiming algorithm.
     * @param _startPool The earning pool from the start round for the start cumulative factors. Normally this is the
     * earning pool from the {Delegator-lastClaimRound} round, as the round where `_stake` was measured.
     * @param _endPool The earning pool from the end round for the end cumulative factors.
     * @param _stake The delegator stake at the start round, before earned rewards. Normally {Delegator-bondedAmount}.
     * @param _fees The delegator's initial fees before including earned fees.
     * @return The delegator's cumulative fees including earned fees.
     */
    function delegatorCumulativeFees(
        EarningsPool.Data memory _startPool,
        EarningsPool.Data memory _endPool,
        uint256 _stake,
        uint256 _fees
    ) internal pure returns (uint256) {
        // If the start cumulativeRewardFactor is 0 set the default value to PreciseMathUtils.percPoints(1, 1)
        if (_startPool.cumulativeRewardFactor == 0) {
            _startPool.cumulativeRewardFactor = PreciseMathUtils.percPoints(1, 1);
        }

        uint256 earnedFees = PreciseMathUtils.percOf(
            _stake,
            _endPool.cumulativeFeeFactor.sub(_startPool.cumulativeFeeFactor),
            _startPool.cumulativeRewardFactor
        );
        return _fees.add(earnedFees);
    }
}

File 6 of 24 : SortedArrays.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "../../libraries/MathUtils.sol";

import "@openzeppelin/contracts/utils/Arrays.sol";

/**
 * @title SortedArrays
 * @dev Handles maintaining and looking up on sorted uint256 arrays.
 */
library SortedArrays {
    using Arrays for uint256[];

    error DecreasingValues(uint256 newValue, uint256 lastValue);

    /**
     * @notice Searches a sorted _array and returns the last element to be lower or equal to _val. If there is no such
     * element (all elements in array are higher than the searched element), the array length is returned.
     *
     * @dev This basically converts OpenZeppelin's {Arrays-findUpperBound} into findLowerBound, meaning it also uses a
     * binary search in the worst case after trying some shortcuts. Worst case time complexity is O(log n). The only
     * change being that the returned index points to the element lower or equal to _val, instead of higher or equal.
     * @param _array Array to search in
     * @param _val Value to search for
     * @return lower Index of the lower bound found in array
     */
    function findLowerBound(uint256[] storage _array, uint256 _val) internal view returns (uint256) {
        uint256 len = _array.length;
        if (len == 0) {
            return 0;
        }

        if (_array[len - 1] <= _val) {
            return len - 1;
        }

        uint256 upperIdx = _array.findUpperBound(_val);

        // we already checked the last element above so the upper will always be inside the array
        assert(upperIdx < len);

        // the exact value we were searching is in the array
        if (_array[upperIdx] == _val) {
            return upperIdx;
        }

        // a 0 idx means that the first elem is already higher than the searched value (and not equal, checked above)
        if (upperIdx == 0) {
            return len;
        }

        // the element at upperIdx is the first element higher than the value we want, so return the previous element
        return upperIdx - 1;
    }

    /**
     * @notice Pushes a value into an already sorted array.
     * @dev Values must be pushed in increasing order as to avoid shifting values in the array. This function only
     * guarantees that the pushed value will not create duplicates nor make the array out of order.
     * @param array Array to push the value into
     * @param val Value to push into array. Must be greater than or equal to the highest (last) element.
     */
    function pushSorted(uint256[] storage array, uint256 val) internal {
        if (array.length == 0) {
            array.push(val);
        } else {
            uint256 last = array[array.length - 1];

            // values must be pushed in order
            if (val < last) {
                revert DecreasingValues(val, last);
            }

            // don't push duplicate values
            if (val != last) {
                array.push(val);
            }
        }
    }
}

File 7 of 24 : ManagerProxyTarget.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./Manager.sol";

/**
 * @title ManagerProxyTarget
 * @notice The base contract that target contracts used by a proxy contract should inherit from
 * @dev Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee
 that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can
 potentially break the delegate proxy upgradeability mechanism
 */
abstract contract ManagerProxyTarget is Manager {
    // Used to look up target contract address in controller's registry
    bytes32 public targetContractId;
}

File 8 of 24 : IBondingVotes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "../treasury/IVotes.sol";

/**
 * @title Interface for BondingVotes
 */
interface IBondingVotes is IVotes {
    error InvalidCaller(address caller, address required);
    error InvalidStartRound(uint256 checkpointRound, uint256 requiredRound);
    error FutureLastClaimRound(uint256 lastClaimRound, uint256 maxAllowed);
    error InvalidTotalStakeCheckpointRound(uint256 checkpointRound, uint256 requiredRound);

    error FutureLookup(uint256 queryRound, uint256 maxAllowed);
    error MissingEarningsPool(address transcoder, uint256 round);

    // Indicates that the called function is not supported in this contract and should be performed through the
    // BondingManager instead. This is mostly used for IVotes delegation methods which must be bonds instead.
    error MustCallBondingManager(string bondingManagerFunction);

    /**
     * @dev Emitted when a checkpoint results in changes to a delegator's `bondedAmount`. This complements the events
     * from IERC5805 by also supporting voting power for the delegators themselves, though requiring knowledge about our
     * specific reward-claiming protocol to calculate voting power based on this value.
     */
    event DelegatorBondedAmountChanged(
        address indexed delegate,
        uint256 previousBondedAmount,
        uint256 previousLastClaimRound,
        uint256 newBondedAmount,
        uint256 newLastClaimRound
    );

    // BondingManager hooks

    function checkpointBondingState(
        address _account,
        uint256 _startRound,
        uint256 _bondedAmount,
        address _delegateAddress,
        uint256 _delegatedAmount,
        uint256 _lastClaimRound,
        uint256 _lastRewardRound
    ) external;

    function checkpointTotalActiveStake(uint256 _totalStake, uint256 _round) external;

    // Historical stake access functions

    function hasCheckpoint(address _account) external view returns (bool);

    function getTotalActiveStakeAt(uint256 _round) external view returns (uint256);

    function getVotesAndDelegateAtRoundStart(address _account, uint256 _round)
        external
        view
        returns (uint256 amount, address delegateAddress);
}

File 9 of 24 : IBondingManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

/**
 * @title Interface for BondingManager
 * TODO: switch to interface type
 */
interface IBondingManager {
    event TranscoderUpdate(address indexed transcoder, uint256 rewardCut, uint256 feeShare);
    event TranscoderActivated(address indexed transcoder, uint256 activationRound);
    event TranscoderDeactivated(address indexed transcoder, uint256 deactivationRound);
    event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward);
    event Reward(address indexed transcoder, uint256 amount);
    event TreasuryReward(address indexed transcoder, address treasury, uint256 amount);
    event Bond(
        address indexed newDelegate,
        address indexed oldDelegate,
        address indexed delegator,
        uint256 additionalAmount,
        uint256 bondedAmount
    );
    event Unbond(
        address indexed delegate,
        address indexed delegator,
        uint256 unbondingLockId,
        uint256 amount,
        uint256 withdrawRound
    );
    event Rebond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount);
    event TransferBond(
        address indexed oldDelegator,
        address indexed newDelegator,
        uint256 oldUnbondingLockId,
        uint256 newUnbondingLockId,
        uint256 amount
    );
    event WithdrawStake(address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);
    event WithdrawFees(address indexed delegator, address recipient, uint256 amount);
    event EarningsClaimed(
        address indexed delegate,
        address indexed delegator,
        uint256 rewards,
        uint256 fees,
        uint256 startRound,
        uint256 endRound
    );

    // Deprecated events
    // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding
    // to these deprecated events.
    // event Bond(address indexed delegate, address indexed delegator);
    // event Unbond(address indexed delegate, address indexed delegator);
    // event WithdrawStake(address indexed delegator);
    // event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered);
    // event TranscoderEvicted(address indexed transcoder);
    // event TranscoderResigned(address indexed transcoder);

    // External functions
    function updateTranscoderWithFees(
        address _transcoder,
        uint256 _fees,
        uint256 _round
    ) external;

    function slashTranscoder(
        address _transcoder,
        address _finder,
        uint256 _slashAmount,
        uint256 _finderFee
    ) external;

    function setCurrentRoundTotalActiveStake() external;

    // Public functions
    function getTranscoderPoolSize() external view returns (uint256);

    function transcoderTotalStake(address _transcoder) external view returns (uint256);

    function isActiveTranscoder(address _transcoder) external view returns (bool);

    function getTotalBonded() external view returns (uint256);

    function nextRoundTotalActiveStake() external view returns (uint256);

    function getTranscoderEarningsPoolForRound(address _transcoder, uint256 _round)
        external
        view
        returns (
            uint256 totalStake,
            uint256 transcoderRewardCut,
            uint256 transcoderFeeShare,
            uint256 cumulativeRewardFactor,
            uint256 cumulativeFeeFactor
        );
}

File 10 of 24 : IRoundsManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

/**
 * @title RoundsManager interface
 */
interface IRoundsManager {
    // Events
    event NewRound(uint256 indexed round, bytes32 blockHash);

    // Deprecated events
    // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding
    // to these deprecated events.
    // event NewRound(uint256 round)

    // External functions
    function initializeRound() external;

    function lipUpgradeRound(uint256 _lip) external view returns (uint256);

    // Public functions
    function blockNum() external view returns (uint256);

    function blockHash(uint256 _block) external view returns (bytes32);

    function blockHashForRound(uint256 _round) external view returns (bytes32);

    function currentRound() external view returns (uint256);

    function currentRoundStartBlock() external view returns (uint256);

    function currentRoundInitialized() external view returns (bool);

    function currentRoundLocked() external view returns (bool);
}

File 11 of 24 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 12 of 24 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 13 of 24 : MathUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

library MathUtils {
    using SafeMath for uint256;

    // Divisor used for representing percentages
    uint256 public constant PERC_DIVISOR = 1000000;

    /**
     * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR
     * @param _amount Amount that is supposed to be a percentage
     */
    function validPerc(uint256 _amount) internal pure returns (bool) {
        return _amount <= PERC_DIVISOR;
    }

    /**
     * @dev Compute percentage of a value with the percentage represented by a fraction
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage
     * @param _fracDenom Denominator of fraction representing the percentage
     */
    function percOf(
        uint256 _amount,
        uint256 _fracNum,
        uint256 _fracDenom
    ) internal pure returns (uint256) {
        return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);
    }

    /**
     * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator
     */
    function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {
        return _amount.mul(_fracNum).div(PERC_DIVISOR);
    }

    /**
     * @dev Compute percentage representation of a fraction
     * @param _fracNum Numerator of fraction represeting the percentage
     * @param _fracDenom Denominator of fraction represeting the percentage
     */
    function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {
        return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);
    }
}

File 14 of 24 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

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

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

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @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 a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

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

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

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * 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) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 15 of 24 : PreciseMathUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";

library PreciseMathUtils {
    using SafeMath for uint256;

    // Divisor used for representing percentages
    uint256 public constant PERC_DIVISOR = 10**27;

    /**
     * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR
     * @param _amount Amount that is supposed to be a percentage
     */
    function validPerc(uint256 _amount) internal pure returns (bool) {
        return _amount <= PERC_DIVISOR;
    }

    /**
     * @dev Compute percentage of a value with the percentage represented by a fraction
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage
     * @param _fracDenom Denominator of fraction representing the percentage
     */
    function percOf(
        uint256 _amount,
        uint256 _fracNum,
        uint256 _fracDenom
    ) internal pure returns (uint256) {
        return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);
    }

    /**
     * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR
     * @param _amount Amount to take the percentage of
     * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator
     */
    function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {
        return _amount.mul(_fracNum).div(PERC_DIVISOR);
    }

    /**
     * @dev Compute percentage representation of a fraction
     * @param _fracNum Numerator of fraction represeting the percentage
     * @param _fracDenom Denominator of fraction represeting the percentage
     */
    function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {
        return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);
    }
}

File 16 of 24 : Manager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./IManager.sol";
import "./IController.sol";

contract Manager is IManager {
    // Controller that contract is registered with
    IController public controller;

    // Check if sender is controller
    modifier onlyController() {
        _onlyController();
        _;
    }

    // Check if sender is controller owner
    modifier onlyControllerOwner() {
        _onlyControllerOwner();
        _;
    }

    // Check if controller is not paused
    modifier whenSystemNotPaused() {
        _whenSystemNotPaused();
        _;
    }

    // Check if controller is paused
    modifier whenSystemPaused() {
        _whenSystemPaused();
        _;
    }

    constructor(address _controller) {
        controller = IController(_controller);
    }

    /**
     * @notice Set controller. Only callable by current controller
     * @param _controller Controller contract address
     */
    function setController(address _controller) external onlyController {
        controller = IController(_controller);

        emit SetController(_controller);
    }

    function _onlyController() private view {
        require(msg.sender == address(controller), "caller must be Controller");
    }

    function _onlyControllerOwner() private view {
        require(msg.sender == controller.owner(), "caller must be Controller owner");
    }

    function _whenSystemNotPaused() private view {
        require(!controller.paused(), "system is paused");
    }

    function _whenSystemPaused() private view {
        require(controller.paused(), "system is not paused");
    }
}

File 17 of 24 : IManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

interface IManager {
    event SetController(address controller);
    event ParameterUpdate(string param);

    function setController(address _controller) external;
}

File 18 of 24 : IController.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./zeppelin/Pausable.sol";

abstract contract IController is Pausable {
    event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash);

    function setContractInfo(
        bytes32 _id,
        address _contractAddress,
        bytes20 _gitCommitHash
    ) external virtual;

    function updateController(bytes32 _id, address _controller) external virtual;

    function getContract(bytes32 _id) public view virtual returns (address);
}

File 19 of 24 : Pausable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "./Ownable.sol";

/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is Ownable {
    event Pause();
    event Unpause();

    bool public paused;

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(paused);
        _;
    }

    /**
     * @dev called by the owner to pause, triggers stopped state
     */
    function pause() public onlyOwner whenNotPaused {
        paused = true;
        emit Pause();
    }

    /**
     * @dev called by the owner to unpause, returns to normal state
     */
    function unpause() public onlyOwner whenPaused {
        paused = false;
        emit Unpause();
    }
}

File 20 of 24 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
    address public owner;

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

    /**
     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
     * account.
     */
    constructor() {
        owner = msg.sender;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0));
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

File 21 of 24 : IVotes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts-upgradeable/interfaces/IERC5805Upgradeable.sol";

interface IVotes is IERC5805Upgradeable {
    function totalSupply() external view returns (uint256);

    function delegatedAt(address account, uint256 timepoint) external returns (address);

    // ERC-20 metadata functions that improve compatibility with tools like Tally

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

File 22 of 24 : IERC5805Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol)

pragma solidity ^0.8.0;

import "../governance/utils/IVotesUpgradeable.sol";
import "./IERC6372Upgradeable.sol";

interface IERC5805Upgradeable is IERC6372Upgradeable, IVotesUpgradeable {}

File 23 of 24 : IVotesUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotesUpgradeable {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     */
    function getPastVotes(address account, uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is
     * configured to use block numbers, this will return the value at the end of the corresponding block.
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 timepoint) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}

File 24 of 24 : IERC6372Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol)

pragma solidity ^0.8.0;

interface IERC6372Upgradeable {
    /**
     * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).
     */
    function clock() external view returns (uint48);

    /**
     * @dev Description of the clock
     */
    // solhint-disable-next-line func-name-mixedcase
    function CLOCK_MODE() external view returns (string memory);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"},{"internalType":"uint256","name":"lastValue","type":"uint256"}],"name":"DecreasingValues","type":"error"},{"inputs":[{"internalType":"uint256","name":"lastClaimRound","type":"uint256"},{"internalType":"uint256","name":"maxAllowed","type":"uint256"}],"name":"FutureLastClaimRound","type":"error"},{"inputs":[{"internalType":"uint256","name":"queryRound","type":"uint256"},{"internalType":"uint256","name":"maxAllowed","type":"uint256"}],"name":"FutureLookup","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"required","type":"address"}],"name":"InvalidCaller","type":"error"},{"inputs":[{"internalType":"uint256","name":"checkpointRound","type":"uint256"},{"internalType":"uint256","name":"requiredRound","type":"uint256"}],"name":"InvalidStartRound","type":"error"},{"inputs":[{"internalType":"uint256","name":"checkpointRound","type":"uint256"},{"internalType":"uint256","name":"requiredRound","type":"uint256"}],"name":"InvalidTotalStakeCheckpointRound","type":"error"},{"inputs":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint256","name":"round","type":"uint256"}],"name":"MissingEarningsPool","type":"error"},{"inputs":[{"internalType":"string","name":"bondingManagerFunction","type":"string"}],"name":"MustCallBondingManager","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBondedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"previousLastClaimRound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBondedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLastClaimRound","type":"uint256"}],"name":"DelegatorBondedAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"param","type":"string"}],"name":"ParameterUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"controller","type":"address"}],"name":"SetController","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_startRound","type":"uint256"},{"internalType":"uint256","name":"_bondedAmount","type":"uint256"},{"internalType":"address","name":"_delegateAddress","type":"address"},{"internalType":"uint256","name":"_delegatedAmount","type":"uint256"},{"internalType":"uint256","name":"_lastClaimRound","type":"uint256"},{"internalType":"uint256","name":"_lastRewardRound","type":"uint256"}],"name":"checkpointBondingState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalStake","type":"uint256"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"checkpointTotalActiveStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"delegatedAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"getTotalActiveStakeAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_round","type":"uint256"}],"name":"getVotesAndDelegateAtRoundStart","outputs":[{"internalType":"uint256","name":"votes","type":"uint256"},{"internalType":"address","name":"delegateAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"hasCheckpoint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_controller","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"targetContractId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506040516117d03803806117d083398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b61173d806100936000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806392eefe9b116100b8578063c656a01e1161007c578063c656a01e146102cd578063db51a69f14610308578063e35c3e4314610338578063ef105c911461034b578063f77c47911461035e578063f92e135b1461037157600080fd5b806392eefe9b1461026157806395d89b41146102745780639ab24eb014610294578063b782c2bd146102a7578063c3cda520146102ba57600080fd5b806351720b41116100ff57806351720b41146101e6578063587cde1e146101ef5780635c19a95c1461021a5780638e539e8c1461022f57806391ddadf41461024257600080fd5b806306fdde031461013c57806318160ddd1461017f578063313ce567146101955780633a46b1a8146101a45780634bf5d7e9146101b7575b600080fd5b6040805180820190915260158152742634bb32b832b2b9102b37ba34b733902837bbb2b960591b60208201525b60405161017691906113fd565b60405180910390f35b610187610384565b604051908152602001610176565b60405160128152602001610176565b6101876101b236600461146a565b6103ae565b6040805180820190915260138152721b5bd9194f5b1a5d995c19595c97dc9bdd5b99606a1b6020820152610169565b61018760015481565b6102026101fd366004611496565b610429565b6040516001600160a01b039091168152602001610176565b61022d610228366004611496565b610458565b005b61018761023d3660046114b3565b61048a565b61024a6104c8565b60405165ffffffffffff9091168152602001610176565b61022d61026f366004611496565b61054a565b6040805180820190915260048152631d93141560e21b6020820152610169565b6101876102a2366004611496565b6105a6565b6101876102b53660046114b3565b6105bd565b61022d6102c83660046114cc565b61071b565b6102f86102db366004611496565b6001600160a01b0316600090815260026020526040902054151590565b6040519015158152602001610176565b61031b61031636600461146a565b61074e565b604080519283526001600160a01b03909116602083015201610176565b61022d61034636600461152e565b6107b1565b61022d610359366004611593565b6109ed565b600054610202906001600160a01b031681565b61020261037f36600461146a565b610a5e565b60006103a96103916104c8565b61039c9060016115cb565b65ffffffffffff166105bd565b905090565b60008160006103bb6104c8565b65ffffffffffff16905080821061040d578181156103e3576103de6001836115f5565b6103e6565b60005b604051637f07449b60e01b8152600481019290925260248201526044015b60405180910390fd5b600061041e8661031687600161160c565b509695505050505050565b600080610450836104386104c8565b6104439060016115cb565b65ffffffffffff1661074e565b949350505050565b60405163866cb42d60e01b815260040161040490602080825260049082015263189bdb9960e21b604082015260600190565b60008160006104976104c8565b65ffffffffffff1690508082106104ba578181156103e3576103de6001836115f5565b6104506102b585600161160c565b60006103a96104d5610aaa565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561050d57600080fd5b505afa158015610521573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105459190611624565b610b47565b610552610bb2565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709060200160405180910390a150565b6000806105b5836104386104c8565b509392505050565b60006105c76104c8565b6105d29060016115cb565b65ffffffffffff1682111561061f57816105ea6104c8565b6105f59060016115cb565b604051637f07449b60e01b8152600481019290925265ffffffffffff166024820152604401610404565b600082815260046020526040902054801561063a5792915050565b600360006106488286610c0e565b90508061065a57506000949350505050565b815481101561069a5760008282815481106106775761067761163d565b600091825260208083209091015482526004905260409020549695505050505050565b6106a2610cbb565b6001600160a01b031663465501d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156106da57600080fd5b505afa1580156106ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107129190611624565b95945050505050565b60405163866cb42d60e01b81526020600482015260076024820152663137b7322337b960c91b6044820152606401610404565b600080600061075d8585610d0c565b600181015481546001600160a01b03909116935090915061078157600092506107a9565b61078b8582610dd2565b1561079c57806002015492506107a9565b6107a68185610dfb565b92505b509250929050565b6107b9610e7a565b6107c16104c8565b6107cc9060016115cb565b65ffffffffffff16861461081857856107e36104c8565b6107ee9060016115cb565b60405163b986b59960e01b8152600481019290925265ffffffffffff166024820152604401610404565b85821061084d578161082b6001886115f5565b6040516308384c5960e11b815260048101929092526024820152604401610404565b6108886040518060a001604052806000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b038816600090815260026020526040902054156108f5576108b08888610d0c565b6040805160a0810182528254815260018301546001600160a01b0316602082015260028301549181019190915260038201546060820152600490910154608082015290505b6000600260008a6001600160a01b03166001600160a01b03168152602001908152602001600020905060006040518060a00160405280898152602001886001600160a01b03168152602001878152602001868152602001858152509050808260010160008b81526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002015560608201518160030155608082015181600401559050506109d68983600001610ecf90919063ffffffff16565b6109e18a8483610f6a565b50505050505050505050565b6109f5610e7a565b6109fd6104c8565b65ffffffffffff168114610a3e5780610a146104c8565b6040516329af3fdf60e01b8152600481019290925265ffffffffffff166024820152604401610404565b6000818152600460205260409020829055610a5a600382610ecf565b5050565b6000816000610a6b6104c8565b65ffffffffffff169050808210610a8e578181156103e3576103de6001836115f5565b6000610a9f8661031687600161160c565b979650505050505050565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b158015610b0f57600080fd5b505afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a99190611653565b600065ffffffffffff821115610bae5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610404565b5090565b6000546001600160a01b03163314610c0c5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572000000000000006044820152606401610404565b565b8154600090610c1f57506000610cb5565b82546000905b80821015610c6c576000610c39838361111b565b60008781526020902090915085908201541115610c5857809150610c66565b610c6381600161160c565b92505b50610c25565b600082118015610c98575083610c9586610c876001866115f5565b600091825260209091200190565b54145b15610cb157610ca86001836115f5565b92505050610cb5565b5090505b92915050565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d9890602401610af7565b6000610d166104c8565b610d219060016115cb565b65ffffffffffff16821115610d3957816105ea6104c8565b6001600160a01b038316600090815260026020908152604080832085845260018101909252909120805415610d71579150610cb59050565b6000610d7d8386611136565b8354909150811415610d9357509150610cb59050565b6000836000018281548110610daa57610daa61163d565b6000918252602080832090910154825260019095019094525050604090912091505092915050565b60018101546000906001600160a01b038481169116148015610df45750815415155b9392505050565b600182015460038301546000916001600160a01b0316908290610e1f9083906111ec565b9050600080610e2e84876112c4565b91509150610e3c8483610dd2565b610e4d576000945050505050610cb5565b866003015482600401541015610e6b57505084549250610cb5915050565b610a9f83828960000154611354565b610e82610cbb565b6001600160a01b0316336001600160a01b031614610c0c5733610ea3610cbb565b6040516302d9d9c960e31b81526001600160a01b03928316600482015291166024820152604401610404565b8154610eed5781546001810183556000928352602090922090910155565b81546000908390610f00906001906115f5565b81548110610f1057610f1061163d565b9060005260206000200154905080821015610f48576040516328ffde6160e01b81526004810183905260248101829052604401610404565b808214610f65578254600181018455600084815260209020018290555b505050565b602080830151908201516001600160a01b0380831690821614610fd257806001600160a01b0316826001600160a01b0316866001600160a01b03167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a45b6000856001600160a01b0316826001600160a01b0316148015610ff55750835115155b90506000866001600160a01b0316846001600160a01b031614801561101a5750855115155b905060008161102a576000611030565b86604001515b9050600083611040576000611046565b86604001515b90508082146110945760408051838152602081018390526001600160a01b038b16917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25b865188511415806110ad57508660600151886060015114155b156111105787516060808a015189518a83015160408051958652602086019390935291840152908201526001600160a01b038a16907f1232f54fc2d34f79dc63b496ab493d834655fc2ea6d945ca547e9be242fd2b729060800160405180910390a25b505050505050505050565b600061112a6002848418611670565b610df49084841661160c565b81546000908061114a576000915050610cb5565b82846111576001846115f5565b815481106111675761116761163d565b90600052602060002001541161118a576111826001826115f5565b915050610cb5565b60006111968585610c0e565b90508181106111a7576111a7611692565b838582815481106111ba576111ba61163d565b906000526020600020015414156111d4579150610cb59050565b806111e157509050610cb5565b6107126001826115f5565b61121e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b611226610cbb565b60405163091153f160e21b81526001600160a01b0385811660048301526024820185905291909116906324454fc49060440160a06040518083038186803b15801561127057600080fd5b505afa158015611284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a891906116a8565b6080860152606085015260408401526020830152815292915050565b60006112f86040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6113028484610d0c565b600481015490925080156107a95761131a85826111ec565b91508160600151600014156107a957604051634956ad3960e11b81526001600160a01b038616600482015260248101829052604401610404565b60008360600151600014156113745761136e6001806113a1565b60608501525b606083015161138e576113886001806113a1565b60608401525b61045082846060015186606001516113c3565b6000610df4826113bd856b033b2e3c9fd0803ce80000006113e5565b906113f1565b60006104506b033b2e3c9fd0803ce80000006113bd6113e286866113a1565b87905b6000610df482846116e8565b6000610df48284611670565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461146757600080fd5b50565b6000806040838503121561147d57600080fd5b823561148881611452565b946020939093013593505050565b6000602082840312156114a857600080fd5b8135610df481611452565b6000602082840312156114c557600080fd5b5035919050565b60008060008060008060c087890312156114e557600080fd5b86356114f081611452565b95506020870135945060408701359350606087013560ff8116811461151457600080fd5b9598949750929560808101359460a0909101359350915050565b600080600080600080600060e0888a03121561154957600080fd5b873561155481611452565b96506020880135955060408801359450606088013561157281611452565b9699959850939660808101359560a0820135955060c0909101359350915050565b600080604083850312156115a657600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b600065ffffffffffff8083168185168083038211156115ec576115ec6115b5565b01949350505050565b600082821015611607576116076115b5565b500390565b6000821982111561161f5761161f6115b5565b500190565b60006020828403121561163657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166557600080fd5b8151610df481611452565b60008261168d57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a086880312156116c057600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000816000190483118215151615611702576117026115b5565b50029056fea2646970667358221220d61eadc5e7f542ce1a008b8848bc9d50b7dcfcad8cf39f24bee5ddf6168cb0d364736f6c63430008090033000000000000000000000000d8e8328501e9645d16cf49539efc04f734606ee4

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101375760003560e01c806392eefe9b116100b8578063c656a01e1161007c578063c656a01e146102cd578063db51a69f14610308578063e35c3e4314610338578063ef105c911461034b578063f77c47911461035e578063f92e135b1461037157600080fd5b806392eefe9b1461026157806395d89b41146102745780639ab24eb014610294578063b782c2bd146102a7578063c3cda520146102ba57600080fd5b806351720b41116100ff57806351720b41146101e6578063587cde1e146101ef5780635c19a95c1461021a5780638e539e8c1461022f57806391ddadf41461024257600080fd5b806306fdde031461013c57806318160ddd1461017f578063313ce567146101955780633a46b1a8146101a45780634bf5d7e9146101b7575b600080fd5b6040805180820190915260158152742634bb32b832b2b9102b37ba34b733902837bbb2b960591b60208201525b60405161017691906113fd565b60405180910390f35b610187610384565b604051908152602001610176565b60405160128152602001610176565b6101876101b236600461146a565b6103ae565b6040805180820190915260138152721b5bd9194f5b1a5d995c19595c97dc9bdd5b99606a1b6020820152610169565b61018760015481565b6102026101fd366004611496565b610429565b6040516001600160a01b039091168152602001610176565b61022d610228366004611496565b610458565b005b61018761023d3660046114b3565b61048a565b61024a6104c8565b60405165ffffffffffff9091168152602001610176565b61022d61026f366004611496565b61054a565b6040805180820190915260048152631d93141560e21b6020820152610169565b6101876102a2366004611496565b6105a6565b6101876102b53660046114b3565b6105bd565b61022d6102c83660046114cc565b61071b565b6102f86102db366004611496565b6001600160a01b0316600090815260026020526040902054151590565b6040519015158152602001610176565b61031b61031636600461146a565b61074e565b604080519283526001600160a01b03909116602083015201610176565b61022d61034636600461152e565b6107b1565b61022d610359366004611593565b6109ed565b600054610202906001600160a01b031681565b61020261037f36600461146a565b610a5e565b60006103a96103916104c8565b61039c9060016115cb565b65ffffffffffff166105bd565b905090565b60008160006103bb6104c8565b65ffffffffffff16905080821061040d578181156103e3576103de6001836115f5565b6103e6565b60005b604051637f07449b60e01b8152600481019290925260248201526044015b60405180910390fd5b600061041e8661031687600161160c565b509695505050505050565b600080610450836104386104c8565b6104439060016115cb565b65ffffffffffff1661074e565b949350505050565b60405163866cb42d60e01b815260040161040490602080825260049082015263189bdb9960e21b604082015260600190565b60008160006104976104c8565b65ffffffffffff1690508082106104ba578181156103e3576103de6001836115f5565b6104506102b585600161160c565b60006103a96104d5610aaa565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561050d57600080fd5b505afa158015610521573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105459190611624565b610b47565b610552610bb2565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f709060200160405180910390a150565b6000806105b5836104386104c8565b509392505050565b60006105c76104c8565b6105d29060016115cb565b65ffffffffffff1682111561061f57816105ea6104c8565b6105f59060016115cb565b604051637f07449b60e01b8152600481019290925265ffffffffffff166024820152604401610404565b600082815260046020526040902054801561063a5792915050565b600360006106488286610c0e565b90508061065a57506000949350505050565b815481101561069a5760008282815481106106775761067761163d565b600091825260208083209091015482526004905260409020549695505050505050565b6106a2610cbb565b6001600160a01b031663465501d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156106da57600080fd5b505afa1580156106ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107129190611624565b95945050505050565b60405163866cb42d60e01b81526020600482015260076024820152663137b7322337b960c91b6044820152606401610404565b600080600061075d8585610d0c565b600181015481546001600160a01b03909116935090915061078157600092506107a9565b61078b8582610dd2565b1561079c57806002015492506107a9565b6107a68185610dfb565b92505b509250929050565b6107b9610e7a565b6107c16104c8565b6107cc9060016115cb565b65ffffffffffff16861461081857856107e36104c8565b6107ee9060016115cb565b60405163b986b59960e01b8152600481019290925265ffffffffffff166024820152604401610404565b85821061084d578161082b6001886115f5565b6040516308384c5960e11b815260048101929092526024820152604401610404565b6108886040518060a001604052806000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b038816600090815260026020526040902054156108f5576108b08888610d0c565b6040805160a0810182528254815260018301546001600160a01b0316602082015260028301549181019190915260038201546060820152600490910154608082015290505b6000600260008a6001600160a01b03166001600160a01b03168152602001908152602001600020905060006040518060a00160405280898152602001886001600160a01b03168152602001878152602001868152602001858152509050808260010160008b81526020019081526020016000206000820151816000015560208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002015560608201518160030155608082015181600401559050506109d68983600001610ecf90919063ffffffff16565b6109e18a8483610f6a565b50505050505050505050565b6109f5610e7a565b6109fd6104c8565b65ffffffffffff168114610a3e5780610a146104c8565b6040516329af3fdf60e01b8152600481019290925265ffffffffffff166024820152604401610404565b6000818152600460205260409020829055610a5a600382610ecf565b5050565b6000816000610a6b6104c8565b65ffffffffffff169050808210610a8e578181156103e3576103de6001836115f5565b6000610a9f8661031687600161160c565b979650505050505050565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b158015610b0f57600080fd5b505afa158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a99190611653565b600065ffffffffffff821115610bae5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610404565b5090565b6000546001600160a01b03163314610c0c5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572000000000000006044820152606401610404565b565b8154600090610c1f57506000610cb5565b82546000905b80821015610c6c576000610c39838361111b565b60008781526020902090915085908201541115610c5857809150610c66565b610c6381600161160c565b92505b50610c25565b600082118015610c98575083610c9586610c876001866115f5565b600091825260209091200190565b54145b15610cb157610ca86001836115f5565b92505050610cb5565b5090505b92915050565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d9890602401610af7565b6000610d166104c8565b610d219060016115cb565b65ffffffffffff16821115610d3957816105ea6104c8565b6001600160a01b038316600090815260026020908152604080832085845260018101909252909120805415610d71579150610cb59050565b6000610d7d8386611136565b8354909150811415610d9357509150610cb59050565b6000836000018281548110610daa57610daa61163d565b6000918252602080832090910154825260019095019094525050604090912091505092915050565b60018101546000906001600160a01b038481169116148015610df45750815415155b9392505050565b600182015460038301546000916001600160a01b0316908290610e1f9083906111ec565b9050600080610e2e84876112c4565b91509150610e3c8483610dd2565b610e4d576000945050505050610cb5565b866003015482600401541015610e6b57505084549250610cb5915050565b610a9f83828960000154611354565b610e82610cbb565b6001600160a01b0316336001600160a01b031614610c0c5733610ea3610cbb565b6040516302d9d9c960e31b81526001600160a01b03928316600482015291166024820152604401610404565b8154610eed5781546001810183556000928352602090922090910155565b81546000908390610f00906001906115f5565b81548110610f1057610f1061163d565b9060005260206000200154905080821015610f48576040516328ffde6160e01b81526004810183905260248101829052604401610404565b808214610f65578254600181018455600084815260209020018290555b505050565b602080830151908201516001600160a01b0380831690821614610fd257806001600160a01b0316826001600160a01b0316866001600160a01b03167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a45b6000856001600160a01b0316826001600160a01b0316148015610ff55750835115155b90506000866001600160a01b0316846001600160a01b031614801561101a5750855115155b905060008161102a576000611030565b86604001515b9050600083611040576000611046565b86604001515b90508082146110945760408051838152602081018390526001600160a01b038b16917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25b865188511415806110ad57508660600151886060015114155b156111105787516060808a015189518a83015160408051958652602086019390935291840152908201526001600160a01b038a16907f1232f54fc2d34f79dc63b496ab493d834655fc2ea6d945ca547e9be242fd2b729060800160405180910390a25b505050505050505050565b600061112a6002848418611670565b610df49084841661160c565b81546000908061114a576000915050610cb5565b82846111576001846115f5565b815481106111675761116761163d565b90600052602060002001541161118a576111826001826115f5565b915050610cb5565b60006111968585610c0e565b90508181106111a7576111a7611692565b838582815481106111ba576111ba61163d565b906000526020600020015414156111d4579150610cb59050565b806111e157509050610cb5565b6107126001826115f5565b61121e6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b611226610cbb565b60405163091153f160e21b81526001600160a01b0385811660048301526024820185905291909116906324454fc49060440160a06040518083038186803b15801561127057600080fd5b505afa158015611284573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a891906116a8565b6080860152606085015260408401526020830152815292915050565b60006112f86040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6113028484610d0c565b600481015490925080156107a95761131a85826111ec565b91508160600151600014156107a957604051634956ad3960e11b81526001600160a01b038616600482015260248101829052604401610404565b60008360600151600014156113745761136e6001806113a1565b60608501525b606083015161138e576113886001806113a1565b60608401525b61045082846060015186606001516113c3565b6000610df4826113bd856b033b2e3c9fd0803ce80000006113e5565b906113f1565b60006104506b033b2e3c9fd0803ce80000006113bd6113e286866113a1565b87905b6000610df482846116e8565b6000610df48284611670565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461146757600080fd5b50565b6000806040838503121561147d57600080fd5b823561148881611452565b946020939093013593505050565b6000602082840312156114a857600080fd5b8135610df481611452565b6000602082840312156114c557600080fd5b5035919050565b60008060008060008060c087890312156114e557600080fd5b86356114f081611452565b95506020870135945060408701359350606087013560ff8116811461151457600080fd5b9598949750929560808101359460a0909101359350915050565b600080600080600080600060e0888a03121561154957600080fd5b873561155481611452565b96506020880135955060408801359450606088013561157281611452565b9699959850939660808101359560a0820135955060c0909101359350915050565b600080604083850312156115a657600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b600065ffffffffffff8083168185168083038211156115ec576115ec6115b5565b01949350505050565b600082821015611607576116076115b5565b500390565b6000821982111561161f5761161f6115b5565b500190565b60006020828403121561163657600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561166557600080fd5b8151610df481611452565b60008261168d57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052600160045260246000fd5b600080600080600060a086880312156116c057600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000816000190483118215151615611702576117026115b5565b50029056fea2646970667358221220d61eadc5e7f542ce1a008b8848bc9d50b7dcfcad8cf39f24bee5ddf6168cb0d364736f6c63430008090033

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

000000000000000000000000d8e8328501e9645d16cf49539efc04f734606ee4

-----Decoded View---------------
Arg [0] : _controller (address): 0xD8E8328501E9645d16Cf49539efC04f734606ee4

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000d8e8328501e9645d16cf49539efc04f734606ee4


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.