creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SafeMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n"
      },
      "contracts/CheckPointable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\nimport \"./lib/CheckPointHistory.sol\";\r\nimport \"./lib/CheckPointsByAddress.sol\";\r\nimport \"./lib/CheckPointHistoryCache.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\n\r\n/**\r\n * @title Check Pointable ERC20 Behavior\r\n * @notice ERC20 behavior which adds balance check point features.\r\n **/\r\nabstract contract CheckPointable {\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n    using CheckPointsByAddress for CheckPointsByAddress.CheckPointsByAddressState;\r\n    using CheckPointHistoryCache for CheckPointHistoryCache.CacheState;\r\n    using SafeMath for uint256;\r\n\r\n    // The number of history cleanup steps executed for every write operation.\r\n    // It is more than 1 to make as certain as possible that all history gets cleaned eventually.\r\n    uint256 private constant CLEANUP_COUNT = 2;\r\n\r\n    // Private member variables\r\n    CheckPointsByAddress.CheckPointsByAddressState private balanceHistory;\r\n    CheckPointHistory.CheckPointHistoryState private totalSupply;\r\n    CheckPointHistoryCache.CacheState private totalSupplyCache;\r\n\r\n    // Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n    // history before that block should never be used since it can be inconsistent.\r\n    uint256 private cleanupBlockNumber;\r\n\r\n    // Address of the contract that is allowed to call methods for history cleaning.\r\n    address public cleanerContract;\r\n\r\n    /**\r\n     * Emitted when a total supply cache entry is created.\r\n     * Allows history cleaners to track total supply cache cleanup opportunities off-chain.\r\n     */\r\n    event CreatedTotalSupplyCache(uint256 _blockNumber);\r\n\r\n    // Most cleanup opportunities can be deduced from standard event\r\n    // Transfer(from, to, amount):\r\n    //   - balance history for `from` (if nonzero) and `to` (if nonzero)\r\n    //   - total supply history when either `from` or `to` is zero\r\n\r\n    modifier notBeforeCleanupBlock(uint256 _blockNumber) {\r\n        require(\r\n            _blockNumber >= cleanupBlockNumber,\r\n            \"CheckPointable: reading from cleaned-up block\"\r\n        );\r\n        _;\r\n    }\r\n\r\n    modifier onlyCleaner() {\r\n        require(msg.sender == cleanerContract, \"Only cleaner contract\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @dev Queries the token balance of `_owner` at a specific `_blockNumber`.\r\n     * @param _owner The address from which the balance will be retrieved.\r\n     * @param _blockNumber The block number when the balance is queried.\r\n     * @return _balance The balance at `_blockNumber`.\r\n     **/\r\n    function balanceOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    )\r\n        public\r\n        view\r\n        virtual\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _balance)\r\n    {\r\n        return balanceHistory.valueOfAt(_owner, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Burn current token `amount` for `owner` of checkpoints at current block.\r\n     * @param _owner The address of the owner to burn tokens.\r\n     * @param _amount The amount to burn.\r\n     */\r\n    function _burnForAtNow(address _owner, uint256 _amount) internal virtual {\r\n        uint256 newBalance = balanceOfAt(_owner, block.number).sub(\r\n            _amount,\r\n            \"Burn too big for owner\"\r\n        );\r\n        balanceHistory.writeValue(_owner, newBalance);\r\n        balanceHistory.cleanupOldCheckpoints(\r\n            _owner,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n        totalSupply.writeValue(\r\n            totalSupplyAt(block.number).sub(\r\n                _amount,\r\n                \"Burn too big for total supply\"\r\n            )\r\n        );\r\n        totalSupply.cleanupOldCheckpoints(CLEANUP_COUNT, cleanupBlockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Mint current token `amount` for `owner` of checkpoints at current block.\r\n     * @param _owner The address of the owner to burn tokens.\r\n     * @param _amount The amount to burn.\r\n     */\r\n    function _mintForAtNow(address _owner, uint256 _amount) internal virtual {\r\n        uint256 newBalance = balanceOfAt(_owner, block.number).add(_amount);\r\n        balanceHistory.writeValue(_owner, newBalance);\r\n        balanceHistory.cleanupOldCheckpoints(\r\n            _owner,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n        totalSupply.writeValue(totalSupplyAt(block.number).add(_amount));\r\n        totalSupply.cleanupOldCheckpoints(CLEANUP_COUNT, cleanupBlockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Total amount of tokens at a specific `_blockNumber`.\r\n     * @param _blockNumber The block number when the _totalSupply is queried\r\n     * @return _totalSupply The total amount of tokens at `_blockNumber`\r\n     **/\r\n    function totalSupplyAt(\r\n        uint256 _blockNumber\r\n    )\r\n        public\r\n        view\r\n        virtual\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _totalSupply)\r\n    {\r\n        return totalSupply.valueAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Total amount of tokens at a specific `_blockNumber`.\r\n     * @param _blockNumber The block number when the _totalSupply is queried\r\n     * @return _totalSupply The total amount of tokens at `_blockNumber`\r\n     **/\r\n    function _totalSupplyAtCached(\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _totalSupply)\r\n    {\r\n        // use cache only for the past (the value will never change)\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Can only be used for past blocks\"\r\n        );\r\n        (uint256 value, bool cacheCreated) = totalSupplyCache.valueAt(\r\n            totalSupply,\r\n            _blockNumber\r\n        );\r\n        if (cacheCreated) emit CreatedTotalSupplyCache(_blockNumber);\r\n        return value;\r\n    }\r\n\r\n    /**\r\n     * @notice Transmit token `_amount` `_from` address `_to` address of checkpoints at current block.\r\n     * @param _from The address of the sender.\r\n     * @param _to The address of the receiver.\r\n     * @param _amount The amount to transmit.\r\n     */\r\n    function _transmitAtNow(\r\n        address _from,\r\n        address _to,\r\n        uint256 _amount\r\n    ) internal virtual {\r\n        balanceHistory.transmit(_from, _to, _amount);\r\n        balanceHistory.cleanupOldCheckpoints(\r\n            _from,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n        balanceHistory.cleanupOldCheckpoints(\r\n            _to,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n    }\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     */\r\n    function _setCleanupBlockNumber(uint256 _blockNumber) internal {\r\n        require(\r\n            _blockNumber >= cleanupBlockNumber,\r\n            \"Cleanup block number must never decrease\"\r\n        );\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Cleanup block must be in the past\"\r\n        );\r\n        cleanupBlockNumber = _blockNumber;\r\n    }\r\n\r\n    /**\r\n     * Get the cleanup block number.\r\n     */\r\n    function _cleanupBlockNumber() internal view returns (uint256) {\r\n        return cleanupBlockNumber;\r\n    }\r\n\r\n    /**\r\n     * @notice Update history at token transfer, the CheckPointable part of `_beforeTokenTransfer` hook.\r\n     * @param _from The address of the sender.\r\n     * @param _to The address of the receiver.\r\n     * @param _amount The amount to transmit.\r\n     */\r\n    function _updateBalanceHistoryAtTransfer(\r\n        address _from,\r\n        address _to,\r\n        uint256 _amount\r\n    ) internal virtual {\r\n        if (_from == address(0)) {\r\n            // mint checkpoint balance data for transferee\r\n            _mintForAtNow(_to, _amount);\r\n        } else if (_to == address(0)) {\r\n            // burn checkpoint data for transferer\r\n            _burnForAtNow(_from, _amount);\r\n        } else {\r\n            // transfer checkpoint balance data\r\n            _transmitAtNow(_from, _to, _amount);\r\n        }\r\n    }\r\n\r\n    // history cleanup methods\r\n\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     */\r\n    function _setCleanerContract(address _cleanerContract) internal {\r\n        cleanerContract = _cleanerContract;\r\n    }\r\n\r\n    /**\r\n     * Delete balance checkpoints that expired (i.e. are before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _owner balance owner account address\r\n     * @param _count maximum number of checkpoints to delete\r\n     * @return the number of checkpoints deleted\r\n     */\r\n    function balanceHistoryCleanup(\r\n        address _owner,\r\n        uint256 _count\r\n    ) external onlyCleaner returns (uint256) {\r\n        return\r\n            balanceHistory.cleanupOldCheckpoints(\r\n                _owner,\r\n                _count,\r\n                cleanupBlockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * Delete total supply checkpoints that expired (i.e. are before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _count maximum number of checkpoints to delete\r\n     * @return the number of checkpoints deleted\r\n     */\r\n    function totalSupplyHistoryCleanup(\r\n        uint256 _count\r\n    ) external onlyCleaner returns (uint256) {\r\n        return totalSupply.cleanupOldCheckpoints(_count, cleanupBlockNumber);\r\n    }\r\n\r\n    /**\r\n     * Delete total supply cache entry that expired (i.e. is before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _blockNumber the block number for which total supply value was cached\r\n     * @return the number of cache entries deleted (always 0 or 1)\r\n     */\r\n    function totalSupplyCacheCleanup(\r\n        uint256 _blockNumber\r\n    ) external onlyCleaner returns (uint256) {\r\n        require(\r\n            _blockNumber < cleanupBlockNumber,\r\n            \"No cleanup after cleanup block\"\r\n        );\r\n        return totalSupplyCache.deleteAt(_blockNumber);\r\n    }\r\n}\r\n"
      },
      "contracts/Delegatable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./lib/PercentageDelegation.sol\";\r\nimport \"./lib/ExplicitDelegation.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"./utils/SafePct.sol\";\r\nimport \"./lib/VotePower.sol\";\r\nimport \"./lib/VotePowerCache.sol\";\r\nimport \"./interfaces/IVPContractEvents.sol\";\r\n\r\n/**\r\n * @title Delegateable ERC20 behavior\r\n * @notice An ERC20 Delegateable behavior to delegate voting power\r\n *  of a token to delegates. This contract orchestrates interaction between\r\n *  managing a delegation and the vote power allocations that result.\r\n **/\r\ncontract Delegatable is IVPContractEvents {\r\n    using PercentageDelegation for PercentageDelegation.DelegationState;\r\n    using ExplicitDelegation for ExplicitDelegation.DelegationState;\r\n    using SafeMath for uint256;\r\n    using SafePct for uint256;\r\n    using VotePower for VotePower.VotePowerState;\r\n    using VotePowerCache for VotePowerCache.CacheState;\r\n\r\n    enum DelegationMode {\r\n        NOTSET,\r\n        PERCENTAGE,\r\n        AMOUNT\r\n    }\r\n\r\n    // The number of history cleanup steps executed for every write operation.\r\n    // It is more than 1 to make as certain as possible that all history gets cleaned eventually.\r\n    uint256 private constant CLEANUP_COUNT = 2;\r\n\r\n    string private constant UNDELEGATED_VP_TOO_SMALL_MSG =\r\n        \"Undelegated vote power too small\";\r\n\r\n    // Map that tracks delegation mode of each address.\r\n    mapping(address => DelegationMode) private delegationModes;\r\n\r\n    // `percentageDelegations` is the map that tracks the percentage voting power delegation of each address.\r\n    // Explicit delegations are tracked directly through votePower.\r\n    mapping(address => PercentageDelegation.DelegationState)\r\n        private percentageDelegations;\r\n\r\n    mapping(address => ExplicitDelegation.DelegationState)\r\n        private explicitDelegations;\r\n\r\n    // `votePower` tracks all voting power balances\r\n    VotePower.VotePowerState private votePower;\r\n\r\n    // `votePower` tracks all voting power balances\r\n    VotePowerCache.CacheState private votePowerCache;\r\n\r\n    // Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n    // history before that block should never be used since it can be inconsistent.\r\n    uint256 private cleanupBlockNumber;\r\n\r\n    // Address of the contract that is allowed to call methods for history cleaning.\r\n    address public cleanerContract;\r\n\r\n    /**\r\n     * Emitted when a vote power cache entry is created.\r\n     * Allows history cleaners to track vote power cache cleanup opportunities off-chain.\r\n     */\r\n    event CreatedVotePowerCache(address _owner, uint256 _blockNumber);\r\n\r\n    // Most history cleanup opportunities can be deduced from standard events:\r\n    // Transfer(from, to, amount):\r\n    //  - vote power checkpoints for `from` (if nonzero) and `to` (if nonzero)\r\n    //  - vote power checkpoints for percentage delegatees of `from` and `to` are also created,\r\n    //    but they don't have to be checked since Delegate events are also emitted in case of\r\n    //    percentage delegation vote power change due to delegators balance change\r\n    //  - Note: Transfer event is emitted from VPToken but vote power checkpoint delegationModes\r\n    //    must be called on its writeVotePowerContract\r\n    // Delegate(from, to, priorVP, newVP):\r\n    //  - vote power checkpoints for `from` and `to`\r\n    //  - percentage delegation checkpoint for `from` (if `from` uses percentage delegation mode)\r\n    //  - explicit delegation checkpoint from `from` to `to` (if `from` uses explicit delegation mode)\r\n    // Revoke(from, to, vp, block):\r\n    //  - vote power cache for `from` and `to` at `block`\r\n    //  - revocation cache block from `from` to `to` at `block`\r\n\r\n    /**\r\n     * Reading from history is not allowed before `cleanupBlockNumber`, since data before that\r\n     * might have been deleted and is thus unreliable.\r\n     */\r\n    modifier notBeforeCleanupBlock(uint256 _blockNumber) {\r\n        require(\r\n            _blockNumber >= cleanupBlockNumber,\r\n            \"Delegatable: reading from cleaned-up block\"\r\n        );\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * History cleaning methods can be called only from the cleaner address.\r\n     */\r\n    modifier onlyCleaner() {\r\n        require(msg.sender == cleanerContract, \"Only cleaner contract\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @notice (Un)Allocate `_owner` vote power of `_amount` across owner delegate\r\n     *  vote power percentages.\r\n     * @param _owner The address of the vote power owner.\r\n     * @param _priorBalance The owner's balance before change.\r\n     * @param _newBalance The owner's balance after change.\r\n     * @dev precondition: delegationModes[_owner] == DelegationMode.PERCENTAGE\r\n     */\r\n    function _allocateVotePower(\r\n        address _owner,\r\n        uint256 _priorBalance,\r\n        uint256 _newBalance\r\n    ) private {\r\n        // Get the voting delegation for the _owner\r\n        PercentageDelegation.DelegationState\r\n            storage delegation = percentageDelegations[_owner];\r\n        // Track total owner vp change\r\n        uint256 ownerVpAdd = _newBalance;\r\n        uint256 ownerVpSub = _priorBalance;\r\n        // Iterate over the delegates\r\n        (\r\n            uint256 length,\r\n            mapping(uint256 => DelegationHistory.Delegation) storage delegations\r\n        ) = delegation.getDelegationsRaw();\r\n        for (uint256 i = 0; i < length; i++) {\r\n            DelegationHistory.Delegation storage dlg = delegations[i];\r\n            address delegatee = dlg.delegate;\r\n            uint256 value = dlg.value;\r\n            // Compute the delegated vote power for the delegatee\r\n            uint256 priorValue = _priorBalance.mulDiv(\r\n                value,\r\n                PercentageDelegation.MAX_BIPS\r\n            );\r\n            uint256 newValue = _newBalance.mulDiv(\r\n                value,\r\n                PercentageDelegation.MAX_BIPS\r\n            );\r\n            ownerVpAdd = ownerVpAdd.add(priorValue);\r\n            ownerVpSub = ownerVpSub.add(newValue);\r\n            // could optimize next lines by checking that priorValue != newValue, but that can only happen\r\n            // for the transfer of 0 amount, which is prevented by the calling function\r\n            votePower.changeValue(delegatee, newValue, priorValue);\r\n            votePower.cleanupOldCheckpoints(\r\n                delegatee,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            emit Delegate(_owner, delegatee, priorValue, newValue);\r\n        }\r\n        // (ownerVpAdd - ownerVpSub) is how much the owner vp changes - will be 0 if delegation is 100%\r\n        if (ownerVpAdd != ownerVpSub) {\r\n            votePower.changeValue(_owner, ownerVpAdd, ownerVpSub);\r\n            votePower.cleanupOldCheckpoints(\r\n                _owner,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Burn `_amount` of vote power for `_owner`.\r\n     * @param _owner The address of the _owner vote power to burn.\r\n     * @param _ownerCurrentBalance The current token balance of the owner (which is their allocatable vote power).\r\n     * @param _amount The amount of vote power to burn.\r\n     */\r\n    function _burnVotePower(\r\n        address _owner,\r\n        uint256 _ownerCurrentBalance,\r\n        uint256 _amount\r\n    ) internal {\r\n        // revert with the same error as ERC20 in case transfer exceeds balance\r\n        uint256 newOwnerBalance = _ownerCurrentBalance.sub(\r\n            _amount,\r\n            \"ERC20: transfer amount exceeds balance\"\r\n        );\r\n        if (delegationModes[_owner] == DelegationMode.PERCENTAGE) {\r\n            // for PERCENTAGE delegation: reduce owner vote power allocations\r\n            _allocateVotePower(_owner, _ownerCurrentBalance, newOwnerBalance);\r\n        } else {\r\n            // for AMOUNT delegation: is there enough unallocated VP _to burn if explicitly delegated?\r\n            require(\r\n                _isTransmittable(_owner, _ownerCurrentBalance, _amount),\r\n                UNDELEGATED_VP_TOO_SMALL_MSG\r\n            );\r\n            // burn vote power\r\n            votePower.changeValue(_owner, 0, _amount);\r\n            votePower.cleanupOldCheckpoints(\r\n                _owner,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get whether `_owner` current delegation can be delegated by percentage.\r\n     * @param _owner Address of delegation to check.\r\n     * @return True if delegation can be delegated by percentage.\r\n     */\r\n    function _canDelegateByPct(address _owner) internal view returns (bool) {\r\n        // Get the delegation mode.\r\n        DelegationMode delegationMode = delegationModes[_owner];\r\n        // Return true if delegation is safe _to store percents, which can also\r\n        // apply if there is not delegation mode set.\r\n        return\r\n            delegationMode == DelegationMode.NOTSET ||\r\n            delegationMode == DelegationMode.PERCENTAGE;\r\n    }\r\n\r\n    /**\r\n     * @notice Get whether `_owner` current delegation can be delegated by amount.\r\n     * @param _owner Address of delegation to check.\r\n     * @return True if delegation can be delegated by amount.\r\n     */\r\n    function _canDelegateByAmount(address _owner) internal view returns (bool) {\r\n        // Get the delegation mode.\r\n        DelegationMode delegationMode = delegationModes[_owner];\r\n        // Return true if delegation is safe to store explicit amounts, which can also\r\n        // apply if there is not delegation mode set.\r\n        return\r\n            delegationMode == DelegationMode.NOTSET ||\r\n            delegationMode == DelegationMode.AMOUNT;\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate `_amount` of voting power to `_to` from `_from`\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _senderCurrentBalance The senders current balance (not their voting power)\r\n     * @param _amount The amount of voting power to be delegated\r\n     **/\r\n    function _delegateByAmount(\r\n        address _from,\r\n        address _to,\r\n        uint256 _senderCurrentBalance,\r\n        uint256 _amount\r\n    ) internal virtual {\r\n        require(_to != address(0), \"Cannot delegate to zero\");\r\n        require(_to != _from, \"Cannot delegate to self\");\r\n        require(_canDelegateByAmount(_from), \"Cannot delegate by amount\");\r\n\r\n        // Get the vote power delegation for the sender\r\n        ExplicitDelegation.DelegationState\r\n            storage delegation = explicitDelegations[_from];\r\n\r\n        // the prior value\r\n        uint256 priorAmount = delegation.getDelegatedValue(_to);\r\n\r\n        // Delegate new power\r\n        if (_amount < priorAmount) {\r\n            // Prior amount is greater, just reduce the delegated amount.\r\n            // subtraction is safe since _amount < priorAmount\r\n            votePower.undelegate(_from, _to, priorAmount - _amount);\r\n        } else {\r\n            // Is there enough undelegated vote power?\r\n            uint256 availableAmount = _undelegatedVotePowerOf(\r\n                _from,\r\n                _senderCurrentBalance\r\n            ).add(priorAmount);\r\n            require(availableAmount >= _amount, UNDELEGATED_VP_TOO_SMALL_MSG);\r\n            // Increase the delegated amount of vote power.\r\n            // subtraction is safe since _amount >= priorAmount\r\n            votePower.delegate(_from, _to, _amount - priorAmount);\r\n        }\r\n        votePower.cleanupOldCheckpoints(\r\n            _from,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n        votePower.cleanupOldCheckpoints(_to, CLEANUP_COUNT, cleanupBlockNumber);\r\n\r\n        // Add/replace delegate\r\n        delegation.addReplaceDelegate(_to, _amount);\r\n        delegation.cleanupOldCheckpoints(\r\n            _to,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n\r\n        // update mode if needed\r\n        if (delegationModes[_from] != DelegationMode.AMOUNT) {\r\n            delegationModes[_from] = DelegationMode.AMOUNT;\r\n        }\r\n\r\n        // emit event for delegation change\r\n        emit Delegate(_from, _to, priorAmount, _amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate `_bips` of voting power to `_to` from `_from`\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _senderCurrentBalance The senders current balance (not their voting power)\r\n     * @param _bips The percentage of voting power in basis points (1/100 of 1 percent) to be delegated\r\n     **/\r\n    function _delegateByPercentage(\r\n        address _from,\r\n        address _to,\r\n        uint256 _senderCurrentBalance,\r\n        uint256 _bips\r\n    ) internal virtual {\r\n        require(_to != address(0), \"Cannot delegate to zero\");\r\n        require(_to != _from, \"Cannot delegate to self\");\r\n        require(_canDelegateByPct(_from), \"Cannot delegate by percentage\");\r\n\r\n        // Get the vote power delegation for the sender\r\n        PercentageDelegation.DelegationState\r\n            storage delegation = percentageDelegations[_from];\r\n\r\n        // Get prior percent for delegate if exists\r\n        uint256 priorBips = delegation.getDelegatedValue(_to);\r\n        uint256 reverseVotePower = 0;\r\n        uint256 newVotePower = 0;\r\n\r\n        // Add/replace delegate\r\n        delegation.addReplaceDelegate(_to, _bips);\r\n        delegation.cleanupOldCheckpoints(CLEANUP_COUNT, cleanupBlockNumber);\r\n\r\n        // First, back out old voting power percentage, if not zero\r\n        if (priorBips != 0) {\r\n            reverseVotePower = _senderCurrentBalance.mulDiv(\r\n                priorBips,\r\n                PercentageDelegation.MAX_BIPS\r\n            );\r\n        }\r\n\r\n        // Calculate the new vote power\r\n        if (_bips != 0) {\r\n            newVotePower = _senderCurrentBalance.mulDiv(\r\n                _bips,\r\n                PercentageDelegation.MAX_BIPS\r\n            );\r\n        }\r\n\r\n        // Delegate new power\r\n        if (newVotePower < reverseVotePower) {\r\n            // subtraction is safe since newVotePower < reverseVotePower\r\n            votePower.undelegate(_from, _to, reverseVotePower - newVotePower);\r\n        } else {\r\n            // subtraction is safe since newVotePower >= reverseVotePower\r\n            votePower.delegate(_from, _to, newVotePower - reverseVotePower);\r\n        }\r\n        votePower.cleanupOldCheckpoints(\r\n            _from,\r\n            CLEANUP_COUNT,\r\n            cleanupBlockNumber\r\n        );\r\n        votePower.cleanupOldCheckpoints(_to, CLEANUP_COUNT, cleanupBlockNumber);\r\n\r\n        // update mode if needed\r\n        if (delegationModes[_from] != DelegationMode.PERCENTAGE) {\r\n            delegationModes[_from] = DelegationMode.PERCENTAGE;\r\n        }\r\n\r\n        // emit event for delegation change\r\n        emit Delegate(_from, _to, reverseVotePower, newVotePower);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the delegation mode for '_who'. This mode determines whether vote power is\r\n     *  allocated by percentage or by explicit value.\r\n     * @param _who The address to get delegation mode.\r\n     * @return Delegation mode\r\n     */\r\n    function _delegationModeOf(\r\n        address _who\r\n    ) internal view returns (DelegationMode) {\r\n        return delegationModes[_who];\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `_bips` of an `_owner`. Returned in two separate positional arrays.\r\n     * @param _owner The address to get delegations.\r\n     * @param _blockNumber The block for which we want to know the delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     */\r\n    function _percentageDelegatesOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (address[] memory _delegateAddresses, uint256[] memory _bips)\r\n    {\r\n        PercentageDelegation.DelegationState\r\n            storage delegation = percentageDelegations[_owner];\r\n        address[] memory allDelegateAddresses;\r\n        uint256[] memory allBips;\r\n        (allDelegateAddresses, allBips) = delegation.getDelegationsAt(\r\n            _blockNumber\r\n        );\r\n        // delete revoked addresses\r\n        for (uint256 i = 0; i < allDelegateAddresses.length; i++) {\r\n            if (\r\n                votePowerCache.revokedFromToAt(\r\n                    _owner,\r\n                    allDelegateAddresses[i],\r\n                    _blockNumber\r\n                )\r\n            ) {\r\n                allBips[i] = 0;\r\n            }\r\n        }\r\n        uint256 length = 0;\r\n        for (uint256 i = 0; i < allDelegateAddresses.length; i++) {\r\n            if (allBips[i] != 0) length++;\r\n        }\r\n        _delegateAddresses = new address[](length);\r\n        _bips = new uint256[](length);\r\n        uint256 destIndex = 0;\r\n        for (uint256 i = 0; i < allDelegateAddresses.length; i++) {\r\n            if (allBips[i] != 0) {\r\n                _delegateAddresses[destIndex] = allDelegateAddresses[i];\r\n                _bips[destIndex] = allBips[i];\r\n                destIndex++;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Checks if enough undelegated vote power exists to allow a token\r\n     *  transfer to occur if vote power is explicitly delegated.\r\n     * @param _owner The address of transmittable vote power to check.\r\n     * @param _ownerCurrentBalance The current balance of `_owner`.\r\n     * @param _amount The amount to check.\r\n     * @return True is `_amount` is transmittable.\r\n     */\r\n    function _isTransmittable(\r\n        address _owner,\r\n        uint256 _ownerCurrentBalance,\r\n        uint256 _amount\r\n    ) private view returns (bool) {\r\n        // Only proceed if we have a delegation by _amount\r\n        if (delegationModes[_owner] == DelegationMode.AMOUNT) {\r\n            // Return true if there is enough vote power _to cover the transfer\r\n            return\r\n                _undelegatedVotePowerOf(_owner, _ownerCurrentBalance) >=\r\n                _amount;\r\n        } else {\r\n            // Not delegated by _amount, so transfer always allowed\r\n            return true;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Mint `_amount` of vote power for `_owner`.\r\n     * @param _owner The address of the owner to receive new vote power.\r\n     * @param _amount The amount of vote power to mint.\r\n     */\r\n    function _mintVotePower(\r\n        address _owner,\r\n        uint256 _ownerCurrentBalance,\r\n        uint256 _amount\r\n    ) internal {\r\n        if (delegationModes[_owner] == DelegationMode.PERCENTAGE) {\r\n            // Allocate newly minted vote power over delegates\r\n            _allocateVotePower(\r\n                _owner,\r\n                _ownerCurrentBalance,\r\n                _ownerCurrentBalance.add(_amount)\r\n            );\r\n        } else {\r\n            votePower.changeValue(_owner, _amount, 0);\r\n            votePower.cleanupOldCheckpoints(\r\n                _owner,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Revoke the vote power of `_to` at block `_blockNumber`\r\n     * @param _from The address of the delegator\r\n     * @param _to The delegatee address of vote power to revoke.\r\n     * @param _senderBalanceAt The sender's balance at the block to be revoked.\r\n     * @param _blockNumber The block number at which to revoke.\r\n     */\r\n    function _revokeDelegationAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _senderBalanceAt,\r\n        uint256 _blockNumber\r\n    ) internal notBeforeCleanupBlock(_blockNumber) {\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Revoke is only for the past, use undelegate for the present\"\r\n        );\r\n\r\n        // Get amount revoked\r\n        uint256 votePowerRevoked = _votePowerFromToAtNoRevokeCheck(\r\n            _from,\r\n            _to,\r\n            _senderBalanceAt,\r\n            _blockNumber\r\n        );\r\n\r\n        // Revoke vote power\r\n        votePowerCache.revokeAt(\r\n            votePower,\r\n            _from,\r\n            _to,\r\n            votePowerRevoked,\r\n            _blockNumber\r\n        );\r\n\r\n        // Emit revoke event\r\n        emit Revoke(_from, _to, votePowerRevoked, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Transmit `_amount` of vote power `_from` address `_to` address.\r\n     * @param _from The address of the sender.\r\n     * @param _to The address of the receiver.\r\n     * @param _fromCurrentBalance The current token balance of the transmitter.\r\n     * @param _toCurrentBalance The current token balance of the receiver.\r\n     * @param _amount The amount of vote power to transmit.\r\n     */\r\n    function _transmitVotePower(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromCurrentBalance,\r\n        uint256 _toCurrentBalance,\r\n        uint256 _amount\r\n    ) internal {\r\n        _burnVotePower(_from, _fromCurrentBalance, _amount);\r\n        _mintVotePower(_to, _toCurrentBalance, _amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all vote power by percentage for `delegation` of `_who`.\r\n     * @param _from The address of the delegator\r\n     * @param _senderCurrentBalance The current balance of message sender.\r\n     * precondition: delegationModes[_who] == DelegationMode.PERCENTAGE\r\n     */\r\n    function _undelegateAllByPercentage(\r\n        address _from,\r\n        uint256 _senderCurrentBalance\r\n    ) internal {\r\n        DelegationMode delegationMode = delegationModes[_from];\r\n        if (delegationMode == DelegationMode.NOTSET) return;\r\n        require(\r\n            delegationMode == DelegationMode.PERCENTAGE,\r\n            \"undelegateAll can only be used in percentage delegation mode\"\r\n        );\r\n\r\n        PercentageDelegation.DelegationState\r\n            storage delegation = percentageDelegations[_from];\r\n\r\n        // Iterate over the delegates\r\n        (address[] memory delegates, uint256[] memory _bips) = delegation\r\n            .getDelegations();\r\n        for (uint256 i = 0; i < delegates.length; i++) {\r\n            address to = delegates[i];\r\n            // Compute vote power to be reversed for the delegate\r\n            uint256 reverseVotePower = _senderCurrentBalance.mulDiv(\r\n                _bips[i],\r\n                PercentageDelegation.MAX_BIPS\r\n            );\r\n            // Transmit vote power back to _owner\r\n            votePower.undelegate(_from, to, reverseVotePower);\r\n            votePower.cleanupOldCheckpoints(\r\n                _from,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            votePower.cleanupOldCheckpoints(\r\n                to,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            // Emit vote power reversal event\r\n            emit Delegate(_from, to, reverseVotePower, 0);\r\n        }\r\n\r\n        // Clear delegates\r\n        delegation.clear();\r\n        delegation.cleanupOldCheckpoints(CLEANUP_COUNT, cleanupBlockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all vote power by amount delegates for `_from`.\r\n     * @param _from The address of the delegator\r\n     * @param _delegateAddresses Explicit delegation does not store delegatees' addresses,\r\n     *   so the caller must supply them.\r\n     */\r\n    function _undelegateAllByAmount(\r\n        address _from,\r\n        address[] memory _delegateAddresses\r\n    ) internal returns (uint256 _remainingDelegation) {\r\n        DelegationMode delegationMode = delegationModes[_from];\r\n        if (delegationMode == DelegationMode.NOTSET) return 0;\r\n        require(\r\n            delegationMode == DelegationMode.AMOUNT,\r\n            \"undelegateAllExplicit can only be used in explicit delegation mode\"\r\n        );\r\n\r\n        ExplicitDelegation.DelegationState\r\n            storage delegation = explicitDelegations[_from];\r\n\r\n        // Iterate over the delegates\r\n        for (uint256 i = 0; i < _delegateAddresses.length; i++) {\r\n            address to = _delegateAddresses[i];\r\n            // Compute vote power _to be reversed for the delegate\r\n            uint256 reverseVotePower = delegation.getDelegatedValue(to);\r\n            if (reverseVotePower == 0) continue;\r\n            // Transmit vote power back _to _owner\r\n            votePower.undelegate(_from, to, reverseVotePower);\r\n            votePower.cleanupOldCheckpoints(\r\n                _from,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            votePower.cleanupOldCheckpoints(\r\n                to,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            // change delagation\r\n            delegation.addReplaceDelegate(to, 0);\r\n            delegation.cleanupOldCheckpoints(\r\n                to,\r\n                CLEANUP_COUNT,\r\n                cleanupBlockNumber\r\n            );\r\n            // Emit vote power reversal event\r\n            emit Delegate(_from, to, reverseVotePower, 0);\r\n        }\r\n\r\n        return delegation.getDelegatedTotal();\r\n    }\r\n\r\n    /**\r\n     * @notice Check if the `_owner` has made any delegations.\r\n     * @param _owner The address of owner to get delegated vote power.\r\n     * @return The total delegated vote power at block.\r\n     */\r\n    function _hasAnyDelegations(address _owner) internal view returns (bool) {\r\n        DelegationMode delegationMode = delegationModes[_owner];\r\n        if (delegationMode == DelegationMode.NOTSET) {\r\n            return false;\r\n        } else if (delegationMode == DelegationMode.AMOUNT) {\r\n            return explicitDelegations[_owner].getDelegatedTotal() > 0;\r\n        } else {\r\n            // delegationMode == DelegationMode.PERCENTAGE\r\n            return percentageDelegations[_owner].getCount() > 0;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total delegated vote power of `_owner` at some block.\r\n     * @param _owner The address of owner to get delegated vote power.\r\n     * @param _ownerBalanceAt The balance of the owner at that block (not their vote power).\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePower The total delegated vote power at block.\r\n     */\r\n    function _delegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _ownerBalanceAt,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _votePower)\r\n    {\r\n        // Get the vote power delegation for the _owner\r\n        DelegationMode delegationMode = delegationModes[_owner];\r\n        if (delegationMode == DelegationMode.NOTSET) {\r\n            return 0;\r\n        } else if (delegationMode == DelegationMode.AMOUNT) {\r\n            return\r\n                explicitDelegations[_owner].getDelegatedTotalAt(_blockNumber);\r\n        } else {\r\n            // delegationMode == DelegationMode.PERCENTAGE\r\n            return\r\n                percentageDelegations[_owner].getDelegatedTotalAmountAt(\r\n                    _ownerBalanceAt,\r\n                    _blockNumber\r\n                );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner` at some block.\r\n     * @param _owner The address of owner to get undelegated vote power.\r\n     * @param _ownerBalanceAt The balance of the owner at that block (not their vote power).\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePower The undelegated vote power at block.\r\n     */\r\n    function _undelegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _ownerBalanceAt,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _votePower)\r\n    {\r\n        // Return the current balance less delegations or zero if negative\r\n        uint256 delegated = _delegatedVotePowerOfAt(\r\n            _owner,\r\n            _ownerBalanceAt,\r\n            _blockNumber\r\n        );\r\n        bool overflow;\r\n        uint256 result;\r\n        (overflow, result) = _ownerBalanceAt.trySub(delegated);\r\n        return result;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner`.\r\n     * @param _owner The address of owner to get undelegated vote power.\r\n     * @param _ownerCurrentBalance The current balance of the owner (not their vote power).\r\n     * @return _votePower The undelegated vote power.\r\n     */\r\n    function _undelegatedVotePowerOf(\r\n        address _owner,\r\n        uint256 _ownerCurrentBalance\r\n    ) internal view returns (uint256 _votePower) {\r\n        return\r\n            _undelegatedVotePowerOfAt(\r\n                _owner,\r\n                _ownerCurrentBalance,\r\n                block.number\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get current delegated vote power `_from` delegator delegated `_to` delegatee.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @return _votePower The delegated vote power.\r\n     */\r\n    function _votePowerFromTo(\r\n        address _from,\r\n        address _to,\r\n        uint256 _currentFromBalance\r\n    ) internal view returns (uint256 _votePower) {\r\n        DelegationMode delegationMode = delegationModes[_from];\r\n        if (delegationMode == DelegationMode.NOTSET) {\r\n            return 0;\r\n        } else if (delegationMode == DelegationMode.PERCENTAGE) {\r\n            uint256 _bips = percentageDelegations[_from].getDelegatedValue(_to);\r\n            return\r\n                _currentFromBalance.mulDiv(\r\n                    _bips,\r\n                    PercentageDelegation.MAX_BIPS\r\n                );\r\n        } else {\r\n            // delegationMode == DelegationMode.AMOUNT\r\n            return explicitDelegations[_from].getDelegatedValue(_to);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _fromBalanceAt From's balance at the block `_blockNumber`.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePower The delegated vote power.\r\n     */\r\n    function _votePowerFromToAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromBalanceAt,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256 _votePower)\r\n    {\r\n        // if revoked, return 0\r\n        if (votePowerCache.revokedFromToAt(_from, _to, _blockNumber)) return 0;\r\n        return\r\n            _votePowerFromToAtNoRevokeCheck(\r\n                _from,\r\n                _to,\r\n                _fromBalanceAt,\r\n                _blockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     *   Private use only - ignores revocations.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _fromBalanceAt From's balance at the block `_blockNumber`.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePower The delegated vote power.\r\n     */\r\n    function _votePowerFromToAtNoRevokeCheck(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromBalanceAt,\r\n        uint256 _blockNumber\r\n    ) private view returns (uint256 _votePower) {\r\n        // assumed: notBeforeCleanupBlock(_blockNumber)\r\n        DelegationMode delegationMode = delegationModes[_from];\r\n        if (delegationMode == DelegationMode.NOTSET) {\r\n            return 0;\r\n        } else if (delegationMode == DelegationMode.PERCENTAGE) {\r\n            uint256 _bips = percentageDelegations[_from].getDelegatedValueAt(\r\n                _to,\r\n                _blockNumber\r\n            );\r\n            return _fromBalanceAt.mulDiv(_bips, PercentageDelegation.MAX_BIPS);\r\n        } else {\r\n            // delegationMode == DelegationMode.AMOUNT\r\n            return\r\n                explicitDelegations[_from].getDelegatedValueAt(\r\n                    _to,\r\n                    _blockNumber\r\n                );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_who`.\r\n     * @param _who The address to get voting power.\r\n     * @return Current vote power of `_who`.\r\n     */\r\n    function _votePowerOf(address _who) internal view returns (uint256) {\r\n        return votePower.votePowerOfAtNow(_who);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function _votePowerOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal view notBeforeCleanupBlock(_blockNumber) returns (uint256) {\r\n        // read cached value for past blocks to respect revocations (and possibly get a cache speedup)\r\n        if (_blockNumber < block.number) {\r\n            return\r\n                votePowerCache.valueOfAtReadonly(votePower, _who, _blockNumber);\r\n        } else {\r\n            return votePower.votePowerOfAtNow(_who);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`, ignoring revocation information (and cache).\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`. Result doesn't change if vote power is revoked.\r\n     */\r\n    function _votePowerOfAtIgnoringRevocation(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal view notBeforeCleanupBlock(_blockNumber) returns (uint256) {\r\n        return votePower.votePowerOfAt(_who, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * Return vote powers for several addresses in a batch.\r\n     * Only works for past blocks.\r\n     * @param _owners The list of addresses to fetch vote power of.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePowers A list of vote powers corresponding to _owners.\r\n     */\r\n    function _batchVotePowerOfAt(\r\n        address[] memory _owners,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        notBeforeCleanupBlock(_blockNumber)\r\n        returns (uint256[] memory _votePowers)\r\n    {\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Can only be used for past blocks\"\r\n        );\r\n        _votePowers = new uint256[](_owners.length);\r\n        for (uint256 i = 0; i < _owners.length; i++) {\r\n            // read through cache, much faster if it has been set\r\n            _votePowers[i] = votePowerCache.valueOfAtReadonly(\r\n                votePower,\r\n                _owners[i],\r\n                _blockNumber\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     *   Reads/updates cache and upholds revocations.\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function _votePowerOfAtCached(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal notBeforeCleanupBlock(_blockNumber) returns (uint256) {\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Can only be used for past blocks\"\r\n        );\r\n        (uint256 vp, bool createdCache) = votePowerCache.valueOfAt(\r\n            votePower,\r\n            _who,\r\n            _blockNumber\r\n        );\r\n        if (createdCache) emit CreatedVotePowerCache(_who, _blockNumber);\r\n        return vp;\r\n    }\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     */\r\n    function _setCleanupBlockNumber(uint256 _blockNumber) internal {\r\n        require(\r\n            _blockNumber >= cleanupBlockNumber,\r\n            \"Cleanup block number must never decrease\"\r\n        );\r\n        require(\r\n            _blockNumber < block.number,\r\n            \"Cleanup block must be in the past\"\r\n        );\r\n        cleanupBlockNumber = _blockNumber;\r\n    }\r\n\r\n    /**\r\n     * Get the cleanup block number.\r\n     */\r\n    function _cleanupBlockNumber() internal view returns (uint256) {\r\n        return cleanupBlockNumber;\r\n    }\r\n\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     */\r\n    function _setCleanerContract(address _cleanerContract) internal {\r\n        cleanerContract = _cleanerContract;\r\n    }\r\n\r\n    // history cleanup methods\r\n\r\n    /**\r\n     * Delete vote power checkpoints that expired (i.e. are before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _owner vote power owner account address\r\n     * @param _count maximum number of checkpoints to delete\r\n     * @return the number of checkpoints deleted\r\n     */\r\n    function votePowerHistoryCleanup(\r\n        address _owner,\r\n        uint256 _count\r\n    ) external onlyCleaner returns (uint256) {\r\n        return\r\n            votePower.cleanupOldCheckpoints(_owner, _count, cleanupBlockNumber);\r\n    }\r\n\r\n    /**\r\n     * Delete vote power cache entry that expired (i.e. is before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _owner vote power owner account address\r\n     * @param _blockNumber the block number for which total supply value was cached\r\n     * @return the number of cache entries deleted (always 0 or 1)\r\n     */\r\n    function votePowerCacheCleanup(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external onlyCleaner returns (uint256) {\r\n        require(\r\n            _blockNumber < cleanupBlockNumber,\r\n            \"No cleanup after cleanup block\"\r\n        );\r\n        return votePowerCache.deleteValueAt(_owner, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * Delete revocation entry that expired (i.e. is before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _from the delegator address\r\n     * @param _to the delegatee address\r\n     * @param _blockNumber the block number for which total supply value was cached\r\n     * @return the number of revocation entries deleted (always 0 or 1)\r\n     */\r\n    function revocationCleanup(\r\n        address _from,\r\n        address _to,\r\n        uint256 _blockNumber\r\n    ) external onlyCleaner returns (uint256) {\r\n        require(\r\n            _blockNumber < cleanupBlockNumber,\r\n            \"No cleanup after cleanup block\"\r\n        );\r\n        return votePowerCache.deleteRevocationAt(_from, _to, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * Delete percentage delegation checkpoints that expired (i.e. are before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _owner balance owner account address\r\n     * @param _count maximum number of checkpoints to delete\r\n     * @return the number of checkpoints deleted\r\n     */\r\n    function percentageDelegationHistoryCleanup(\r\n        address _owner,\r\n        uint256 _count\r\n    ) external onlyCleaner returns (uint256) {\r\n        return\r\n            percentageDelegations[_owner].cleanupOldCheckpoints(\r\n                _count,\r\n                cleanupBlockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * Delete explicit delegation checkpoints that expired (i.e. are before `cleanupBlockNumber`).\r\n     * Method can only be called from the `cleanerContract` (which may be a proxy to external cleaners).\r\n     * @param _from the delegator address\r\n     * @param _to the delegatee address\r\n     * @param _count maximum number of checkpoints to delete\r\n     * @return the number of checkpoints deleted\r\n     */\r\n    function explicitDelegationHistoryCleanup(\r\n        address _from,\r\n        address _to,\r\n        uint256 _count\r\n    ) external onlyCleaner returns (uint256) {\r\n        return\r\n            explicitDelegations[_from].cleanupOldCheckpoints(\r\n                _to,\r\n                _count,\r\n                cleanupBlockNumber\r\n            );\r\n    }\r\n}\r\n"
      },
      "contracts/Governed.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport {GovernedBase} from \"./GovernedBase.sol\";\r\n\r\n/**\r\n * @title Governed\r\n * @dev For deployed, governed contracts, enforce a non-zero address at create time.\r\n **/\r\ncontract Governed is GovernedBase {\r\n    constructor(address _governance) GovernedBase(_governance) {\r\n        require(_governance != address(0), \"_governance zero\");\r\n    }\r\n}\r\n"
      },
      "contracts/GovernedBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./interfaces/IGovernanceSettings.sol\";\r\n\r\n/**\r\n * @title Governed Base\r\n * @notice This abstract base class defines behaviors for a governed contract.\r\n * @dev This class is abstract so that specific behaviors can be defined for the constructor.\r\n *   Contracts should not be left ungoverned, but not all contract will have a constructor\r\n *   (for example those pre-defined in genesis).\r\n **/\r\nabstract contract GovernedBase {\r\n    struct TimelockedCall {\r\n        uint256 allowedAfterTimestamp;\r\n        bytes encodedCall;\r\n    }\r\n\r\n    // solhint-disable-next-line const-name-snakecase\r\n    IGovernanceSettings public governanceSettings =\r\n        IGovernanceSettings(0x1000000000000000000000000000000000000007);\r\n\r\n    address private initialGovernance;\r\n\r\n    bool private initialised;\r\n\r\n    bool public productionMode;\r\n\r\n    bool private executing;\r\n\r\n    mapping(bytes4 => TimelockedCall) public timelockedCalls;\r\n\r\n    event GovernanceCallTimelocked(\r\n        bytes4 selector,\r\n        uint256 allowedAfterTimestamp,\r\n        bytes encodedCall\r\n    );\r\n    event TimelockedGovernanceCallExecuted(bytes4 selector, uint256 timestamp);\r\n    event TimelockedGovernanceCallCanceled(bytes4 selector, uint256 timestamp);\r\n\r\n    event GovernanceInitialised(address initialGovernance);\r\n    event GovernedProductionModeEntered(address governanceSettings);\r\n    event updateGovernanceAddress(address governanceSettings);\r\n\r\n    modifier onlyGovernance() {\r\n        if (executing || !productionMode) {\r\n            _beforeExecute();\r\n            _;\r\n        } else {\r\n            _recordTimelockedCall(msg.data);\r\n        }\r\n    }\r\n\r\n    modifier onlyImmediateGovernance() {\r\n        _checkOnlyGovernance();\r\n        _;\r\n    }\r\n\r\n    constructor(address _initialGovernance) {\r\n        if (_initialGovernance != address(0)) {\r\n            initialise(_initialGovernance);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Execute the timelocked governance calls once the timelock period expires.\r\n     * @dev Only executor can call this method.\r\n     * @param _selector The method selector (only one timelocked call per method is stored).\r\n     */\r\n    function executeGovernanceCall(bytes4 _selector) external {\r\n        require(governanceSettings.isExecutor(msg.sender), \"only executor\");\r\n        TimelockedCall storage call = timelockedCalls[_selector];\r\n        require(call.allowedAfterTimestamp != 0, \"timelock: invalid selector\");\r\n        require(\r\n            block.timestamp >= call.allowedAfterTimestamp,\r\n            \"timelock: not allowed yet\"\r\n        );\r\n        bytes memory encodedCall = call.encodedCall;\r\n        delete timelockedCalls[_selector];\r\n        executing = true;\r\n        //solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, ) = address(this).call(encodedCall);\r\n        executing = false;\r\n        emit TimelockedGovernanceCallExecuted(_selector, block.timestamp);\r\n        _passReturnOrRevert(success);\r\n    }\r\n\r\n    /**\r\n     * Cancel a timelocked governance call before it has been executed.\r\n     * @dev Only governance can call this method.\r\n     * @param _selector The method selector.\r\n     */\r\n    function cancelGovernanceCall(\r\n        bytes4 _selector\r\n    ) external onlyImmediateGovernance {\r\n        require(\r\n            timelockedCalls[_selector].allowedAfterTimestamp != 0,\r\n            \"timelock: invalid selector\"\r\n        );\r\n        emit TimelockedGovernanceCallCanceled(_selector, block.timestamp);\r\n        delete timelockedCalls[_selector];\r\n    }\r\n\r\n    /**\r\n     * Enter the production mode after all the initial governance settings have been set.\r\n     * This enables timelocks and the governance is afterwards obtained by calling\r\n     * governanceSettings.getGovernanceAddress().\r\n     */\r\n    function switchToProductionMode() external {\r\n        _checkOnlyGovernance();\r\n        require(!productionMode, \"already in production mode\");\r\n        initialGovernance = address(0);\r\n        productionMode = true;\r\n        emit GovernedProductionModeEntered(address(governanceSettings));\r\n    }\r\n\r\n    /**\r\n     * Update governance address\r\n     */\r\n    function updateGovernance(address newGovernance) external {\r\n        _checkOnlyGovernance();\r\n        governanceSettings = IGovernanceSettings(newGovernance);\r\n        emit updateGovernanceAddress(address(governanceSettings));\r\n    }\r\n\r\n    /**\r\n     * @notice Initialize the governance address if not first initialized.\r\n     */\r\n    function initialise(address _initialGovernance) public virtual {\r\n        require(initialised == false, \"initialised != false\");\r\n        initialised = true;\r\n        initialGovernance = _initialGovernance;\r\n        emit GovernanceInitialised(_initialGovernance);\r\n    }\r\n\r\n    /**\r\n     * Returns the current effective governance address.\r\n     */\r\n    function governance() public view returns (address) {\r\n        return\r\n            productionMode\r\n                ? governanceSettings.getGovernanceAddress()\r\n                : initialGovernance;\r\n    }\r\n\r\n    function _beforeExecute() private {\r\n        if (executing) {\r\n            // can only be run from executeGovernanceCall(), where we check that only executor can call\r\n            // make sure nothing else gets executed, even in case of reentrancy\r\n            assert(msg.sender == address(this));\r\n            executing = false;\r\n        } else {\r\n            // must be called with: productionMode=false\r\n            // must check governance in this case\r\n            _checkOnlyGovernance();\r\n        }\r\n    }\r\n\r\n    function _recordTimelockedCall(bytes calldata _data) private {\r\n        _checkOnlyGovernance();\r\n        bytes4 selector;\r\n        //solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            selector := calldataload(_data.offset)\r\n        }\r\n        uint256 timelock = governanceSettings.getTimelock();\r\n        uint256 allowedAt = block.timestamp + timelock;\r\n        timelockedCalls[selector] = TimelockedCall({\r\n            allowedAfterTimestamp: allowedAt,\r\n            encodedCall: _data\r\n        });\r\n        emit GovernanceCallTimelocked(selector, allowedAt, _data);\r\n    }\r\n\r\n    function _checkOnlyGovernance() private view {\r\n        require(msg.sender == governance(), \"only governance\");\r\n    }\r\n\r\n    function _passReturnOrRevert(bool _success) private pure {\r\n        // pass exact return or revert data - needs to be done in assembly\r\n        //solhint-disable-next-line no-inline-assembly\r\n        assembly {\r\n            let size := returndatasize()\r\n            let ptr := mload(0x40)\r\n            mstore(0x40, add(ptr, size))\r\n            returndatacopy(ptr, 0, size)\r\n            if _success {\r\n                return(ptr, size)\r\n            }\r\n            revert(ptr, size)\r\n        }\r\n    }\r\n}\r\n"
      },
      "contracts/interfaces/IGovernanceSettings.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\n/**\r\n * A special contract that holds WFO governance address.\r\n * This contract enables updating governance address and timelock only by hard forking the network,\r\n * meaning only by updating validator code.\r\n */\r\ninterface IGovernanceSettings {\r\n    /**\r\n     * Get the governance account address.\r\n     * The governance address can only be changed by a hardfork.\r\n     */\r\n    function getGovernanceAddress() external view returns (address);\r\n\r\n    /**\r\n     * Get the time in seconds that must pass between a governance call and execution.\r\n     * The timelock value can only be changed by a hardfork.\r\n     */\r\n    function getTimelock() external view returns (uint256);\r\n\r\n    /**\r\n     * Get the addresses of the accounts that are allowed to execute the timelocked governance calls\r\n     * once the timelock period expires.\r\n     * Executors can be changed without a hardfork, via a normal governance call.\r\n     */\r\n    function getExecutors() external view returns (address[] memory);\r\n\r\n    /**\r\n     * Check whether an address is one of the executors.\r\n     */\r\n    function isExecutor(address _address) external view returns (bool);\r\n}\r\n"
      },
      "contracts/interfaces/IGovernanceVotePower.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\ninterface IGovernanceVotePower {\r\n    /**\r\n     * @notice Delegate all governance vote power of `msg.sender` to `_to`.\r\n     * @param _to The address of the recipient\r\n     **/\r\n    function delegate(address _to) external;\r\n\r\n    /**\r\n     * @notice Undelegate all governance vote power of `msg.sender``.\r\n     **/\r\n    function undelegate() external;\r\n\r\n    /**\r\n     * @notice Get the governance vote power of `_who` at block `_blockNumber`\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePower    Governance vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `account` at the current block.\r\n     * @param account The address to get voting power.\r\n     * @return Vote power of `account` at the current block number.\r\n     */\r\n    function getVotes(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the delegate's address of `_who` at block `_blockNumber`\r\n     * @param _who The address to get delegate's address.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Delegate's address of `_who` at `_blockNumber`.\r\n     */\r\n    function getDelegateOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external view returns (address);\r\n\r\n    /**\r\n     * @notice Get the delegate's address of `_who` at the current block.\r\n     * @param _who The address to get delegate's address.\r\n     * @return Delegate's address of `_who` at the current block number.\r\n     */\r\n    function getDelegateOfAtNow(address _who) external view returns (address);\r\n}\r\n"
      },
      "contracts/interfaces/IICleanable.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\ninterface IICleanable {\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     */\r\n    function setCleanerContract(address _cleanerContract) external;\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     * Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n     * history before that block should never be used since it can be inconsistent.\r\n     * In particular, cleanup block number must be before current vote power block.\r\n     * @param _blockNumber The new cleanup block number.\r\n     */\r\n    function setCleanupBlockNumber(uint256 _blockNumber) external;\r\n\r\n    /**\r\n     * Get the current cleanup block number.\r\n     */\r\n    function cleanupBlockNumber() external view returns (uint256);\r\n}\r\n"
      },
      "contracts/interfaces/IIGovernanceVotePower.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\nimport \"./IVPToken.sol\";\r\nimport \"./IGovernanceVotePower.sol\";\r\n\r\ninterface IIGovernanceVotePower is IGovernanceVotePower {\r\n    /**\r\n     * Event triggered when an delegator's balance changes.\r\n     *\r\n     * Note: the event is always emitted from `GovernanceVotePower`.\r\n     */\r\n    event DelegateVotesChanged(\r\n        address indexed delegate,\r\n        uint256 previousBalance,\r\n        uint256 newBalance\r\n    );\r\n\r\n    /**\r\n     * Event triggered when an account delegates to another account.\r\n     *\r\n     * Note: the event is always emitted from `GovernanceVotePower`.\r\n     */\r\n    event DelegateChanged(\r\n        address indexed delegator,\r\n        address indexed fromDelegate,\r\n        address indexed toDelegate\r\n    );\r\n\r\n    /**\r\n     * Update vote powers when tokens are transfered.\r\n     **/\r\n    function updateAtTokenTransfer(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromBalance,\r\n        uint256 _toBalance,\r\n        uint256 _amount\r\n    ) external;\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     * Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n     * history before that block should never be used since it can be inconsistent.\r\n     * In particular, cleanup block number must be before current vote power block.\r\n     * @param _blockNumber The new cleanup block number.\r\n     */\r\n    function setCleanupBlockNumber(uint256 _blockNumber) external;\r\n\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     */\r\n    function setCleanerContract(address _cleanerContract) external;\r\n\r\n    /**\r\n     * @notice Get the token that this governance vote power contract belongs to.\r\n     */\r\n    function ownerToken() external view returns (IVPToken);\r\n\r\n    function getCleanupBlockNumber() external view returns (uint256);\r\n}\r\n"
      },
      "contracts/interfaces/IIVPContract.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\nimport \"./IVPToken.sol\";\r\nimport \"./IVPContractEvents.sol\";\r\nimport \"./IICleanable.sol\";\r\n\r\ninterface IIVPContract is IICleanable, IVPContractEvents {\r\n    /**\r\n     * Update vote powers when tokens are transfered.\r\n     * Also update delegated vote powers for percentage delegation\r\n     * and check for enough funds for explicit delegations.\r\n     **/\r\n    function updateAtTokenTransfer(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromBalance,\r\n        uint256 _toBalance,\r\n        uint256 _amount\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Delegate `_bips` percentage of voting power to `_to` from `_from`\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _balance The delegator's current balance\r\n     * @param _bips The percentage of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 revokes delegation).\r\n     **/\r\n    function delegate(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint256 _bips\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Explicitly delegate `_amount` of voting power to `_to` from `msg.sender`.\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _balance The delegator's current balance\r\n     * @param _amount An explicit vote power amount to be delegated.\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 undelegates `to`).\r\n     **/\r\n    function delegateExplicit(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint _amount\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Revoke all delegation from sender to `_who` at given block.\r\n     *    Only affects the reads via `votePowerOfAtCached()` in the block `_blockNumber`.\r\n     *    Block `_blockNumber` must be in the past.\r\n     *    This method should be used only to prevent rogue delegate voting in the current voting block.\r\n     *    To stop delegating use delegate/delegateExplicit with value of 0 or undelegateAll/undelegateAllExplicit.\r\n     * @param _from The address of the delegator\r\n     * @param _who Address of the delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @param _blockNumber The block number at which to revoke delegation.\r\n     **/\r\n    function revokeDelegationAt(\r\n        address _from,\r\n        address _who,\r\n        uint256 _balance,\r\n        uint _blockNumber\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Undelegate all voting power for delegates of `msg.sender`\r\n     *    Can only be used with percentage delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     * @param _from The address of the delegator\r\n     **/\r\n    function undelegateAll(address _from, uint256 _balance) external;\r\n\r\n    /**\r\n     * @notice Undelegate all explicit vote power by amount delegates for `msg.sender`.\r\n     *    Can only be used with explicit delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     * @param _from The address of the delegator\r\n     * @param _delegateAddresses Explicit delegation does not store delegatees' addresses,\r\n     *   so the caller must supply them.\r\n     * @return The amount still delegated (in case the list of delegates was incomplete).\r\n     */\r\n    function undelegateAllExplicit(\r\n        address _from,\r\n        address[] memory _delegateAddresses\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     *   Reads/updates cache and upholds revocations.\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAtCached(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_who`.\r\n     * @param _who The address to get voting power.\r\n     * @return Current vote power of `_who`.\r\n     */\r\n    function votePowerOf(address _who) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`, ignoring revocation information (and cache).\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`. Result doesn't change if vote power is revoked.\r\n     */\r\n    function votePowerOfAtIgnoringRevocation(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * Return vote powers for several addresses in a batch.\r\n     * @param _owners The list of addresses to fetch vote power of.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return A list of vote powers.\r\n     */\r\n    function batchVotePowerOfAt(\r\n        address[] memory _owners,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256[] memory);\r\n\r\n    /**\r\n     * @notice Get current delegated vote power `_from` delegator delegated `_to` delegatee.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromTo(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromToAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Compute the current undelegated vote power of `_owner`\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _balance Owner's current balance\r\n     * @return The unallocated vote power of `_owner`\r\n     */\r\n    function undelegatedVotePowerOf(\r\n        address _owner,\r\n        uint256 _balance\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner` at given block.\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The undelegated vote power of `_owner` (= owner's own balance minus all delegations from owner)\r\n     */\r\n    function undelegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _balance,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the delegation mode for '_who'. This mode determines whether vote power is\r\n     *  allocated by percentage or by explicit value.\r\n     * @param _who The address to get delegation mode.\r\n     * @return Delegation mode (NOTSET=0, PERCENTAGE=1, AMOUNT=2))\r\n     */\r\n    function delegationModeOf(address _who) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `_delegateAddresses`\r\n     *  and `pcts` of an `_owner`. Returned in two separate positional arrays.\r\n     * @param _owner The address to get delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOf(\r\n        address _owner\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        );\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `pcts` of an `_owner`. Returned in two separate positional arrays.\r\n     * @param _owner The address to get delegations.\r\n     * @param _blockNumber The block for which we want to know the delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        );\r\n\r\n    /**\r\n     * The VPToken (or some other contract) that owns this VPContract.\r\n     * All state changing methods may be called only from this address.\r\n     * This is because original msg.sender is sent in `_from` parameter\r\n     * and we must be sure that it cannot be faked by directly calling VPContract.\r\n     * Owner token is also used in case of replacement to recover vote powers from balances.\r\n     */\r\n    function ownerToken() external view returns (IVPToken);\r\n\r\n    /**\r\n     * Return true if this IIVPContract is configured to be used as a replacement for other contract.\r\n     * It means that vote powers are not necessarily correct at the initialization, therefore\r\n     * every method that reads vote power must check whether it is initialized for that address and block.\r\n     */\r\n    function isReplacement() external view returns (bool);\r\n}\r\n"
      },
      "contracts/interfaces/IIVPToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\nimport \"./IVPToken.sol\";\r\nimport \"./IGovernanceVotePower.sol\";\r\nimport \"./IIVPContract.sol\";\r\nimport \"./IIGovernanceVotePower.sol\";\r\nimport \"./IICleanable.sol\";\r\n\r\ninterface IIVPToken is IVPToken, IICleanable {\r\n    /**\r\n     * Set the contract that is allowed to set cleanupBlockNumber.\r\n     * Usually this will be an instance of CleanupBlockNumberManager.\r\n     */\r\n    function setCleanupBlockNumberManager(\r\n        address _cleanupBlockNumberManager\r\n    ) external;\r\n\r\n    /**\r\n     * Sets new governance vote power contract that allows token owners to participate in governance voting\r\n     * and delegate governance vote power.\r\n     */\r\n    function setGovernanceVotePower(\r\n        IIGovernanceVotePower _governanceVotePower\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Get the total vote power at block `_blockNumber` using cache.\r\n     *   It tries to read the cached value and if not found, reads the actual value and stores it in cache.\r\n     *   Can only be used if `_blockNumber` is in the past, otherwise reverts.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The total vote power at the block (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePowerAtCached(\r\n        uint256 _blockNumber\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber` using cache.\r\n     *   It tries to read the cached value and if not found, reads the actual value and stores it in cache.\r\n     *   Can only be used if _blockNumber is in the past, otherwise reverts.\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAtCached(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * Return vote powers for several addresses in a batch.\r\n     * @param _owners The list of addresses to fetch vote power of.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return A list of vote powers.\r\n     */\r\n    function batchVotePowerOfAt(\r\n        address[] memory _owners,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256[] memory);\r\n}\r\n"
      },
      "contracts/interfaces/IVPContractEvents.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\ninterface IVPContractEvents {\r\n    /**\r\n     * Event triggered when an account delegates or undelegates another account.\r\n     * Definition: `votePowerFromTo(from, to)` is `changed` from `priorVotePower` to `newVotePower`.\r\n     * For undelegation, `newVotePower` is 0.\r\n     *\r\n     * Note: the event is always emitted from VPToken's `writeVotePowerContract`.\r\n     */\r\n    event Delegate(\r\n        address indexed from,\r\n        address indexed to,\r\n        uint256 priorVotePower,\r\n        uint256 newVotePower\r\n    );\r\n\r\n    /**\r\n     * Event triggered only when account `delegator` revokes delegation to `delegatee`\r\n     * for a single block in the past (typically the current vote block).\r\n     *\r\n     * Note: the event is always emitted from VPToken's `writeVotePowerContract` and/or `readVotePowerContract`.\r\n     */\r\n    event Revoke(\r\n        address indexed delegator,\r\n        address indexed delegatee,\r\n        uint256 votePower,\r\n        uint256 blockNumber\r\n    );\r\n}\r\n"
      },
      "contracts/interfaces/IVPToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport {IGovernanceVotePower} from \"./IGovernanceVotePower.sol\";\r\nimport {IVPContractEvents} from \"./IVPContractEvents.sol\";\r\n\r\ninterface IVPToken is IERC20 {\r\n    /**\r\n     * @notice Delegate by percentage `_bips` of voting power to `_to` from `msg.sender`.\r\n     * @param _to The address of the recipient\r\n     * @param _bips The percentage of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 undelegates `to`).\r\n     **/\r\n    function delegate(address _to, uint256 _bips) external;\r\n\r\n    /**\r\n     * @notice Undelegate all percentage delegations from teh sender and then delegate corresponding\r\n     *   `_bips` percentage of voting power from the sender to each member of `_delegatees`.\r\n     * @param _delegatees The addresses of the new recipients.\r\n     * @param _bips The percentages of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Total of all `_bips` values must be at most 10000.\r\n     **/\r\n    function batchDelegate(\r\n        address[] memory _delegatees,\r\n        uint256[] memory _bips\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Explicitly delegate `_amount` of voting power to `_to` from `msg.sender`.\r\n     * @param _to The address of the recipient\r\n     * @param _amount An explicit vote power amount to be delegated.\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 undelegates `to`).\r\n     **/\r\n    function delegateExplicit(address _to, uint _amount) external;\r\n\r\n    /**\r\n     * @notice Revoke all delegation from sender to `_who` at given block.\r\n     *    Only affects the reads via `votePowerOfAtCached()` in the block `_blockNumber`.\r\n     *    Block `_blockNumber` must be in the past.\r\n     *    This method should be used only to prevent rogue delegate voting in the current voting block.\r\n     *    To stop delegating use delegate/delegateExplicit with value of 0 or undelegateAll/undelegateAllExplicit.\r\n     * @param _who Address of the delegatee\r\n     * @param _blockNumber The block number at which to revoke delegation.\r\n     */\r\n    function revokeDelegationAt(address _who, uint _blockNumber) external;\r\n\r\n    /**\r\n     * @notice Undelegate all voting power for delegates of `msg.sender`\r\n     *    Can only be used with percentage delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     **/\r\n    function undelegateAll() external;\r\n\r\n    /**\r\n     * @notice Undelegate all explicit vote power by amount delegates for `msg.sender`.\r\n     *    Can only be used with explicit delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     * @param _delegateAddresses Explicit delegation does not store delegatees' addresses,\r\n     *   so the caller must supply them.\r\n     * @return The amount still delegated (in case the list of delegates was incomplete).\r\n     */\r\n    function undelegateAllExplicit(\r\n        address[] memory _delegateAddresses\r\n    ) external returns (uint256);\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function name() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function symbol() external view returns (string memory);\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function decimals() external view returns (uint8);\r\n\r\n    /**\r\n     * @notice Total amount of tokens at a specific `_blockNumber`.\r\n     * @param _blockNumber The block number when the totalSupply is queried\r\n     * @return The total amount of tokens at `_blockNumber`\r\n     **/\r\n    function totalSupplyAt(uint _blockNumber) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Queries the token balance of `_owner` at a specific `_blockNumber`.\r\n     * @param _owner The address from which the balance will be retrieved.\r\n     * @param _blockNumber The block number when the balance is queried.\r\n     * @return The balance at `_blockNumber`.\r\n     **/\r\n    function balanceOfAt(\r\n        address _owner,\r\n        uint _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the current total vote power.\r\n     * @return The current total vote power (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePower() external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the total vote power at block `_blockNumber`\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The total vote power at the block  (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePowerAt(\r\n        uint _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_owner`.\r\n     * @param _owner The address to get voting power.\r\n     * @return Current vote power of `_owner`.\r\n     */\r\n    function votePowerOf(address _owner) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber`\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber`, ignoring revocation information (and cache).\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`. Result doesn't change if vote power is revoked.\r\n     */\r\n    function votePowerOfAtIgnoringRevocation(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the delegation mode for '_who'. This mode determines whether vote power is\r\n     *  allocated by percentage or by explicit value. Once the delegation mode is set,\r\n     *  it never changes, even if all delegations are removed.\r\n     * @param _who The address to get delegation mode.\r\n     * @return delegation mode: 0 = NOTSET, 1 = PERCENTAGE, 2 = AMOUNT (i.e. explicit)\r\n     */\r\n    function delegationModeOf(address _who) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get current delegated vote power `_from` delegator delegated `_to` delegatee.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromTo(\r\n        address _from,\r\n        address _to\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromToAt(\r\n        address _from,\r\n        address _to,\r\n        uint _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Compute the current undelegated vote power of `_owner`\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @return The unallocated vote power of `_owner`\r\n     */\r\n    function undelegatedVotePowerOf(\r\n        address _owner\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner` at given block.\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The undelegated vote power of `_owner` (= owner's own balance minus all delegations from owner)\r\n     */\r\n    function undelegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view returns (uint256);\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `_bips` of `_who`. Returned in two separate positional arrays.\r\n     * @param _who The address to get delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOf(\r\n        address _who\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        );\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `pcts` of `_who`. Returned in two separate positional arrays.\r\n     * @param _who The address to get delegations.\r\n     * @param _blockNumber The block for which we want to know the delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        );\r\n\r\n    /**\r\n     * Returns VPContract used for readonly operations (view methods).\r\n     * The only non-view method that might be called on it is `revokeDelegationAt`.\r\n     *\r\n     * @notice `readVotePowerContract` is almost always equal to `writeVotePowerContract`\r\n     * except during upgrade from one VPContract to a new version (which should happen\r\n     * rarely or never and will be anounced before).\r\n     *\r\n     * @notice You shouldn't call any methods on VPContract directly, all are exposed\r\n     * via VPToken (and state changing methods are forbidden from direct calls).\r\n     * This is the reason why this method returns `IVPContractEvents` - it should only be used\r\n     * for listening to events (`Revoke` only).\r\n     */\r\n    function readVotePowerContract() external view returns (IVPContractEvents);\r\n\r\n    /**\r\n     * Returns VPContract used for state changing operations (non-view methods).\r\n     * The only non-view method that might be called on it is `revokeDelegationAt`.\r\n     *\r\n     * @notice `writeVotePowerContract` is almost always equal to `readVotePowerContract`\r\n     * except during upgrade from one VPContract to a new version (which should happen\r\n     * rarely or never and will be anounced before). In the case of upgrade,\r\n     * `writeVotePowerContract` will be replaced first to establish delegations, and\r\n     * after some perio (e.g. after a reward epoch ends) `readVotePowerContract` will be set equal to it.\r\n     *\r\n     * @notice You shouldn't call any methods on VPContract directly, all are exposed\r\n     * via VPToken (and state changing methods are forbidden from direct calls).\r\n     * This is the reason why this method returns `IVPContractEvents` - it should only be used\r\n     * for listening to events (`Delegate` and `Revoke` only).\r\n     */\r\n    function writeVotePowerContract() external view returns (IVPContractEvents);\r\n\r\n    /**\r\n     * When set, allows token owners to participate in governance voting\r\n     * and delegate governance vote power.\r\n     */\r\n    function governanceVotePower() external view returns (IGovernanceVotePower);\r\n}\r\n"
      },
      "contracts/interfaces/IWNat.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity >=0.7.6 <0.9;\r\n\r\ninterface IWNat {\r\n    /**\r\n     * @notice Deposit wfo token and mint WNAT ERC20.\r\n     */\r\n    function deposit(uint256 _amount) external;\r\n\r\n    /**\r\n     * @notice Withdraw wfo token and burn WNAT ERC20.\r\n     * @param _amount The amount to withdraw.\r\n     */\r\n    function withdraw(uint256 _amount) external;\r\n\r\n    /**\r\n     * @notice Deposit wfo token from msg.sender and mint WNAT ERC20.\r\n     * @param _recipient An address to receive minted WNAT.\r\n     */\r\n    function depositTo(address _recipient, uint256 _amount) external;\r\n\r\n    /**\r\n     * @notice Withdraw WNAT from an owner and send wfo to msg.sender given an allowance.\r\n     * @param _owner An address spending the wfo tokens.\r\n     * @param _amount The amount to spend.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `_owner` must have a balance of at least `_amount`.\r\n     * - the caller must have allowance for `_owners`'s tokens of at least\r\n     * `_amount`.\r\n     */\r\n    function withdrawFrom(address _owner, uint256 _amount) external;\r\n}\r\n"
      },
      "contracts/lib/CheckPointHistory.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\r\n\r\n/**\r\n * @title Check Point History library\r\n * @notice A contract to manage checkpoints as of a given block.\r\n * @dev Store value history by block number with detachable state.\r\n **/\r\nlibrary CheckPointHistory {\r\n    using SafeMath for uint256;\r\n    using SafeCast for uint256;\r\n\r\n    /**\r\n     * @dev `CheckPoint` is the structure that attaches a block number to a\r\n     *  given value; the block number attached is the one that last changed the\r\n     *  value\r\n     **/\r\n    struct CheckPoint {\r\n        // `value` is the amount of tokens at a specific block number\r\n        uint192 value;\r\n        // `fromBlock` is the block number that the value was generated from\r\n        uint64 fromBlock;\r\n    }\r\n\r\n    struct CheckPointHistoryState {\r\n        // `checkpoints` is an array that tracks values at non-contiguous block numbers\r\n        mapping(uint256 => CheckPoint) checkpoints;\r\n        // `checkpoints` before `startIndex` have been deleted\r\n        // INVARIANT: checkpoints.endIndex == 0 || startIndex < checkpoints.endIndex      (strict!)\r\n        // startIndex and endIndex are both less then fromBlock, so 64 bits is enough\r\n        uint64 startIndex;\r\n        // the index AFTER last\r\n        uint64 endIndex;\r\n    }\r\n\r\n    /**\r\n     * @notice Binary search of _checkpoints array.\r\n     * @param _checkpoints An array of CheckPoint to search.\r\n     * @param _startIndex Smallest possible index to be returned.\r\n     * @param _blockNumber The block number to search for.\r\n     */\r\n    function _indexOfGreatestBlockLessThan(\r\n        mapping(uint256 => CheckPoint) storage _checkpoints,\r\n        uint256 _startIndex,\r\n        uint256 _endIndex,\r\n        uint256 _blockNumber\r\n    ) private view returns (uint256 index) {\r\n        // Binary search of the value by given block number in the array\r\n        uint256 min = _startIndex;\r\n        uint256 max = _endIndex.sub(1);\r\n        while (max > min) {\r\n            uint256 mid = (max.add(min).add(1)).div(2);\r\n            if (_checkpoints[mid].fromBlock <= _blockNumber) {\r\n                min = mid;\r\n            } else {\r\n                max = mid.sub(1);\r\n            }\r\n        }\r\n        return min;\r\n    }\r\n\r\n    /**\r\n     * @notice Queries the value at a specific `_blockNumber`\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _blockNumber The block number of the value active at that time\r\n     * @return _value The value at `_blockNumber`\r\n     **/\r\n    function valueAt(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _value) {\r\n        uint256 historyCount = _self.endIndex;\r\n\r\n        // No _checkpoints, return 0\r\n        if (historyCount == 0) return 0;\r\n\r\n        // Shortcut for the actual value (extra optimized for current block, to save one storage read)\r\n        // historyCount - 1 is safe, since historyCount != 0\r\n        if (\r\n            _blockNumber >= block.number ||\r\n            _blockNumber >= _self.checkpoints[historyCount - 1].fromBlock\r\n        ) {\r\n            return _self.checkpoints[historyCount - 1].value;\r\n        }\r\n\r\n        // guard values at start\r\n        uint256 startIndex = _self.startIndex;\r\n        if (_blockNumber < _self.checkpoints[startIndex].fromBlock) {\r\n            // reading data before `startIndex` is only safe before first cleanup\r\n            require(\r\n                startIndex == 0,\r\n                \"CheckPointHistory: reading from cleaned-up block\"\r\n            );\r\n            return 0;\r\n        }\r\n\r\n        // Find the block with number less than or equal to block given\r\n        uint256 index = _indexOfGreatestBlockLessThan(\r\n            _self.checkpoints,\r\n            startIndex,\r\n            _self.endIndex,\r\n            _blockNumber\r\n        );\r\n\r\n        return _self.checkpoints[index].value;\r\n    }\r\n\r\n    /**\r\n     * @notice Queries the value at `block.number`\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @return _value The value at `block.number`\r\n     **/\r\n    function valueAtNow(\r\n        CheckPointHistoryState storage _self\r\n    ) internal view returns (uint256 _value) {\r\n        uint256 historyCount = _self.endIndex;\r\n        // No _checkpoints, return 0\r\n        if (historyCount == 0) return 0;\r\n        // Return last value\r\n        return _self.checkpoints[historyCount - 1].value;\r\n    }\r\n\r\n    /**\r\n     * @notice Writes the value at the current block.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _value Value to write.\r\n     **/\r\n    function writeValue(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _value\r\n    ) internal {\r\n        uint256 historyCount = _self.endIndex;\r\n        if (historyCount == 0) {\r\n            // checkpoints array empty, push new CheckPoint\r\n            _self.checkpoints[0] = CheckPoint({\r\n                fromBlock: block.number.toUint64(),\r\n                value: _toUint192(_value)\r\n            });\r\n            _self.endIndex = 1;\r\n        } else {\r\n            // historyCount - 1 is safe, since historyCount != 0\r\n            CheckPoint storage lastCheckpoint = _self.checkpoints[\r\n                historyCount - 1\r\n            ];\r\n            uint256 lastBlock = lastCheckpoint.fromBlock;\r\n            // slither-disable-next-line incorrect-equality\r\n            if (block.number == lastBlock) {\r\n                // If last check point is the current block, just update\r\n                lastCheckpoint.value = _toUint192(_value);\r\n            } else {\r\n                // we should never have future blocks in history\r\n                assert(block.number > lastBlock);\r\n                // push new CheckPoint\r\n                _self.checkpoints[historyCount] = CheckPoint({\r\n                    fromBlock: block.number.toUint64(),\r\n                    value: _toUint192(_value)\r\n                });\r\n                _self.endIndex = uint64(historyCount + 1); // 64 bit safe, because historyCount <= block.number\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256) {\r\n        if (_cleanupBlockNumber == 0) return 0; // optimization for when cleaning is not enabled\r\n        uint256 length = _self.endIndex;\r\n        if (length == 0) return 0;\r\n        uint256 startIndex = _self.startIndex;\r\n        // length - 1 is safe, since length != 0 (check above)\r\n        uint256 endIndex = Math.min(startIndex.add(_count), length - 1); // last element can never be deleted\r\n        uint256 index = startIndex;\r\n        // we can delete `checkpoint[index]` while the next checkpoint is at `_cleanupBlockNumber` or before\r\n        while (\r\n            index < endIndex &&\r\n            _self.checkpoints[index + 1].fromBlock <= _cleanupBlockNumber\r\n        ) {\r\n            delete _self.checkpoints[index];\r\n            index++;\r\n        }\r\n        if (index > startIndex) {\r\n            // index is the first not deleted index\r\n            _self.startIndex = index.toUint64();\r\n        }\r\n        return index - startIndex; // safe: index >= startIndex at start and then increases\r\n    }\r\n\r\n    // SafeCast lib is missing cast to uint192\r\n    function _toUint192(uint256 _value) internal pure returns (uint192) {\r\n        require(_value < 2 ** 192, \"value doesn't fit in 192 bits\");\r\n        return uint192(_value);\r\n    }\r\n}\r\n"
      },
      "contracts/lib/CheckPointHistoryCache.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"./CheckPointHistory.sol\";\r\n\r\nlibrary CheckPointHistoryCache {\r\n    using SafeMath for uint256;\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n\r\n    struct CacheState {\r\n        // mapping blockNumber => (value + 1)\r\n        mapping(uint256 => uint256) cache;\r\n    }\r\n\r\n    function valueAt(\r\n        CacheState storage _self,\r\n        CheckPointHistory.CheckPointHistoryState storage _checkPointHistory,\r\n        uint256 _blockNumber\r\n    ) internal returns (uint256 _value, bool _cacheCreated) {\r\n        // is it in cache?\r\n        uint256 cachedValue = _self.cache[_blockNumber];\r\n        if (cachedValue != 0) {\r\n            return (cachedValue - 1, false); // safe, cachedValue != 0\r\n        }\r\n        // read from _checkPointHistory\r\n        uint256 historyValue = _checkPointHistory.valueAt(_blockNumber);\r\n        _self.cache[_blockNumber] = historyValue.add(1); // store to cache (add 1 to differentiate from empty)\r\n        return (historyValue, true);\r\n    }\r\n\r\n    function deleteAt(\r\n        CacheState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal returns (uint256 _deleted) {\r\n        if (_self.cache[_blockNumber] != 0) {\r\n            _self.cache[_blockNumber] = 0;\r\n            return 1;\r\n        }\r\n        return 0;\r\n    }\r\n}\r\n"
      },
      "contracts/lib/CheckPointsByAddress.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./CheckPointHistory.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\n\r\n/**\r\n * @title Check Points By Address library\r\n * @notice A contract to manage checkpoint history for a collection of addresses.\r\n * @dev Store value history by address, and then by block number.\r\n **/\r\nlibrary CheckPointsByAddress {\r\n    using SafeMath for uint256;\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n\r\n    struct CheckPointsByAddressState {\r\n        // `historyByAddress` is the map that stores the check point history of each address\r\n        mapping(address => CheckPointHistory.CheckPointHistoryState) historyByAddress;\r\n    }\r\n\r\n    /**\r\n    /**\r\n     * @notice Send `amount` value to `to` address from `from` address.\r\n     * @param _self A CheckPointsByAddressState instance to manage.\r\n     * @param _from Address of the history of from values \r\n     * @param _to Address of the history of to values \r\n     * @param _amount The amount of value to be transferred\r\n     **/\r\n    function transmit(\r\n        CheckPointsByAddressState storage _self,\r\n        address _from,\r\n        address _to,\r\n        uint256 _amount\r\n    ) internal {\r\n        // Shortcut\r\n        if (_amount == 0) return;\r\n\r\n        // Both from and to can never be zero\r\n        assert(!(_from == address(0) && _to == address(0)));\r\n\r\n        // Update transferer value\r\n        if (_from != address(0)) {\r\n            // Compute the new from balance\r\n            uint256 newValueFrom = valueOfAtNow(_self, _from).sub(_amount);\r\n            writeValue(_self, _from, newValueFrom);\r\n        }\r\n\r\n        // Update transferee value\r\n        if (_to != address(0)) {\r\n            // Compute the new to balance\r\n            uint256 newValueTo = valueOfAtNow(_self, _to).add(_amount);\r\n            writeValue(_self, _to, newValueTo);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Queries the value of `_owner` at a specific `_blockNumber`.\r\n     * @param _self A CheckPointsByAddressState instance to manage.\r\n     * @param _owner The address from which the value will be retrieved.\r\n     * @param _blockNumber The block number to query for the then current value.\r\n     * @return The value at `_blockNumber` for `_owner`.\r\n     **/\r\n    function valueOfAt(\r\n        CheckPointsByAddressState storage _self,\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256) {\r\n        // Get history for _owner\r\n        CheckPointHistory.CheckPointHistoryState storage history = _self\r\n            .historyByAddress[_owner];\r\n        // Return value at given block\r\n        return history.valueAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the value of the `_owner` at the current `block.number`.\r\n     * @param _self A CheckPointsByAddressState instance to manage.\r\n     * @param _owner The address of the value is being requested.\r\n     * @return The value of `_owner` at the current block.\r\n     **/\r\n    function valueOfAtNow(\r\n        CheckPointsByAddressState storage _self,\r\n        address _owner\r\n    ) internal view returns (uint256) {\r\n        // Get history for _owner\r\n        CheckPointHistory.CheckPointHistoryState storage history = _self\r\n            .historyByAddress[_owner];\r\n        // Return value at now\r\n        return history.valueAtNow();\r\n    }\r\n\r\n    /**\r\n     * @notice Writes the `value` at the current block number for `_owner`.\r\n     * @param _self A CheckPointsByAddressState instance to manage.\r\n     * @param _owner The address of `_owner` to write.\r\n     * @param _value The value to write.\r\n     * @dev Sender must be the owner of the contract.\r\n     **/\r\n    function writeValue(\r\n        CheckPointsByAddressState storage _self,\r\n        address _owner,\r\n        uint256 _value\r\n    ) internal {\r\n        // Get history for _owner\r\n        CheckPointHistory.CheckPointHistoryState storage history = _self\r\n            .historyByAddress[_owner];\r\n        // Write the value\r\n        history.writeValue(_value);\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        CheckPointsByAddressState storage _self,\r\n        address _owner,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256) {\r\n        if (_owner != address(0)) {\r\n            return\r\n                _self.historyByAddress[_owner].cleanupOldCheckpoints(\r\n                    _count,\r\n                    _cleanupBlockNumber\r\n                );\r\n        }\r\n        return 0;\r\n    }\r\n}\r\n"
      },
      "contracts/lib/DelegationHistory.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\r\nimport \"../utils/SafePct.sol\";\r\n\r\n/**\r\n * @title DelegationHistory library\r\n * @notice A contract to manage checkpoints as of a given block.\r\n * @dev Store value history by block number with detachable state.\r\n **/\r\nlibrary DelegationHistory {\r\n    using SafeMath for uint256;\r\n    using SafePct for uint256;\r\n    using SafeCast for uint256;\r\n\r\n    uint256 public constant MAX_DELEGATES_BY_PERCENT = 2;\r\n    string private constant MAX_DELEGATES_MSG = \"Max delegates exceeded\";\r\n\r\n    struct Delegation {\r\n        address delegate;\r\n        uint16 value;\r\n        // delegations[0] will also hold length and blockNumber to save 1 slot of storage per checkpoint\r\n        // for all other indexes these fields will be 0\r\n        // also, when checkpoint is empty, `length` will automatically be 0, which is ok\r\n        uint64 fromBlock;\r\n        uint8 length; // length is limited to MAX_DELEGATES_BY_PERCENT which fits in 8 bits\r\n    }\r\n\r\n    /**\r\n     * @dev `CheckPoint` is the structure that attaches a block number to a\r\n     *  given value; the block number attached is the one that last changed the\r\n     *  value\r\n     **/\r\n    struct CheckPoint {\r\n        // the list of delegations at the time\r\n        mapping(uint256 => Delegation) delegations;\r\n    }\r\n\r\n    struct CheckPointHistoryState {\r\n        // `checkpoints` is an array that tracks delegations at non-contiguous block numbers\r\n        mapping(uint256 => CheckPoint) checkpoints;\r\n        // `checkpoints` before `startIndex` have been deleted\r\n        // INVARIANT: checkpoints.length == 0 || startIndex < checkpoints.length      (strict!)\r\n        uint64 startIndex;\r\n        uint64 length;\r\n    }\r\n\r\n    /**\r\n     * @notice Queries the value at a specific `_blockNumber`\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _delegate The delegate for which we need value.\r\n     * @param _blockNumber The block number of the value active at that time\r\n     * @return _value The value of the `_delegate` at `_blockNumber`\r\n     **/\r\n    function valueOfAt(\r\n        CheckPointHistoryState storage _self,\r\n        address _delegate,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _value) {\r\n        (bool found, uint256 index) = _findGreatestBlockLessThan(\r\n            _self,\r\n            _blockNumber\r\n        );\r\n        if (!found) return 0;\r\n        return _getValueForDelegate(_self.checkpoints[index], _delegate);\r\n    }\r\n\r\n    /**\r\n     * @notice Queries the value at `block.number`\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _delegate The delegate for which we need value.\r\n     * @return _value The value at `block.number`\r\n     **/\r\n    function valueOfAtNow(\r\n        CheckPointHistoryState storage _self,\r\n        address _delegate\r\n    ) internal view returns (uint256 _value) {\r\n        uint256 length = _self.length;\r\n        if (length == 0) return 0;\r\n        return _getValueForDelegate(_self.checkpoints[length - 1], _delegate);\r\n    }\r\n\r\n    /**\r\n     * @notice Writes the value at the current block.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _delegate The delegate tu update.\r\n     * @param _value The new value to set for this delegate (value `0` deletes `_delegate` from the list).\r\n     **/\r\n    function writeValue(\r\n        CheckPointHistoryState storage _self,\r\n        address _delegate,\r\n        uint256 _value\r\n    ) internal {\r\n        uint256 historyCount = _self.length;\r\n        if (historyCount == 0) {\r\n            // checkpoints array empty, push new CheckPoint\r\n            if (_value != 0) {\r\n                CheckPoint storage cp = _self.checkpoints[historyCount];\r\n                _self.length = SafeCast.toUint64(historyCount + 1);\r\n                cp.delegations[0] = Delegation({\r\n                    delegate: _delegate,\r\n                    value: _value.toUint16(),\r\n                    fromBlock: block.number.toUint64(),\r\n                    length: 1\r\n                });\r\n            }\r\n        } else {\r\n            // historyCount - 1 is safe, since historyCount != 0\r\n            CheckPoint storage lastCheckpoint = _self.checkpoints[\r\n                historyCount - 1\r\n            ];\r\n            uint256 lastBlock = lastCheckpoint.delegations[0].fromBlock;\r\n            // slither-disable-next-line incorrect-equality\r\n            if (block.number == lastBlock) {\r\n                // If last check point is the current block, just update\r\n                _updateDelegates(lastCheckpoint, _delegate, _value);\r\n            } else {\r\n                // we should never have future blocks in history\r\n                assert(block.number > lastBlock);\r\n                // last check point block is before\r\n                CheckPoint storage cp = _self.checkpoints[historyCount];\r\n                _self.length = SafeCast.toUint64(historyCount + 1);\r\n                _copyAndUpdateDelegates(cp, lastCheckpoint, _delegate, _value);\r\n                cp.delegations[0].fromBlock = block.number.toUint64();\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get all percentage delegations active at a time.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @param _blockNumber The block number to query.\r\n     * @return _delegates The active percentage delegates at the time.\r\n     * @return _values The delegates' values at the time.\r\n     **/\r\n    function delegationsAt(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        returns (address[] memory _delegates, uint256[] memory _values)\r\n    {\r\n        (bool found, uint256 index) = _findGreatestBlockLessThan(\r\n            _self,\r\n            _blockNumber\r\n        );\r\n        if (!found) {\r\n            return (new address[](0), new uint256[](0));\r\n        }\r\n\r\n        // copy delegates and values to memory arrays\r\n        // (to prevent caller updating the stored value)\r\n        CheckPoint storage cp = _self.checkpoints[index];\r\n        uint256 length = cp.delegations[0].length;\r\n        _delegates = new address[](length);\r\n        _values = new uint256[](length);\r\n        for (uint256 i = 0; i < length; i++) {\r\n            Delegation storage dlg = cp.delegations[i];\r\n            _delegates[i] = dlg.delegate;\r\n            _values[i] = dlg.value;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get all percentage delegations active now.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @return _delegates The active percentage delegates.\r\n     * @return _values The delegates' values.\r\n     **/\r\n    function delegationsAtNow(\r\n        CheckPointHistoryState storage _self\r\n    )\r\n        internal\r\n        view\r\n        returns (address[] memory _delegates, uint256[] memory _values)\r\n    {\r\n        return delegationsAt(_self, block.number);\r\n    }\r\n\r\n    /**\r\n     * Get all percentage delegations active now.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @return _length The number of delegations.\r\n     * @return _delegations .\r\n     **/\r\n    function delegationsAtNowRaw(\r\n        CheckPointHistoryState storage _self\r\n    )\r\n        internal\r\n        view\r\n        returns (\r\n            uint256 _length,\r\n            mapping(uint256 => Delegation) storage _delegations\r\n        )\r\n    {\r\n        uint256 length = _self.length;\r\n        if (length == 0) {\r\n            return (0, _self.checkpoints[0].delegations);\r\n        }\r\n        CheckPoint storage cp = _self.checkpoints[length - 1];\r\n        return (cp.delegations[0].length, cp.delegations);\r\n    }\r\n\r\n    /**\r\n     * Get the number of delegations.\r\n     * @param _self A CheckPointHistoryState instance to query.\r\n     * @param _blockNumber The block number to query.\r\n     * @return _count Count of delegations at the time.\r\n     **/\r\n    function countAt(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _count) {\r\n        (bool found, uint256 index) = _findGreatestBlockLessThan(\r\n            _self,\r\n            _blockNumber\r\n        );\r\n        if (!found) return 0;\r\n        return _self.checkpoints[index].delegations[0].length;\r\n    }\r\n\r\n    /**\r\n     * Get the sum of all delegation values.\r\n     * @param _self A CheckPointHistoryState instance to query.\r\n     * @param _blockNumber The block number to query.\r\n     * @return _total Total delegation value at the time.\r\n     **/\r\n    function totalValueAt(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _total) {\r\n        (bool found, uint256 index) = _findGreatestBlockLessThan(\r\n            _self,\r\n            _blockNumber\r\n        );\r\n        if (!found) return 0;\r\n\r\n        CheckPoint storage cp = _self.checkpoints[index];\r\n        uint256 length = cp.delegations[0].length;\r\n        _total = 0;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            _total = _total.add(cp.delegations[i].value);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get the sum of all delegation values.\r\n     * @param _self A CheckPointHistoryState instance to query.\r\n     * @return _total Total delegation value at the time.\r\n     **/\r\n    function totalValueAtNow(\r\n        CheckPointHistoryState storage _self\r\n    ) internal view returns (uint256 _total) {\r\n        return totalValueAt(_self, block.number);\r\n    }\r\n\r\n    /**\r\n     * Get the sum of all delegation values, every one scaled by `_mul/_div`.\r\n     * @param _self A CheckPointHistoryState instance to query.\r\n     * @param _mul The multiplier.\r\n     * @param _div The divisor.\r\n     * @param _blockNumber The block number to query.\r\n     * @return _total Total scaled delegation value at the time.\r\n     **/\r\n    function scaledTotalValueAt(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _mul,\r\n        uint256 _div,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _total) {\r\n        (bool found, uint256 index) = _findGreatestBlockLessThan(\r\n            _self,\r\n            _blockNumber\r\n        );\r\n        if (!found) return 0;\r\n\r\n        CheckPoint storage cp = _self.checkpoints[index];\r\n        uint256 length = cp.delegations[0].length;\r\n        _total = 0;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            _total = _total.add(\r\n                uint256(cp.delegations[i].value).mulDiv(_mul, _div)\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Clear all delegations at this moment.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     */\r\n    function clear(CheckPointHistoryState storage _self) internal {\r\n        uint256 historyCount = _self.length;\r\n        if (historyCount > 0) {\r\n            // add an empty checkpoint\r\n            CheckPoint storage cp = _self.checkpoints[historyCount];\r\n            _self.length = SafeCast.toUint64(historyCount + 1);\r\n            // create empty checkpoint = only set fromBlock\r\n            cp.delegations[0] = Delegation({\r\n                delegate: address(0),\r\n                value: 0,\r\n                fromBlock: block.number.toUint64(),\r\n                length: 0\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256) {\r\n        if (_cleanupBlockNumber == 0) return 0; // optimization for when cleaning is not enabled\r\n        uint256 length = _self.length;\r\n        if (length == 0) return 0;\r\n        uint256 startIndex = _self.startIndex;\r\n        // length - 1 is safe, since length != 0 (check above)\r\n        uint256 endIndex = Math.min(startIndex.add(_count), length - 1); // last element can never be deleted\r\n        uint256 index = startIndex;\r\n        // we can delete `checkpoint[index]` while the next checkpoint is at `_cleanupBlockNumber` or before\r\n        while (\r\n            index < endIndex &&\r\n            _self.checkpoints[index + 1].delegations[0].fromBlock <=\r\n            _cleanupBlockNumber\r\n        ) {\r\n            CheckPoint storage cp = _self.checkpoints[index];\r\n            uint256 cplength = cp.delegations[0].length;\r\n            for (uint256 i = 0; i < cplength; i++) {\r\n                delete cp.delegations[i];\r\n            }\r\n            index++;\r\n        }\r\n        if (index > startIndex) {\r\n            // index is the first not deleted index\r\n            _self.startIndex = SafeCast.toUint64(index);\r\n        }\r\n        return index - startIndex; // safe: index = startIndex at start and increases in loop\r\n    }\r\n\r\n    /////////////////////////////////////////////////////////////////////////////////\r\n    // helper functions for writeValueAt\r\n\r\n    function _copyAndUpdateDelegates(\r\n        CheckPoint storage _cp,\r\n        CheckPoint storage _orig,\r\n        address _delegate,\r\n        uint256 _value\r\n    ) private {\r\n        uint256 length = _orig.delegations[0].length;\r\n        bool updated = false;\r\n        uint256 newlength = 0;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            Delegation memory origDlg = _orig.delegations[i];\r\n            if (origDlg.delegate == _delegate) {\r\n                // copy delegate, but with new value\r\n                newlength = _appendDelegate(\r\n                    _cp,\r\n                    origDlg.delegate,\r\n                    _value,\r\n                    newlength\r\n                );\r\n                updated = true;\r\n            } else {\r\n                // just copy the delegate with original value\r\n                newlength = _appendDelegate(\r\n                    _cp,\r\n                    origDlg.delegate,\r\n                    origDlg.value,\r\n                    newlength\r\n                );\r\n            }\r\n        }\r\n        if (!updated) {\r\n            // delegate is not in the original list, so add it\r\n            newlength = _appendDelegate(_cp, _delegate, _value, newlength);\r\n        }\r\n        // safe - newlength <= length + 1 <= MAX_DELEGATES_BY_PERCENT\r\n        _cp.delegations[0].length = uint8(newlength);\r\n    }\r\n\r\n    function _updateDelegates(\r\n        CheckPoint storage _cp,\r\n        address _delegate,\r\n        uint256 _value\r\n    ) private {\r\n        uint256 length = _cp.delegations[0].length;\r\n        uint256 i = 0;\r\n        while (i < length && _cp.delegations[i].delegate != _delegate) ++i;\r\n        if (i < length) {\r\n            if (_value != 0) {\r\n                _cp.delegations[i].value = _value.toUint16();\r\n            } else {\r\n                _deleteDelegate(_cp, i, length - 1); // length - 1 is safe:  0 <= i < length\r\n                _cp.delegations[0].length = uint8(length - 1);\r\n            }\r\n        } else {\r\n            uint256 newlength = _appendDelegate(_cp, _delegate, _value, length);\r\n            _cp.delegations[0].length = uint8(newlength); // safe - length <= MAX_DELEGATES_BY_PERCENT\r\n        }\r\n    }\r\n\r\n    function _appendDelegate(\r\n        CheckPoint storage _cp,\r\n        address _delegate,\r\n        uint256 _value,\r\n        uint256 _length\r\n    ) private returns (uint256) {\r\n        if (_value != 0) {\r\n            require(_length < MAX_DELEGATES_BY_PERCENT, MAX_DELEGATES_MSG);\r\n            Delegation storage dlg = _cp.delegations[_length];\r\n            dlg.delegate = _delegate;\r\n            dlg.value = _value.toUint16();\r\n            // for delegations[0], fromBlock and length are assigned outside\r\n            return _length + 1;\r\n        }\r\n        return _length;\r\n    }\r\n\r\n    function _deleteDelegate(\r\n        CheckPoint storage _cp,\r\n        uint256 _index,\r\n        uint256 _last\r\n    ) private {\r\n        Delegation storage dlg = _cp.delegations[_index];\r\n        Delegation storage lastDlg = _cp.delegations[_last];\r\n        if (_index < _last) {\r\n            dlg.delegate = lastDlg.delegate;\r\n            dlg.value = lastDlg.value;\r\n        }\r\n        lastDlg.delegate = address(0);\r\n        lastDlg.value = 0;\r\n    }\r\n\r\n    /////////////////////////////////////////////////////////////////////////////////\r\n    // helper functions for querying\r\n\r\n    /**\r\n     * @notice Binary search of _checkpoints array.\r\n     * @param _checkpoints An array of CheckPoint to search.\r\n     * @param _startIndex Smallest possible index to be returned.\r\n     * @param _blockNumber The block number to search for.\r\n     */\r\n    function _binarySearchGreatestBlockLessThan(\r\n        mapping(uint256 => CheckPoint) storage _checkpoints,\r\n        uint256 _startIndex,\r\n        uint256 _endIndex,\r\n        uint256 _blockNumber\r\n    ) private view returns (uint256 _index) {\r\n        // Binary search of the value by given block number in the array\r\n        uint256 min = _startIndex;\r\n        uint256 max = _endIndex.sub(1);\r\n        while (max > min) {\r\n            uint256 mid = (max.add(min).add(1)).div(2);\r\n            if (_checkpoints[mid].delegations[0].fromBlock <= _blockNumber) {\r\n                min = mid;\r\n            } else {\r\n                max = mid.sub(1);\r\n            }\r\n        }\r\n        return min;\r\n    }\r\n\r\n    /**\r\n     * @notice Binary search of _checkpoints array. Extra optimized for the common case when we are\r\n     *   searching for the last block.\r\n     * @param _self The state to query.\r\n     * @param _blockNumber The block number to search for.\r\n     * @return _found true if value was found (only `false` if `_blockNumber` is before first\r\n     *   checkpoint or the checkpoint array is empty)\r\n     * @return _index index of the newest block with number less than or equal `_blockNumber`\r\n     */\r\n    function _findGreatestBlockLessThan(\r\n        CheckPointHistoryState storage _self,\r\n        uint256 _blockNumber\r\n    ) private view returns (bool _found, uint256 _index) {\r\n        uint256 startIndex = _self.startIndex;\r\n        uint256 historyCount = _self.length;\r\n        if (historyCount == 0) {\r\n            _found = false;\r\n        } else if (\r\n            _blockNumber >=\r\n            _self.checkpoints[historyCount - 1].delegations[0].fromBlock\r\n        ) {\r\n            _found = true;\r\n            _index = historyCount - 1; // safe, historyCount != 0 in this branch\r\n        } else if (\r\n            _blockNumber <\r\n            _self.checkpoints[startIndex].delegations[0].fromBlock\r\n        ) {\r\n            // reading data before `_startIndex` is only safe before first cleanup\r\n            require(\r\n                startIndex == 0,\r\n                \"DelegationHistory: reading from cleaned-up block\"\r\n            );\r\n            _found = false;\r\n        } else {\r\n            _found = true;\r\n            _index = _binarySearchGreatestBlockLessThan(\r\n                _self.checkpoints,\r\n                startIndex,\r\n                historyCount,\r\n                _blockNumber\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Find delegate and return its value or 0 if not found.\r\n     */\r\n    function _getValueForDelegate(\r\n        CheckPoint storage _cp,\r\n        address _delegate\r\n    ) internal view returns (uint256) {\r\n        uint256 length = _cp.delegations[0].length;\r\n        for (uint256 i = 0; i < length; i++) {\r\n            Delegation storage dlg = _cp.delegations[i];\r\n            if (dlg.delegate == _delegate) {\r\n                return dlg.value;\r\n            }\r\n        }\r\n        return 0; // _delegate not found\r\n    }\r\n}\r\n"
      },
      "contracts/lib/ExplicitDelegation.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./CheckPointsByAddress.sol\";\r\nimport \"./CheckPointHistory.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"../utils/SafePct.sol\";\r\n\r\n/**\r\n * @title ExplicitDelegation library\r\n * @notice A library to manage a group of delegates for allocating voting power by a delegator.\r\n **/\r\nlibrary ExplicitDelegation {\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n    using CheckPointsByAddress for CheckPointsByAddress.CheckPointsByAddressState;\r\n    using SafeMath for uint256;\r\n    using SafePct for uint256;\r\n\r\n    /**\r\n     * @dev `DelegationState` is the state structure used by this library to contain/manage\r\n     *  a grouing of delegates (a ExplicitDelegation) for a delegator.\r\n     */\r\n    struct DelegationState {\r\n        CheckPointHistory.CheckPointHistoryState delegatedTotal;\r\n        // `delegatedVotePower` is a map of delegators pointing to a map of delegates\r\n        // containing a checkpoint history of delegated vote power balances.\r\n        CheckPointsByAddress.CheckPointsByAddressState delegatedVotePower;\r\n    }\r\n\r\n    /**\r\n     * @notice Add or replace an existing _delegate with new vote power (explicit).\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The address of the _delegate to add/replace\r\n     * @param _amount Allocation of the delegation as explicit amount\r\n     */\r\n    function addReplaceDelegate(\r\n        DelegationState storage _self,\r\n        address _delegate,\r\n        uint256 _amount\r\n    ) internal {\r\n        uint256 prevAmount = _self.delegatedVotePower.valueOfAtNow(_delegate);\r\n        uint256 newTotal = _self\r\n            .delegatedTotal\r\n            .valueAtNow()\r\n            .sub(prevAmount, \"Total < 0\")\r\n            .add(_amount);\r\n        _self.delegatedVotePower.writeValue(_delegate, _amount);\r\n        _self.delegatedTotal.writeValue(newTotal);\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        DelegationState storage _self,\r\n        address _owner,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256 _deleted) {\r\n        _deleted = _self.delegatedTotal.cleanupOldCheckpoints(\r\n            _count,\r\n            _cleanupBlockNumber\r\n        );\r\n        // safe: cleanupOldCheckpoints always returns the number of deleted elements which is small, so no owerflow\r\n        _deleted += _self.delegatedVotePower.cleanupOldCheckpoints(\r\n            _owner,\r\n            _count,\r\n            _cleanupBlockNumber\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Get the _total of the explicit vote power delegation amount.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _blockNumber The block to query.\r\n     * @return _total The _total vote power amount delegated.\r\n     */\r\n    function getDelegatedTotalAt(\r\n        DelegationState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _total) {\r\n        return _self.delegatedTotal.valueAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the _total of the explicit vote power delegation amount.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @return _total The total vote power amount delegated.\r\n     */\r\n    function getDelegatedTotal(\r\n        DelegationState storage _self\r\n    ) internal view returns (uint256 _total) {\r\n        return _self.delegatedTotal.valueAtNow();\r\n    }\r\n\r\n    /**\r\n     * @notice Given a delegate address, return the explicit amount of the vote power delegation.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The _delegate address to find.\r\n     * @param _blockNumber The block to query.\r\n     * @return _value The percent of vote power allocated to the _delegate address.\r\n     */\r\n    function getDelegatedValueAt(\r\n        DelegationState storage _self,\r\n        address _delegate,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _value) {\r\n        return _self.delegatedVotePower.valueOfAt(_delegate, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Given a delegate address, return the explicit amount of the vote power delegation.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The _delegate address to find.\r\n     * @return _value The percent of vote power allocated to the _delegate address.\r\n     */\r\n    function getDelegatedValue(\r\n        DelegationState storage _self,\r\n        address _delegate\r\n    ) internal view returns (uint256 _value) {\r\n        return _self.delegatedVotePower.valueOfAtNow(_delegate);\r\n    }\r\n}\r\n"
      },
      "contracts/lib/PercentageDelegation.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./CheckPointHistory.sol\";\r\nimport \"./DelegationHistory.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"../utils/SafePct.sol\";\r\n\r\n/**\r\n * @title PercentageDelegation library\r\n * @notice Only handles percentage delegation\r\n * @notice A library to manage a group of _delegates for allocating voting power by a delegator.\r\n **/\r\nlibrary PercentageDelegation {\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n    using DelegationHistory for DelegationHistory.CheckPointHistoryState;\r\n    using SafeMath for uint256;\r\n    using SafePct for uint256;\r\n\r\n    uint256 public constant MAX_BIPS = 10000;\r\n    string private constant MAX_BIPS_MSG = \"Max delegation bips exceeded\";\r\n\r\n    /**\r\n     * @dev `DelegationState` is the state structure used by this library to contain/manage\r\n     *  a grouing of _delegates (a PercentageDelegation) for a delegator.\r\n     */\r\n    struct DelegationState {\r\n        // percentages by _delegates\r\n        DelegationHistory.CheckPointHistoryState delegation;\r\n    }\r\n\r\n    /**\r\n     * @notice Add or replace an existing _delegate with allocated vote power in basis points.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The address of the _delegate to add/replace\r\n     * @param _bips Allocation of the delegation specified in basis points (1/100 of 1 percent)\r\n     * @dev If you send a `_bips` of zero, `_delegate` will be deleted if one\r\n     *  exists in the delegation; if zero and `_delegate` does not exist, it will not be added.\r\n     */\r\n    function addReplaceDelegate(\r\n        DelegationState storage _self,\r\n        address _delegate,\r\n        uint256 _bips\r\n    ) internal {\r\n        // Check for max delegation basis points\r\n        assert(_bips <= MAX_BIPS);\r\n\r\n        // Change the delegate's percentage\r\n        _self.delegation.writeValue(_delegate, _bips);\r\n\r\n        // check the total\r\n        require(_self.delegation.totalValueAtNow() <= MAX_BIPS, MAX_BIPS_MSG);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total of the explicit vote power delegation bips of all delegates at given block.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _blockNumber The block to query.\r\n     * @return _totalBips The total vote power bips delegated.\r\n     */\r\n    function getDelegatedTotalAt(\r\n        DelegationState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _totalBips) {\r\n        return _self.delegation.totalValueAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total of the bips vote power delegation bips of all _delegates.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @return _totalBips The total vote power bips delegated.\r\n     */\r\n    function getDelegatedTotal(\r\n        DelegationState storage _self\r\n    ) internal view returns (uint256 _totalBips) {\r\n        return _self.delegation.totalValueAtNow();\r\n    }\r\n\r\n    /**\r\n     * @notice Given a _delegate address, return the bips of the vote power delegation.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The delegate address to find.\r\n     * @param _blockNumber The block to query.\r\n     * @return _bips The percent of vote power allocated to the delegate address.\r\n     */\r\n    function getDelegatedValueAt(\r\n        DelegationState storage _self,\r\n        address _delegate,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _bips) {\r\n        return _self.delegation.valueOfAt(_delegate, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Given a delegate address, return the bips of the vote power delegation.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _delegate The delegate address to find.\r\n     * @return _bips The percent of vote power allocated to the delegate address.\r\n     */\r\n    function getDelegatedValue(\r\n        DelegationState storage _self,\r\n        address _delegate\r\n    ) internal view returns (uint256 _bips) {\r\n        return _self.delegation.valueOfAtNow(_delegate);\r\n    }\r\n\r\n    /**\r\n     * @notice Returns lists of delegate addresses and corresponding values at given block.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _blockNumber The block to query.\r\n     * @return _delegates Positional array of delegation addresses.\r\n     * @return _values Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     */\r\n    function getDelegationsAt(\r\n        DelegationState storage _self,\r\n        uint256 _blockNumber\r\n    )\r\n        internal\r\n        view\r\n        returns (address[] memory _delegates, uint256[] memory _values)\r\n    {\r\n        return _self.delegation.delegationsAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Returns lists of delegate addresses and corresponding values.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @return _delegates Positional array of delegation addresses.\r\n     * @return _values Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     */\r\n    function getDelegations(\r\n        DelegationState storage _self\r\n    )\r\n        internal\r\n        view\r\n        returns (address[] memory _delegates, uint256[] memory _values)\r\n    {\r\n        return _self.delegation.delegationsAtNow();\r\n    }\r\n\r\n    /**\r\n     * Get all percentage delegations active now.\r\n     * @param _self A CheckPointHistoryState instance to manage.\r\n     * @return _length The number of delegations.\r\n     * @return _delegations .\r\n     **/\r\n    function getDelegationsRaw(\r\n        DelegationState storage _self\r\n    )\r\n        internal\r\n        view\r\n        returns (\r\n            uint256 _length,\r\n            mapping(uint256 => DelegationHistory.Delegation)\r\n                storage _delegations\r\n        )\r\n    {\r\n        return _self.delegation.delegationsAtNowRaw();\r\n    }\r\n\r\n    /**\r\n     * Get the number of delegations.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _blockNumber The block number to query.\r\n     * @return _count Count of delegations at the time.\r\n     **/\r\n    function getCountAt(\r\n        DelegationState storage _self,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _count) {\r\n        return _self.delegation.countAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * Get the number of delegations.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @return _count Count of delegations at the time.\r\n     **/\r\n    function getCount(\r\n        DelegationState storage _self\r\n    ) internal view returns (uint256 _count) {\r\n        return _self.delegation.countAt(block.number);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total amount (absolute) of the vote power delegation of all delegates.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @param _balance Owner's balance.\r\n     * @return _totalAmount The total vote power amount delegated.\r\n     */\r\n    function getDelegatedTotalAmountAt(\r\n        DelegationState storage _self,\r\n        uint256 _balance,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _totalAmount) {\r\n        return\r\n            _self.delegation.scaledTotalValueAt(\r\n                _balance,\r\n                MAX_BIPS,\r\n                _blockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Clears all delegates.\r\n     * @param _self A DelegationState instance to manage.\r\n     * @dev Delegation mode remains PERCENTAGE, even though the delgation is now empty.\r\n     */\r\n    function clear(DelegationState storage _self) internal {\r\n        _self.delegation.clear();\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        DelegationState storage _self,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256) {\r\n        return\r\n            _self.delegation.cleanupOldCheckpoints(_count, _cleanupBlockNumber);\r\n    }\r\n}\r\n"
      },
      "contracts/lib/VotePower.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./CheckPointHistory.sol\";\r\nimport \"./CheckPointsByAddress.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\n\r\n/**\r\n * @title Vote power library\r\n * @notice A library to record delegate vote power balances by delegator\r\n *  and delegatee.\r\n **/\r\nlibrary VotePower {\r\n    using CheckPointHistory for CheckPointHistory.CheckPointHistoryState;\r\n    using CheckPointsByAddress for CheckPointsByAddress.CheckPointsByAddressState;\r\n    using SafeMath for uint256;\r\n\r\n    /**\r\n     * @dev `VotePowerState` is state structure used by this library to manage vote\r\n     *  power amounts by delegator and it's delegates.\r\n     */\r\n    struct VotePowerState {\r\n        // `votePowerByAddress` is the map that tracks the voting power balance\r\n        //  of each address, by block.\r\n        CheckPointsByAddress.CheckPointsByAddressState votePowerByAddress;\r\n    }\r\n\r\n    /**\r\n     * @notice This modifier checks that both addresses are non-zero.\r\n     * @param _delegator A delegator address.\r\n     * @param _delegatee A delegatee address.\r\n     */\r\n    modifier addressesNotZero(address _delegator, address _delegatee) {\r\n        // Both addresses cannot be zero\r\n        assert(!(_delegator == address(0) && _delegatee == address(0)));\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate vote power `_amount` to `_delegatee` address from `_delegator` address.\r\n     * @param _delegator Delegator address\r\n     * @param _delegatee Delegatee address\r\n     * @param _amount The _amount of vote power to send from _delegator to _delegatee\r\n     * @dev Amount recorded at the current block.\r\n     **/\r\n    function delegate(\r\n        VotePowerState storage _self,\r\n        address _delegator,\r\n        address _delegatee,\r\n        uint256 _amount\r\n    ) internal addressesNotZero(_delegator, _delegatee) {\r\n        // Shortcut\r\n        if (_amount == 0) {\r\n            return;\r\n        }\r\n\r\n        // Transmit vote power\r\n        _self.votePowerByAddress.transmit(_delegator, _delegatee, _amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Change the current vote power value.\r\n     * @param _owner Address of vote power owner.\r\n     * @param _add The amount to add to the vote power.\r\n     * @param _sub The amount to subtract from the vote power.\r\n     */\r\n    function changeValue(\r\n        VotePowerState storage _self,\r\n        address _owner,\r\n        uint256 _add,\r\n        uint256 _sub\r\n    ) internal {\r\n        assert(_owner != address(0));\r\n        if (_add == _sub) return;\r\n        uint256 value = _self.votePowerByAddress.valueOfAtNow(_owner);\r\n        value = value.add(_add).sub(_sub);\r\n        _self.votePowerByAddress.writeValue(_owner, value);\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate vote power `_amount` from `_delegatee` address\r\n     *  to `_delegator` address\r\n     * @param _delegator Delegator address\r\n     * @param _delegatee Delegatee address\r\n     * @param _amount The amount of vote power recovered by delegator from delegatee\r\n     **/\r\n    function undelegate(\r\n        VotePowerState storage _self,\r\n        address _delegator,\r\n        address _delegatee,\r\n        uint256 _amount\r\n    ) internal addressesNotZero(_delegator, _delegatee) {\r\n        // Shortcut\r\n        if (_amount == 0) {\r\n            return;\r\n        }\r\n\r\n        // Recover vote power\r\n        _self.votePowerByAddress.transmit(_delegatee, _delegator, _amount);\r\n    }\r\n\r\n    /**\r\n     * Delete at most `_count` of the oldest checkpoints.\r\n     * At least one checkpoint at or before `_cleanupBlockNumber` will remain\r\n     * (unless the history was empty to start with).\r\n     */\r\n    function cleanupOldCheckpoints(\r\n        VotePowerState storage _self,\r\n        address _owner,\r\n        uint256 _count,\r\n        uint256 _cleanupBlockNumber\r\n    ) internal returns (uint256) {\r\n        return\r\n            _self.votePowerByAddress.cleanupOldCheckpoints(\r\n                _owner,\r\n                _count,\r\n                _cleanupBlockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at `_blockNumber`.\r\n     * @param _self A VotePowerState instance to manage.\r\n     * @param _who Address to get vote power.\r\n     * @param _blockNumber Block number of the block to fetch vote power.\r\n     * @return _votePower The fetched vote power.\r\n     */\r\n    function votePowerOfAt(\r\n        VotePowerState storage _self,\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _votePower) {\r\n        return _self.votePowerByAddress.valueOfAt(_who, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_who`.\r\n     * @param _self A VotePowerState instance to manage.\r\n     * @param _who Address to get vote power.\r\n     * @return _votePower The fetched vote power.\r\n     */\r\n    function votePowerOfAtNow(\r\n        VotePowerState storage _self,\r\n        address _who\r\n    ) internal view returns (uint256 _votePower) {\r\n        return _self.votePowerByAddress.valueOfAtNow(_who);\r\n    }\r\n}\r\n"
      },
      "contracts/lib/VotePowerCache.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"../lib/VotePower.sol\";\r\n\r\n/**\r\n * @title Vote power library\r\n * @notice A library to record delegate vote power balances by delegator\r\n *  and delegatee.\r\n **/\r\nlibrary VotePowerCache {\r\n    using SafeMath for uint256;\r\n    using VotePower for VotePower.VotePowerState;\r\n\r\n    struct RevocationCacheRecord {\r\n        // revoking delegation only affects cached value therefore we have to track\r\n        // the revocation in order not to revoke twice\r\n        // mapping delegatee => revokedValue\r\n        mapping(address => uint256) revocations;\r\n    }\r\n\r\n    /**\r\n     * @dev `CacheState` is state structure used by this library to manage vote\r\n     *  power amounts by delegator and it's delegates.\r\n     */\r\n    struct CacheState {\r\n        // map keccak256([address, _blockNumber]) -> (value + 1)\r\n        mapping(bytes32 => uint256) valueCache;\r\n        // map keccak256([address, _blockNumber]) -> RevocationCacheRecord\r\n        mapping(bytes32 => RevocationCacheRecord) revocationCache;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the cached value at given block. If there is no cached value, original\r\n     *    value is returned and stored to cache. Cache never gets stale, because original\r\n     *    value can never change in a past block.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _votePower A VotePower instance to read from if cache is empty.\r\n     * @param _who Address to get vote power.\r\n     * @param _blockNumber Block number of the block to fetch vote power.\r\n     * precondition: _blockNumber < block.number\r\n     */\r\n    function valueOfAt(\r\n        CacheState storage _self,\r\n        VotePower.VotePowerState storage _votePower,\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal returns (uint256 _value, bool _createdCache) {\r\n        bytes32 key = keccak256(abi.encode(_who, _blockNumber));\r\n        // is it in cache?\r\n        uint256 cachedValue = _self.valueCache[key];\r\n        if (cachedValue != 0) {\r\n            return (cachedValue - 1, false); // safe, cachedValue != 0\r\n        }\r\n        // read from _votePower\r\n        uint256 votePowerValue = _votePower.votePowerOfAt(_who, _blockNumber);\r\n        _writeCacheValue(_self, key, votePowerValue);\r\n        return (votePowerValue, true);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the cached value at given block. If there is no cached value, original\r\n     *    value is returned. Cache is never modified.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _votePower A VotePower instance to read from if cache is empty.\r\n     * @param _who Address to get vote power.\r\n     * @param _blockNumber Block number of the block to fetch vote power.\r\n     * precondition: _blockNumber < block.number\r\n     */\r\n    function valueOfAtReadonly(\r\n        CacheState storage _self,\r\n        VotePower.VotePowerState storage _votePower,\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal view returns (uint256 _value) {\r\n        bytes32 key = keccak256(abi.encode(_who, _blockNumber));\r\n        // is it in cache?\r\n        uint256 cachedValue = _self.valueCache[key];\r\n        if (cachedValue != 0) {\r\n            return cachedValue - 1; // safe, cachedValue != 0\r\n        }\r\n        // read from _votePower\r\n        return _votePower.votePowerOfAt(_who, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Delete cached value for `_who` at given block.\r\n     *   Only used for history cleanup.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _who Address to get vote power.\r\n     * @param _blockNumber Block number of the block to fetch vote power.\r\n     * @return _deleted The number of cache items deleted (always 0 or 1).\r\n     * precondition: _blockNumber < cleanupBlockNumber\r\n     */\r\n    function deleteValueAt(\r\n        CacheState storage _self,\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) internal returns (uint256 _deleted) {\r\n        bytes32 key = keccak256(abi.encode(_who, _blockNumber));\r\n        if (_self.valueCache[key] != 0) {\r\n            delete _self.valueCache[key];\r\n            return 1;\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    /**\r\n     * @notice Revoke vote power delegation from `from` to `to` at given block.\r\n     *   Updates cached values for the block, so they are the only vote power values respecting revocation.\r\n     * @dev Only delegatees cached value is changed, delegator doesn't get the vote power back; so\r\n     *   the revoked vote power is forfeit for as long as this vote power block is in use. This is needed to\r\n     *   prevent double voting.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _votePower A VotePower instance to read from if cache is empty.\r\n     * @param _from The delegator.\r\n     * @param _to The delegatee.\r\n     * @param _revokedValue Value of delegation is not stored here, so it must be supplied by caller.\r\n     * @param _blockNumber Block number of the block to modify.\r\n     * precondition: _blockNumber < block.number\r\n     */\r\n    function revokeAt(\r\n        CacheState storage _self,\r\n        VotePower.VotePowerState storage _votePower,\r\n        address _from,\r\n        address _to,\r\n        uint256 _revokedValue,\r\n        uint256 _blockNumber\r\n    ) internal {\r\n        if (_revokedValue == 0) return;\r\n        bytes32 keyFrom = keccak256(abi.encode(_from, _blockNumber));\r\n        if (_self.revocationCache[keyFrom].revocations[_to] != 0) {\r\n            revert(\"Already revoked\");\r\n        }\r\n        // read values and prime cacheOf\r\n        (uint256 valueTo, ) = valueOfAt(_self, _votePower, _to, _blockNumber);\r\n        // write new values\r\n        bytes32 keyTo = keccak256(abi.encode(_to, _blockNumber));\r\n        _writeCacheValue(\r\n            _self,\r\n            keyTo,\r\n            valueTo.sub(_revokedValue, \"Revoked value too large\")\r\n        );\r\n        // mark as revoked\r\n        _self.revocationCache[keyFrom].revocations[_to] = _revokedValue;\r\n    }\r\n\r\n    /**\r\n     * @notice Delete revocation from `_from` to `_to` at block `_blockNumber`.\r\n     *   Only used for history cleanup.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _from The delegator.\r\n     * @param _to The delegatee.\r\n     * @param _blockNumber Block number of the block to modify.\r\n     * precondition: _blockNumber < cleanupBlockNumber\r\n     */\r\n    function deleteRevocationAt(\r\n        CacheState storage _self,\r\n        address _from,\r\n        address _to,\r\n        uint256 _blockNumber\r\n    ) internal returns (uint256 _deleted) {\r\n        bytes32 keyFrom = keccak256(abi.encode(_from, _blockNumber));\r\n        RevocationCacheRecord storage revocationRec = _self.revocationCache[\r\n            keyFrom\r\n        ];\r\n        uint256 value = revocationRec.revocations[_to];\r\n        if (value != 0) {\r\n            delete revocationRec.revocations[_to];\r\n            return 1;\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    /**\r\n     * @notice Returns true if `from` has revoked vote pover delgation of `to` in block `_blockNumber`.\r\n     * @param _self A VotePowerCache instance to manage.\r\n     * @param _from The delegator.\r\n     * @param _to The delegatee.\r\n     * @param _blockNumber Block number of the block to fetch result.\r\n     * precondition: _blockNumber < block.number\r\n     */\r\n    function revokedFromToAt(\r\n        CacheState storage _self,\r\n        address _from,\r\n        address _to,\r\n        uint256 _blockNumber\r\n    ) internal view returns (bool revoked) {\r\n        bytes32 keyFrom = keccak256(abi.encode(_from, _blockNumber));\r\n        return _self.revocationCache[keyFrom].revocations[_to] != 0;\r\n    }\r\n\r\n    function _writeCacheValue(\r\n        CacheState storage _self,\r\n        bytes32 _key,\r\n        uint256 _value\r\n    ) private {\r\n        // store to cacheOf (add 1 to differentiate from empty)\r\n        _self.valueCache[_key] = _value.add(1);\r\n    }\r\n}\r\n"
      },
      "contracts/utils/SafePct.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity 0.8.9;\r\nimport {SafeMath} from \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\n\r\n/**\r\n * @dev Compute percentages safely without phantom overflows.\r\n *\r\n * Intermediate operations can overflow even when the result will always\r\n * fit into computed type. Developers usually\r\n * assume that overflows raise errors. `SafePct` restores this intuition by\r\n * reverting the transaction when such an operation overflows.\r\n *\r\n * Using this library instead of the unchecked operations eliminates an entire\r\n * class of bugs, so it's recommended to use it always.\r\n *\r\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\r\n * all math on `uint256` and `int256` and then downcasting.\r\n */\r\nlibrary SafePct {\r\n    using SafeMath for uint256;\r\n    /**\r\n     * Requirements:\r\n     *\r\n     * - intermediate operations must revert on overflow\r\n     */\r\n    function mulDiv(\r\n        uint256 x,\r\n        uint256 y,\r\n        uint256 z\r\n    ) internal pure returns (uint256) {\r\n        require(z > 0, \"Division by zero\");\r\n\r\n        if (x == 0) return 0;\r\n        uint256 xy = x * y;\r\n        if (xy / x == y) {\r\n            // no overflow happened - same as in SafeMath mul\r\n            return xy / z;\r\n        }\r\n\r\n        //slither-disable-next-line divide-before-multiply\r\n        uint256 a = x / z;\r\n        uint256 b = x % z; // x = a * z + b\r\n\r\n        //slither-disable-next-line divide-before-multiply\r\n        uint256 c = y / z;\r\n        uint256 d = y % z; // y = c * z + d\r\n\r\n        return\r\n            (a.mul(c).mul(z)).add(a.mul(d)).add(b.mul(c)).add(b.mul(d).div(z));\r\n    }\r\n}\r\n"
      },
      "contracts/VPContract.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"./GovernedBase.sol\";\r\nimport \"./Delegatable.sol\";\r\nimport \"./interfaces/IIVPContract.sol\";\r\nimport \"./interfaces/IIVPToken.sol\";\r\nimport \"./interfaces/IVPToken.sol\";\r\n\r\ncontract VPContract is IIVPContract, Delegatable {\r\n    using SafeMath for uint256;\r\n\r\n    /**\r\n     * The VPToken (or some other contract) that owns this VPContract.\r\n     * All state changing methods may be called only from this address.\r\n     * This is because original msg.sender is sent in `_from` parameter\r\n     * and we must be sure that it cannot be faked by directly calling VPContract.\r\n     * Owner token is also used in case of replacement to recover vote powers from balances.\r\n     */\r\n    IVPToken public immutable override ownerToken;\r\n\r\n    /**\r\n     * Return true if this IIVPContract is configured to be used as a replacement for other contract.\r\n     * It means that vote powers are not necessarily correct at the initialization, therefore\r\n     * every method that reads vote power must check whether it is initialized for that address and block.\r\n     */\r\n    bool public immutable override isReplacement;\r\n\r\n    // The block number when vote power for an address was first set.\r\n    // Reading vote power before this block would return incorrect result and must revert.\r\n    mapping(address => uint256) private votePowerInitializationBlock;\r\n\r\n    // Vote power cache for past blocks when vote power was not initialized.\r\n    // Reading vote power at that block would return incorrect result, so cache must be set by some other means.\r\n    // No need for revocation info, since there can be no delegations at such block.\r\n    mapping(bytes32 => uint256) private uninitializedVotePowerCache;\r\n\r\n    string private constant ALREADY_EXPLICIT_MSG =\r\n        \"Already delegated explicitly\";\r\n    string private constant ALREADY_PERCENT_MSG =\r\n        \"Already delegated by percentage\";\r\n\r\n    string internal constant VOTE_POWER_NOT_INITIALIZED =\r\n        \"Vote power not initialized\";\r\n\r\n    /**\r\n     * All external methods in VPContract can only be executed by the owner token.\r\n     */\r\n    modifier onlyOwnerToken() {\r\n        require(msg.sender == address(ownerToken), \"only owner token\");\r\n        _;\r\n    }\r\n\r\n    modifier onlyPercent(address sender) {\r\n        // If a delegate cannot be added by percentage, revert.\r\n        require(_canDelegateByPct(sender), ALREADY_EXPLICIT_MSG);\r\n        _;\r\n    }\r\n\r\n    modifier onlyExplicit(address sender) {\r\n        // If a delegate cannot be added by explicit amount, revert.\r\n        require(_canDelegateByAmount(sender), ALREADY_PERCENT_MSG);\r\n        _;\r\n    }\r\n\r\n    /**\r\n     * Construct VPContract for given VPToken.\r\n     */\r\n    constructor(IVPToken _ownerToken, bool _isReplacement) {\r\n        require(\r\n            address(_ownerToken) != address(0),\r\n            \"VPContract must belong to a VPToken\"\r\n        );\r\n        ownerToken = _ownerToken;\r\n        isReplacement = _isReplacement;\r\n    }\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     * Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n     * history before that block should never be used since it can be inconsistent.\r\n     * In particular, cleanup block number must be before current vote power block.\r\n     * The method can be called only by the owner token.\r\n     * @param _blockNumber The new cleanup block number.\r\n     */\r\n    function setCleanupBlockNumber(\r\n        uint256 _blockNumber\r\n    ) external override onlyOwnerToken {\r\n        _setCleanupBlockNumber(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     * The method can be called only by the owner token.\r\n     */\r\n    function setCleanerContract(\r\n        address _cleanerContract\r\n    ) external override onlyOwnerToken {\r\n        _setCleanerContract(_cleanerContract);\r\n    }\r\n\r\n    /**\r\n     * Update vote powers when tokens are transfered.\r\n     * Also update delegated vote powers for percentage delegation\r\n     * and check for enough funds for explicit delegations.\r\n     **/\r\n    function updateAtTokenTransfer(\r\n        address _from,\r\n        address _to,\r\n        uint256 _fromBalance,\r\n        uint256 _toBalance,\r\n        uint256 _amount\r\n    ) external override onlyOwnerToken {\r\n        if (_from == address(0)) {\r\n            // mint new vote power\r\n            _initializeVotePower(_to, _toBalance);\r\n            _mintVotePower(_to, _toBalance, _amount);\r\n        } else if (_to == address(0)) {\r\n            // burn vote power\r\n            _initializeVotePower(_from, _fromBalance);\r\n            _burnVotePower(_from, _fromBalance, _amount);\r\n        } else {\r\n            // transmit vote power _to receiver\r\n            _initializeVotePower(_from, _fromBalance);\r\n            _initializeVotePower(_to, _toBalance);\r\n            _transmitVotePower(_from, _to, _fromBalance, _toBalance, _amount);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate `_bips` percentage of voting power to `_to` from `_from`\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _balance The delegator's current balance\r\n     * @param _bips The percentage of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 revokes delegation).\r\n     **/\r\n    function delegate(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint256 _bips\r\n    ) external override onlyOwnerToken onlyPercent(_from) {\r\n        _initializeVotePower(_from, _balance);\r\n        if (!_votePowerInitialized(_to)) {\r\n            _initializeVotePower(_to, ownerToken.balanceOf(_to));\r\n        }\r\n        _delegateByPercentage(_from, _to, _balance, _bips);\r\n    }\r\n\r\n    /**\r\n     * @notice Explicitly delegate `_amount` of voting power to `_to` from `_from`.\r\n     * @param _from The address of the delegator\r\n     * @param _to The address of the recipient\r\n     * @param _balance The delegator's current balance\r\n     * @param _amount An explicit vote power amount to be delegated.\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 undelegates `to`).\r\n     **/\r\n    function delegateExplicit(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint _amount\r\n    ) external override onlyOwnerToken onlyExplicit(_from) {\r\n        _initializeVotePower(_from, _balance);\r\n        if (!_votePowerInitialized(_to)) {\r\n            _initializeVotePower(_to, ownerToken.balanceOf(_to));\r\n        }\r\n        _delegateByAmount(_from, _to, _balance, _amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Revoke all delegation from `_from` to `_to` at given block.\r\n     *    Only affects the reads via `votePowerOfAtCached()` in the block `_blockNumber`.\r\n     *    Block `_blockNumber` must be in the past.\r\n     *    This method should be used only to prevent rogue delegate voting in the current voting block.\r\n     *    To stop delegating use delegate/delegateExplicit with value of 0 or undelegateAll/undelegateAllExplicit.\r\n     * @param _from The address of the delegator\r\n     * @param _to Address of the delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @param _blockNumber The block number at which to revoke delegation.\r\n     **/\r\n    function revokeDelegationAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint _blockNumber\r\n    ) external override onlyOwnerToken {\r\n        // ASSERT: if there was a delegation, _from and _to must be initialized\r\n        if (\r\n            !isReplacement ||\r\n            (_votePowerInitializedAt(_from, _blockNumber) &&\r\n                _votePowerInitializedAt(_to, _blockNumber))\r\n        ) {\r\n            _revokeDelegationAt(_from, _to, _balance, _blockNumber);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all voting power for delegates of `_from`\r\n     *    Can only be used with percentage delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     * @param _from The address of the delegator\r\n     **/\r\n    function undelegateAll(\r\n        address _from,\r\n        uint256 _balance\r\n    ) external override onlyOwnerToken onlyPercent(_from) {\r\n        if (_hasAnyDelegations(_from)) {\r\n            // ASSERT: since there were delegations, _from and its targets must be initialized\r\n            _undelegateAllByPercentage(_from, _balance);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all explicit vote power by amount delegates for `_from`.\r\n     *    Can only be used with explicit delegation.\r\n     *    Does not reset delegation mode back to NOTSET.\r\n     * @param _from The address of the delegator\r\n     * @param _delegateAddresses Explicit delegation does not store delegatees' addresses,\r\n     *   so the caller must supply them.\r\n     * @return The amount still delegated (in case the list of delegates was incomplete).\r\n     */\r\n    function undelegateAllExplicit(\r\n        address _from,\r\n        address[] memory _delegateAddresses\r\n    ) external override onlyOwnerToken onlyExplicit(_from) returns (uint256) {\r\n        if (_hasAnyDelegations(_from)) {\r\n            // ASSERT: since there were delegations, _from and its targets must be initialized\r\n            return _undelegateAllByAmount(_from, _delegateAddresses);\r\n        }\r\n        return 0;\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     *   Reads/updates cache and upholds revocations.\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAtCached(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external override returns (uint256) {\r\n        if (!isReplacement || _votePowerInitializedAt(_who, _blockNumber)) {\r\n            // use standard method\r\n            return _votePowerOfAtCached(_who, _blockNumber);\r\n        } else {\r\n            // use uninitialized vote power cache\r\n            bytes32 key = keccak256(abi.encode(_who, _blockNumber));\r\n            uint256 cached = uninitializedVotePowerCache[key];\r\n            if (cached != 0) {\r\n                return cached - 1; // safe, cached != 0\r\n            }\r\n            uint256 balance = ownerToken.balanceOfAt(_who, _blockNumber);\r\n            uninitializedVotePowerCache[key] = balance.add(1);\r\n            return balance;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get the current cleanup block number.\r\n     */\r\n    function cleanupBlockNumber() external view override returns (uint256) {\r\n        return _cleanupBlockNumber();\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_who`.\r\n     * @param _who The address to get voting power.\r\n     * @return Current vote power of `_who`.\r\n     */\r\n    function votePowerOf(\r\n        address _who\r\n    ) external view override returns (uint256) {\r\n        if (_votePowerInitialized(_who)) {\r\n            return _votePowerOf(_who);\r\n        } else {\r\n            return ownerToken.balanceOf(_who);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) public view override returns (uint256) {\r\n        if (!isReplacement || _votePowerInitializedAt(_who, _blockNumber)) {\r\n            return _votePowerOfAt(_who, _blockNumber);\r\n        } else {\r\n            return ownerToken.balanceOfAt(_who, _blockNumber);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_who` at block `_blockNumber`, ignoring revocation information (and cache).\r\n     * @param _who The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_who` at `_blockNumber`. Result doesn't change if vote power is revoked.\r\n     */\r\n    function votePowerOfAtIgnoringRevocation(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        if (!isReplacement || _votePowerInitializedAt(_who, _blockNumber)) {\r\n            return _votePowerOfAtIgnoringRevocation(_who, _blockNumber);\r\n        } else {\r\n            return ownerToken.balanceOfAt(_who, _blockNumber);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Return vote powers for several addresses in a batch.\r\n     * @param _owners The list of addresses to fetch vote power of.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return _votePowers A list of vote powers corresponding to _owners.\r\n     */\r\n    function batchVotePowerOfAt(\r\n        address[] memory _owners,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256[] memory _votePowers) {\r\n        _votePowers = _batchVotePowerOfAt(_owners, _blockNumber);\r\n        // zero results might not have been initialized\r\n        if (isReplacement) {\r\n            for (uint256 i = 0; i < _votePowers.length; i++) {\r\n                if (\r\n                    _votePowers[i] == 0 &&\r\n                    !_votePowerInitializedAt(_owners[i], _blockNumber)\r\n                ) {\r\n                    _votePowers[i] = ownerToken.balanceOfAt(\r\n                        _owners[i],\r\n                        _blockNumber\r\n                    );\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get current delegated vote power `_from` delegator delegated `_to` delegatee.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromTo(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance\r\n    ) external view override returns (uint256) {\r\n        // ASSERT: if the result is nonzero, _from and _to are initialized\r\n        return _votePowerFromTo(_from, _to, _balance);\r\n    }\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _balance The delegator's current balance\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromToAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _balance,\r\n        uint _blockNumber\r\n    ) external view override returns (uint256) {\r\n        // ASSERT: if the result is nonzero, _from and _to were initialized at _blockNumber\r\n        return _votePowerFromToAt(_from, _to, _balance, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the delegation mode for '_who'. This mode determines whether vote power is\r\n     *  allocated by percentage or by explicit value.\r\n     * @param _who The address to get delegation mode.\r\n     * @return Delegation mode (NOTSET=0, PERCENTAGE=1, AMOUNT=2))\r\n     */\r\n    function delegationModeOf(\r\n        address _who\r\n    ) external view override returns (uint256) {\r\n        return uint256(_delegationModeOf(_who));\r\n    }\r\n\r\n    /**\r\n     * @notice Compute the current undelegated vote power of `_owner`\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _balance Owner's current balance\r\n     * @return The unallocated vote power of `_owner`\r\n     */\r\n    function undelegatedVotePowerOf(\r\n        address _owner,\r\n        uint256 _balance\r\n    ) external view override returns (uint256) {\r\n        if (_votePowerInitialized(_owner)) {\r\n            return _undelegatedVotePowerOf(_owner, _balance);\r\n        } else {\r\n            // ASSERT: there are no delegations\r\n            return _balance;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner` at given block.\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The undelegated vote power of `_owner` (= owner's own balance minus all delegations from owner)\r\n     */\r\n    function undelegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _balance,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        if (_votePowerInitialized(_owner)) {\r\n            return _undelegatedVotePowerOfAt(_owner, _balance, _blockNumber);\r\n        } else {\r\n            // ASSERT: there were no delegations at _blockNumber\r\n            return _balance;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `_delegateAddresses`\r\n     *  and `pcts` of an `_owner`. Returned in two separate positional arrays.\r\n     *  Also returns the count of delegates and delegation mode.\r\n     * @param _owner The address to get delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOf(\r\n        address _owner\r\n    )\r\n        external\r\n        view\r\n        override\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        )\r\n    {\r\n        // ASSERT: either _owner is initialized or there are no delegations\r\n        return delegatesOfAt(_owner, block.number);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `_bips` of an `_owner`. Returned in two separate positional arrays.\r\n     *  Also returns the count of delegates and delegation mode.\r\n     * @param _owner The address to get delegations.\r\n     * @param _blockNumber The block for which we want to know the delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    )\r\n        public\r\n        view\r\n        override\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        )\r\n    {\r\n        // ASSERT: either _owner was initialized or there were no delegations\r\n        DelegationMode mode = _delegationModeOf(_owner);\r\n        if (mode == DelegationMode.PERCENTAGE) {\r\n            // Get the vote power delegation for the _owner\r\n            (_delegateAddresses, _bips) = _percentageDelegatesOfAt(\r\n                _owner,\r\n                _blockNumber\r\n            );\r\n        } else if (mode == DelegationMode.NOTSET) {\r\n            _delegateAddresses = new address[](0);\r\n            _bips = new uint256[](0);\r\n        } else {\r\n            revert(\"delegatesOf does not work in AMOUNT delegation mode\");\r\n        }\r\n        _count = _delegateAddresses.length;\r\n        _delegationMode = uint256(mode);\r\n    }\r\n\r\n    /**\r\n     * Initialize vote power to current balance if not initialized already.\r\n     * @param _owner The address to initialize voting power.\r\n     * @param _balance The owner's current balance.\r\n     */\r\n    function _initializeVotePower(address _owner, uint256 _balance) internal {\r\n        if (!isReplacement) return;\r\n        if (_owner == address(0)) return; // 0 address is special (usually marks no source/dest - no init needed)\r\n        if (votePowerInitializationBlock[_owner] == 0) {\r\n            // consistency check - no delegations should be made from or to owner before vote power is initialized\r\n            // (that would be dangerous, because vote power would have been delegated incorrectly)\r\n            assert(_votePowerOf(_owner) == 0 && !_hasAnyDelegations(_owner));\r\n            _mintVotePower(_owner, 0, _balance);\r\n            votePowerInitializationBlock[_owner] = block.number.add(1);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Has the vote power of `_owner` been initialized?\r\n     * @param _owner The address to check.\r\n     * @return true if vote power of _owner is initialized\r\n     */\r\n    function _votePowerInitialized(\r\n        address _owner\r\n    ) internal view returns (bool) {\r\n        if (!isReplacement) return true;\r\n        return votePowerInitializationBlock[_owner] != 0;\r\n    }\r\n\r\n    /**\r\n     * Was vote power of `_owner` initialized at some block?\r\n     * @param _owner The address to check.\r\n     * @param _blockNumber The block for which we want to check.\r\n     * @return true if vote power of _owner was initialized at _blockNumber\r\n     */\r\n    function _votePowerInitializedAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) internal view returns (bool) {\r\n        if (!isReplacement) return true;\r\n        uint256 initblock = votePowerInitializationBlock[_owner];\r\n        return initblock != 0 && initblock - 1 <= _blockNumber;\r\n    }\r\n}\r\n"
      },
      "contracts/VPToken.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./CheckPointable.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"./utils/SafePct.sol\";\r\nimport \"./interfaces/IVPToken.sol\";\r\nimport \"./interfaces/IVPContractEvents.sol\";\r\nimport \"./interfaces/IIVPToken.sol\";\r\nimport \"./interfaces/IIVPContract.sol\";\r\nimport \"./interfaces/IIGovernanceVotePower.sol\";\r\nimport \"./interfaces/IGovernanceVotePower.sol\";\r\nimport \"./Governed.sol\";\r\n\r\n/**\r\n * @title Vote Power Token\r\n * @dev An ERC20 token to enable the holder to delegate voting power\r\n *  equal 1-1 to their balance, with history tracking by block.\r\n **/\r\ncontract VPToken is IIVPToken, ERC20, CheckPointable, Governed {\r\n    using SafeMath for uint256;\r\n    using SafePct for uint256;\r\n\r\n    // the VPContract to use for reading vote powers and delegations\r\n    IIVPContract private readVpContract;\r\n\r\n    // the VPContract to use for writing vote powers and delegations\r\n    // normally same as `readVpContract` except during switch\r\n    // when reading happens from the old and writing goes to the new VPContract\r\n    IIVPContract private writeVpContract;\r\n\r\n    // the contract to use for governance vote power and delegation\r\n    // here only to properly update governance vp during transfers -\r\n    // all actual operations go directly to governance vp contract\r\n    IIGovernanceVotePower private governanceVP;\r\n\r\n    // the contract that is allowed to set cleanupBlockNumber\r\n    // usually this will be an instance of CleanupBlockNumberManager\r\n    address public cleanupBlockNumberManager;\r\n\r\n    /**\r\n     * When true, the argument to `setWriteVpContract` must be a vpContract\r\n     * with `isReplacement` set to `true`. To be used for creating the correct VPContract.\r\n     */\r\n    bool public vpContractInitialized = false;\r\n\r\n    /**\r\n     * Event used to track history of VPToken -> VPContract / GovernanceVotePower\r\n     * associations (e.g. by external cleaners).\r\n     * @param _contractType 0 = read VPContract, 1 = write VPContract, 2 = governance vote power\r\n     * @param _oldContractAddress vote power contract address before change\r\n     * @param _newContractAddress vote power contract address after change\r\n     */\r\n    event VotePowerContractChanged(\r\n        uint256 _contractType,\r\n        address _oldContractAddress,\r\n        address _newContractAddress\r\n    );\r\n\r\n    constructor(\r\n        address _governance,\r\n        //slither-disable-next-line shadowing-local\r\n        string memory _name,\r\n        //slither-disable-next-line shadowing-local\r\n        string memory _symbol\r\n    ) Governed(_governance) ERC20(_name, _symbol) {\r\n        /* empty block */\r\n    }\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function name()\r\n        public\r\n        view\r\n        override(ERC20, IVPToken)\r\n        returns (string memory)\r\n    {\r\n        return ERC20.name();\r\n    }\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function symbol()\r\n        public\r\n        view\r\n        override(ERC20, IVPToken)\r\n        returns (string memory)\r\n    {\r\n        return ERC20.symbol();\r\n    }\r\n\r\n    /**\r\n     * @dev Should be compatible with ERC20 method\r\n     */\r\n    function decimals() public view override(ERC20, IVPToken) returns (uint8) {\r\n        return ERC20.decimals();\r\n    }\r\n\r\n    /**\r\n     * @notice Total amount of tokens at a specific `_blockNumber`.\r\n     * @param _blockNumber The block number when the totalSupply is queried\r\n     * @return The total amount of tokens at `_blockNumber`\r\n     **/\r\n    function totalSupplyAt(\r\n        uint256 _blockNumber\r\n    ) public view override(CheckPointable, IVPToken) returns (uint256) {\r\n        return CheckPointable.totalSupplyAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @dev Queries the token balance of `_owner` at a specific `_blockNumber`.\r\n     * @param _owner The address from which the balance will be retrieved.\r\n     * @param _blockNumber The block number when the balance is queried.\r\n     * @return The balance at `_blockNumber`.\r\n     **/\r\n    function balanceOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) public view override(CheckPointable, IVPToken) returns (uint256) {\r\n        return CheckPointable.balanceOfAt(_owner, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate `_bips` of voting power to `_to` from `msg.sender`\r\n     * @param _to The address of the recipient\r\n     * @param _bips The percentage of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 revokes delegation).\r\n     **/\r\n    function delegate(address _to, uint256 _bips) external override {\r\n        // Get the current balance of sender and delegate by percentage _to recipient\r\n        _checkWriteVpContract().delegate(\r\n            msg.sender,\r\n            _to,\r\n            balanceOf(msg.sender),\r\n            _bips\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all percentage delegations from teh sender and then delegate corresponding\r\n     *   `_bips` percentage of voting power from the sender to each member of `_delegatees`.\r\n     * @param _delegatees The addresses of the new recipients.\r\n     * @param _bips The percentages of voting power to be delegated expressed in basis points (1/100 of one percent).\r\n     *   Total of all `_bips` values must be at most 10000.\r\n     **/\r\n    function batchDelegate(\r\n        address[] memory _delegatees,\r\n        uint256[] memory _bips\r\n    ) external override {\r\n        require(_delegatees.length == _bips.length, \"Array length mismatch\");\r\n        IIVPContract vpContract = _checkWriteVpContract();\r\n        uint256 balance = balanceOf(msg.sender);\r\n        vpContract.undelegateAll(msg.sender, balance);\r\n        for (uint256 i = 0; i < _delegatees.length; i++) {\r\n            vpContract.delegate(msg.sender, _delegatees[i], balance, _bips[i]);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Delegate `_amount` of voting power to `_to` from `msg.sender`\r\n     * @param _to The address of the recipient\r\n     * @param _amount An explicit vote power amount to be delegated.\r\n     *   Not cummulative - every call resets the delegation value (and value of 0 revokes delegation).\r\n     **/\r\n    function delegateExplicit(address _to, uint256 _amount) external override {\r\n        _checkWriteVpContract().delegateExplicit(\r\n            msg.sender,\r\n            _to,\r\n            balanceOf(msg.sender),\r\n            _amount\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Compute the current undelegated vote power of `_owner`\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @return The unallocated vote power of `_owner`\r\n     */\r\n    function undelegatedVotePowerOf(\r\n        address _owner\r\n    ) external view override returns (uint256) {\r\n        return\r\n            _checkReadVpContract().undelegatedVotePowerOf(\r\n                _owner,\r\n                balanceOf(_owner)\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get the undelegated vote power of `_owner` at given block.\r\n     * @param _owner The address to get undelegated voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The unallocated vote power of `_owner`\r\n     */\r\n    function undelegatedVotePowerOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        return\r\n            _checkReadVpContract().undelegatedVotePowerOfAt(\r\n                _owner,\r\n                balanceOfAt(_owner, _blockNumber),\r\n                _blockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all voting power for delegates of `msg.sender`\r\n     **/\r\n    function undelegateAll() external override {\r\n        _checkWriteVpContract().undelegateAll(\r\n            msg.sender,\r\n            balanceOf(msg.sender)\r\n        );\r\n    }\r\n\r\n    /**\r\n     * @notice Undelegate all explicit vote power by amount delegates for `msg.sender`.\r\n     * @param _delegateAddresses Explicit delegation does not store delegatees' addresses,\r\n     *   so the caller must supply them.\r\n     * @return _remainingDelegation The amount still delegated (in case the list of delegates was incomplete).\r\n     */\r\n    function undelegateAllExplicit(\r\n        address[] memory _delegateAddresses\r\n    ) external override returns (uint256 _remainingDelegation) {\r\n        return\r\n            _checkWriteVpContract().undelegateAllExplicit(\r\n                msg.sender,\r\n                _delegateAddresses\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Revoke all delegation from sender to `_who` at given block.\r\n     *    Only affects the reads via `votePowerOfAtCached()` in the block `_blockNumber`.\r\n     *    Block `_blockNumber` must be in the past.\r\n     *    This method should be used only to prevent rogue delegate voting in the current voting block.\r\n     *    To stop delegating use delegate/delegateExplicit with value of 0 or undelegateAll/undelegateAllExplicit.\r\n     */\r\n    function revokeDelegationAt(\r\n        address _who,\r\n        uint256 _blockNumber\r\n    ) public override {\r\n        IIVPContract writeVPC = writeVpContract;\r\n        IIVPContract readVPC = readVpContract;\r\n        if (address(writeVPC) != address(0)) {\r\n            writeVPC.revokeDelegationAt(\r\n                msg.sender,\r\n                _who,\r\n                balanceOfAt(msg.sender, _blockNumber),\r\n                _blockNumber\r\n            );\r\n        }\r\n        if (\r\n            address(readVPC) != address(writeVPC) &&\r\n            address(readVPC) != address(0)\r\n        ) {\r\n            try\r\n                readVPC.revokeDelegationAt(\r\n                    msg.sender,\r\n                    _who,\r\n                    balanceOfAt(msg.sender, _blockNumber),\r\n                    _blockNumber\r\n                )\r\n            {} catch {\r\n                // do nothing\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Get current delegated vote power `_from` delegator delegated `_to` delegatee.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @return votePower The delegated vote power.\r\n     */\r\n    function votePowerFromTo(\r\n        address _from,\r\n        address _to\r\n    ) external view override returns (uint256) {\r\n        return\r\n            _checkReadVpContract().votePowerFromTo(\r\n                _from,\r\n                _to,\r\n                balanceOf(_from)\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get delegated the vote power `_from` delegator delegated `_to` delegatee at `_blockNumber`.\r\n     * @param _from Address of delegator\r\n     * @param _to Address of delegatee\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The delegated vote power.\r\n     */\r\n    function votePowerFromToAt(\r\n        address _from,\r\n        address _to,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        return\r\n            _checkReadVpContract().votePowerFromToAt(\r\n                _from,\r\n                _to,\r\n                balanceOfAt(_from, _blockNumber),\r\n                _blockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current total vote power.\r\n     * @return The current total vote power (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePower() external view override returns (uint256) {\r\n        return totalSupply();\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total vote power at block `_blockNumber`\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The total vote power at the block  (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePowerAt(\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        return totalSupplyAt(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the total vote power at block `_blockNumber` using cache.\r\n     *   It tries to read the cached value and if not found, reads the actual value and stores it in cache.\r\n     *   Can only be used if `_blockNumber` is in the past, otherwise reverts.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return The total vote power at the block (sum of all accounts' vote powers).\r\n     */\r\n    function totalVotePowerAtCached(\r\n        uint256 _blockNumber\r\n    ) public override returns (uint256) {\r\n        return _totalSupplyAtCached(_blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the delegation mode for '_who'. This mode determines whether vote power is\r\n     *  allocated by percentage or by explicit value. Once the delegation mode is set,\r\n     *  it never changes, even if all delegations are removed.\r\n     * @param _who The address to get delegation mode.\r\n     * @return delegation mode: 0 = NOTSET, 1 = PERCENTAGE, 2 = AMOUNT (i.e. explicit)\r\n     */\r\n    function delegationModeOf(\r\n        address _who\r\n    ) external view override returns (uint256) {\r\n        return _checkReadVpContract().delegationModeOf(_who);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the current vote power of `_owner`.\r\n     * @param _owner The address to get voting power.\r\n     * @return Current vote power of `_owner`.\r\n     */\r\n    function votePowerOf(\r\n        address _owner\r\n    ) external view override returns (uint256) {\r\n        return _checkReadVpContract().votePowerOf(_owner);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber`\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        return _checkReadVpContract().votePowerOfAt(_owner, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber`, ignoring revocation information (and cache).\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`. Result doesn't change if vote power is revoked.\r\n     */\r\n    function votePowerOfAtIgnoringRevocation(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256) {\r\n        return\r\n            _checkReadVpContract().votePowerOfAtIgnoringRevocation(\r\n                _owner,\r\n                _blockNumber\r\n            );\r\n    }\r\n\r\n    /**\r\n     * Return vote powers for several addresses in a batch.\r\n     * @param _owners The list of addresses to fetch vote power of.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return A list of vote powers.\r\n     */\r\n    function batchVotePowerOfAt(\r\n        address[] memory _owners,\r\n        uint256 _blockNumber\r\n    ) external view override returns (uint256[] memory) {\r\n        return _checkReadVpContract().batchVotePowerOfAt(_owners, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power of `_owner` at block `_blockNumber` using cache.\r\n     *   It tries to read the cached value and if not found, reads the actual value and stores it in cache.\r\n     *   Can only be used if _blockNumber is in the past, otherwise reverts.\r\n     * @param _owner The address to get voting power.\r\n     * @param _blockNumber The block number at which to fetch.\r\n     * @return Vote power of `_owner` at `_blockNumber`.\r\n     */\r\n    function votePowerOfAtCached(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    ) public override returns (uint256) {\r\n        return _checkReadVpContract().votePowerOfAtCached(_owner, _blockNumber);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `_bips` of `_who`. Returned in two separate positional arrays.\r\n     * @param _owner The address to get delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOf(\r\n        address _owner\r\n    )\r\n        external\r\n        view\r\n        override\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        )\r\n    {\r\n        return _checkReadVpContract().delegatesOf(_owner);\r\n    }\r\n\r\n    /**\r\n     * @notice Get the vote power delegation `delegationAddresses`\r\n     *  and `pcts` of `_who`. Returned in two separate positional arrays.\r\n     * @param _owner The address to get delegations.\r\n     * @param _blockNumber The block for which we want to know the delegations.\r\n     * @return _delegateAddresses Positional array of delegation addresses.\r\n     * @return _bips Positional array of delegation percents specified in basis points (1/100 or 1 percent)\r\n     * @return _count The number of delegates.\r\n     * @return _delegationMode The mode of the delegation (NOTSET=0, PERCENTAGE=1, AMOUNT=2).\r\n     */\r\n    function delegatesOfAt(\r\n        address _owner,\r\n        uint256 _blockNumber\r\n    )\r\n        external\r\n        view\r\n        override\r\n        returns (\r\n            address[] memory _delegateAddresses,\r\n            uint256[] memory _bips,\r\n            uint256 _count,\r\n            uint256 _delegationMode\r\n        )\r\n    {\r\n        return _checkReadVpContract().delegatesOfAt(_owner, _blockNumber);\r\n    }\r\n\r\n    // Update vote power and balance checkpoints before balances are modified. This is implemented\r\n    // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.\r\n    function _beforeTokenTransfer(\r\n        address _from,\r\n        address _to,\r\n        uint256 _amount\r\n    ) internal virtual override(ERC20) {\r\n        require(_from != _to, \"Cannot transfer to self\");\r\n\r\n        uint256 fromBalance = _from != address(0) ? balanceOf(_from) : 0;\r\n        uint256 toBalance = _to != address(0) ? balanceOf(_to) : 0;\r\n\r\n        // update vote powers\r\n        IIVPContract vpc = writeVpContract;\r\n        if (address(vpc) != address(0)) {\r\n            vpc.updateAtTokenTransfer(\r\n                _from,\r\n                _to,\r\n                fromBalance,\r\n                toBalance,\r\n                _amount\r\n            );\r\n        } else if (!vpContractInitialized) {\r\n            // transfers without vpcontract are allowed, but after they are made\r\n            // any added vpcontract must have isReplacement set\r\n            vpContractInitialized = true;\r\n        }\r\n\r\n        // update governance vote powers\r\n        IIGovernanceVotePower gvp = governanceVP;\r\n        if (address(gvp) != address(0)) {\r\n            gvp.updateAtTokenTransfer(\r\n                _from,\r\n                _to,\r\n                fromBalance,\r\n                toBalance,\r\n                _amount\r\n            );\r\n        }\r\n\r\n        // update balance history\r\n        _updateBalanceHistoryAtTransfer(_from, _to, _amount);\r\n    }\r\n\r\n    /**\r\n     * Call from governance to set read VpContract on token, e.g.\r\n     * `vpToken.setReadVpContract(new VPContract(vpToken))`\r\n     * Read VPContract must be set before any of the VPToken delegation or vote power reading methods are called,\r\n     * otherwise they will revert.\r\n     * NOTE: If readVpContract differs from writeVpContract all reads will be \"frozen\" and will not reflect\r\n     * changes (not even revokes; they may or may not reflect balance transfers).\r\n     * @param _vpContract Read vote power contract to be used by this token.\r\n     */\r\n    function setReadVpContract(\r\n        IIVPContract _vpContract\r\n    ) external onlyGovernance {\r\n        if (address(_vpContract) != address(0)) {\r\n            require(\r\n                address(_vpContract.ownerToken()) == address(this),\r\n                \"VPContract not owned by this token\"\r\n            );\r\n            // set contract's cleanup block\r\n            _vpContract.setCleanupBlockNumber(_cleanupBlockNumber());\r\n        }\r\n        emit VotePowerContractChanged(\r\n            0,\r\n            address(readVpContract),\r\n            address(_vpContract)\r\n        );\r\n        readVpContract = _vpContract;\r\n    }\r\n\r\n    /**\r\n     * Call from governance to set write VpContract on token, e.g.\r\n     * `vpToken.setWriteVpContract(new VPContract(vpToken))`\r\n     * Write VPContract must be set before any of the VPToken delegation modifying methods are called,\r\n     * otherwise they will revert.\r\n     * @param _vpContract Write vote power contract to be used by this token.\r\n     */\r\n    function setWriteVpContract(\r\n        IIVPContract _vpContract\r\n    ) external onlyGovernance {\r\n        if (address(_vpContract) != address(0)) {\r\n            require(\r\n                address(_vpContract.ownerToken()) == address(this),\r\n                \"VPContract not owned by this token\"\r\n            );\r\n            require(\r\n                !vpContractInitialized || _vpContract.isReplacement(),\r\n                \"VPContract not configured for replacement\"\r\n            );\r\n            // set contract's cleanup block\r\n            _vpContract.setCleanupBlockNumber(_cleanupBlockNumber());\r\n            // once a non-null vpcontract is set, every other has to have isReplacement flag set\r\n            vpContractInitialized = true;\r\n        }\r\n        emit VotePowerContractChanged(\r\n            1,\r\n            address(writeVpContract),\r\n            address(_vpContract)\r\n        );\r\n        writeVpContract = _vpContract;\r\n    }\r\n\r\n    /**\r\n     * Return read vpContract, ensuring that it is not zero.\r\n     */\r\n    function _checkReadVpContract() internal view returns (IIVPContract) {\r\n        IIVPContract vpc = readVpContract;\r\n        require(address(vpc) != address(0), \"Token missing read VPContract\");\r\n        return vpc;\r\n    }\r\n\r\n    /**\r\n     * Return write vpContract, ensuring that it is not zero.\r\n     */\r\n    function _checkWriteVpContract() internal view returns (IIVPContract) {\r\n        IIVPContract vpc = writeVpContract;\r\n        require(address(vpc) != address(0), \"Token missing write VPContract\");\r\n        return vpc;\r\n    }\r\n\r\n    /**\r\n     * Return vpContract use for reading, may be zero.\r\n     */\r\n    function _getReadVpContract() internal view returns (IIVPContract) {\r\n        return readVpContract;\r\n    }\r\n\r\n    /**\r\n     * Return vpContract use for writing, may be zero.\r\n     */\r\n    function _getWriteVpContract() internal view returns (IIVPContract) {\r\n        return writeVpContract;\r\n    }\r\n\r\n    /**\r\n     * Returns VPContract event interface used for readonly operations (view methods).\r\n     */\r\n    function readVotePowerContract()\r\n        external\r\n        view\r\n        override\r\n        returns (IVPContractEvents)\r\n    {\r\n        return readVpContract;\r\n    }\r\n\r\n    /**\r\n     * Returns VPContract event interface used for state changing operations (non-view methods).\r\n     */\r\n    function writeVotePowerContract()\r\n        external\r\n        view\r\n        override\r\n        returns (IVPContractEvents)\r\n    {\r\n        return writeVpContract;\r\n    }\r\n\r\n    /**\r\n     * Set the cleanup block number.\r\n     * Historic data for the blocks before `cleanupBlockNumber` can be erased,\r\n     * history before that block should never be used since it can be inconsistent.\r\n     * In particular, cleanup block number must be before current vote power block.\r\n     * @param _blockNumber The new cleanup block number.\r\n     */\r\n    function setCleanupBlockNumber(uint256 _blockNumber) external override {\r\n        require(\r\n            msg.sender == cleanupBlockNumberManager,\r\n            \"only cleanup block manager\"\r\n        );\r\n        _setCleanupBlockNumber(_blockNumber);\r\n        if (address(readVpContract) != address(0)) {\r\n            readVpContract.setCleanupBlockNumber(_blockNumber);\r\n        }\r\n        if (\r\n            address(writeVpContract) != address(0) &&\r\n            address(writeVpContract) != address(readVpContract)\r\n        ) {\r\n            writeVpContract.setCleanupBlockNumber(_blockNumber);\r\n        }\r\n        if (address(governanceVP) != address(0)) {\r\n            governanceVP.setCleanupBlockNumber(_blockNumber);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get the current cleanup block number.\r\n     */\r\n    function cleanupBlockNumber() external view override returns (uint256) {\r\n        return _cleanupBlockNumber();\r\n    }\r\n\r\n    /**\r\n     * Set the contract that is allowed to set cleanupBlockNumber.\r\n     * Usually this will be an instance of CleanupBlockNumberManager.\r\n     */\r\n    function setCleanupBlockNumberManager(\r\n        address _cleanupBlockNumberManager\r\n    ) external override onlyGovernance {\r\n        cleanupBlockNumberManager = _cleanupBlockNumberManager;\r\n    }\r\n\r\n    /**\r\n     * Set the contract that is allowed to call history cleaning methods.\r\n     */\r\n    function setCleanerContract(\r\n        address _cleanerContract\r\n    ) external override onlyGovernance {\r\n        _setCleanerContract(_cleanerContract);\r\n        if (address(readVpContract) != address(0)) {\r\n            readVpContract.setCleanerContract(_cleanerContract);\r\n        }\r\n        if (\r\n            address(writeVpContract) != address(0) &&\r\n            address(writeVpContract) != address(readVpContract)\r\n        ) {\r\n            writeVpContract.setCleanerContract(_cleanerContract);\r\n        }\r\n        if (address(governanceVP) != address(0)) {\r\n            governanceVP.setCleanerContract(_cleanerContract);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Sets new governance vote power contract that allows token owners to participate in governance voting\r\n     * and delegate governance vote power.\r\n     */\r\n    function setGovernanceVotePower(\r\n        IIGovernanceVotePower _governanceVotePower\r\n    ) external override onlyGovernance {\r\n        require(\r\n            address(_governanceVotePower.ownerToken()) == address(this),\r\n            \"Governance vote power contract does not belong to this token.\"\r\n        );\r\n        emit VotePowerContractChanged(\r\n            2,\r\n            address(governanceVP),\r\n            address(_governanceVotePower)\r\n        );\r\n        governanceVP = _governanceVotePower;\r\n    }\r\n\r\n    /**\r\n     * When set, allows token owners to participate in governance voting\r\n     * and delegate governance vote power.\r\n     */\r\n    function governanceVotePower()\r\n        external\r\n        view\r\n        override\r\n        returns (IGovernanceVotePower)\r\n    {\r\n        return governanceVP;\r\n    }\r\n}\r\n"
      },
      "contracts/WNAT.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.9;\r\n\r\nimport \"./VPToken.sol\";\r\nimport \"./VPContract.sol\";\r\nimport \"./interfaces/IWNat.sol\";\r\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\n/**\r\n * @title Wrapped WFO token\r\n * @notice Accept WFO token deposits and mint ERC20 WNAT (wrapped wfo) tokens 1-1.\r\n */\r\ncontract WNat is VPToken, IWNat {\r\n    using SafeMath for uint256;\r\n\r\n    IERC20 wfoToken;\r\n\r\n    event Deposit(address indexed dst, uint amount);\r\n    event Withdrawal(address indexed src, uint amount);\r\n\r\n    /**\r\n     * Construct an ERC20 token.\r\n     */\r\n    constructor(\r\n        address _governance,\r\n        address _wfoToken,\r\n        string memory _name,\r\n        string memory _symbol\r\n    ) VPToken(_governance, _name, _symbol) {\r\n        wfoToken = IERC20(_wfoToken);\r\n    }\r\n\r\n    /**\r\n     * @notice Withdraw WNAT from an owner and send wfo tokens to msg.sender given an allowance.\r\n     * @param owner An address spending the wfo tokens.\r\n     * @param amount The amount to spend.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `owner` must have a balance of at least `amount`.\r\n     * - the caller must have allowance for `owners`'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function withdrawFrom(address owner, uint256 amount) external override {\r\n        // Reduce senders allowance\r\n        _approve(\r\n            owner,\r\n            msg.sender,\r\n            allowance(owner, msg.sender).sub(amount, \"allowance below zero\")\r\n        );\r\n        // Burn the owners balance\r\n        _burn(owner, amount);\r\n        // Emit withdraw event\r\n        emit Withdrawal(owner, amount);\r\n        // Move value to sender (last statement, to prevent reentrancy)\r\n        wfoToken.transfer(msg.sender, amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Deposit wfo from msg.sender and mints WNAT ERC20 to recipient address.\r\n     * @param recipient An address to receive minted WNAT.\r\n     */\r\n    function depositTo(address recipient, uint256 amount) external {\r\n        require(recipient != address(0), \"Cannot deposit to zero address\");\r\n        //Transfer WFO\r\n        wfoToken.transferFrom(msg.sender, address(this), amount);\r\n        // Mint WNAT\r\n        _mint(recipient, amount);\r\n        // Emit deposit event\r\n        emit Deposit(recipient, amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Deposit wfo and mint wNat ERC20.\r\n     */\r\n    function deposit(uint256 amount) public {\r\n        //Transfer WFO\r\n        wfoToken.transferFrom(msg.sender, address(this), amount);\r\n        // Mint WNAT\r\n        _mint(msg.sender, amount);\r\n        // Emit deposit event\r\n        emit Deposit(msg.sender, amount);\r\n    }\r\n\r\n    /**\r\n     * @notice Withdraw wfo and burn WNAT ERC20.\r\n     * @param amount The amount to withdraw.\r\n     */\r\n    function withdraw(uint256 amount) external {\r\n        // Burn WNAT tokens\r\n        _burn(msg.sender, amount);\r\n        // Emit withdrawal event\r\n        emit Withdrawal(msg.sender, amount);\r\n        // Send wfo to sender (last statement, to prevent reentrancy)\r\n        wfoToken.transfer(msg.sender, amount);\r\n    }\r\n}\r\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}