ETH Price: $3,560.16 (-0.48%)
Gas: 22 Gwei

Contract

0x2c2b362e6ae0F080F39b90Cb5657E5550090D6C3
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Withdraw All ERC...168415512023-03-16 16:19:35378 days ago1678983575IN
0x2c2b362e...50090D6C3
0 ETH0.0032490538.78081884
Withdraw All ERC...168036042023-03-11 8:18:23384 days ago1678522703IN
0x2c2b362e...50090D6C3
0 ETH0.01641877270.06778169
Withdraw All ERC...168036012023-03-11 8:17:47384 days ago1678522667IN
0x2c2b362e...50090D6C3
0 ETH0.02241007287.76237537
Withdraw All To ...168035132023-03-11 7:59:35384 days ago1678521575IN
0x2c2b362e...50090D6C3
0 ETH0.23045538289.81646852
Withdraw To Safe...159842452022-11-16 18:03:35498 days ago1668621815IN
0x2c2b362e...50090D6C3
0 ETH0.0171701819.10530451
Withdraw All ERC...159219822022-11-08 1:19:35507 days ago1667870375IN
0x2c2b362e...50090D6C3
0 ETH0.0011260413.44047614
Withdraw All ERC...157695812022-10-17 18:21:47528 days ago1666030907IN
0x2c2b362e...50090D6C3
0 ETH0.0021507332.27640726
Withdraw ERC20To...157695242022-10-17 18:10:23528 days ago1666030223IN
0x2c2b362e...50090D6C3
0 ETH0.0034394741.50297566
Withdraw To Safe...157636362022-10-16 22:24:11529 days ago1665959051IN
0x2c2b362e...50090D6C3
0 ETH0.0031095615.23518832
Withdraw All ERC...156272192022-09-27 20:58:35548 days ago1664312315IN
0x2c2b362e...50090D6C3
0 ETH0.0012005114.09853541
Withdraw To Safe...156057602022-09-24 20:59:35551 days ago1664053175IN
0x2c2b362e...50090D6C3
0 ETH0.001103595.66765731
Withdraw To Safe...155407832022-09-15 18:10:11560 days ago1663265411IN
0x2c2b362e...50090D6C3
0 ETH0.005185527.29876458
Withdraw To Safe...154982722022-09-08 18:55:06567 days ago1662663306IN
0x2c2b362e...50090D6C3
0 ETH0.0076339.78517574
Withdraw ERC20To...154981342022-09-08 18:22:14567 days ago1662661334IN
0x2c2b362e...50090D6C3
0 ETH0.0030161138.22796726
Withdraw To Safe...154619802022-09-02 23:21:06573 days ago1662160866IN
0x2c2b362e...50090D6C3
0 ETH0.000673710.05928067
Withdraw All ERC...154495162022-08-31 23:36:24575 days ago1661988984IN
0x2c2b362e...50090D6C3
0 ETH0.0017543428.85678847
Withdraw All To ...154495152022-08-31 23:35:43575 days ago1661988943IN
0x2c2b362e...50090D6C3
0 ETH0.0021306730.19707683
Withdraw All ERC...154045482022-08-24 18:47:57582 days ago1661366877IN
0x2c2b362e...50090D6C3
0 ETH0.0017912329.4635181
Withdraw All ERC...153470982022-08-15 16:39:11591 days ago1660581551IN
0x2c2b362e...50090D6C3
0 ETH0.0014691524.24306481
Withdraw ERC20To...152776952022-08-04 19:20:18602 days ago1659640818IN
0x2c2b362e...50090D6C3
0 ETH0.00088113.60056851
Withdraw ERC20To...152776862022-08-04 19:17:49602 days ago1659640669IN
0x2c2b362e...50090D6C3
0 ETH0.0010296815.89588744
Withdraw ERC20To...152776512022-08-04 19:07:48602 days ago1659640068IN
0x2c2b362e...50090D6C3
0 ETH0.0007035410.86095421
Withdraw ERC20To...151697742022-07-19 0:16:34619 days ago1658189794IN
0x2c2b362e...50090D6C3
0 ETH0.0038087661.72731123
Withdraw ERC20To...150911772022-07-06 20:38:52631 days ago1657139932IN
0x2c2b362e...50090D6C3
0 ETH0.0011831717.16635506
Withdraw ERC20To...150911462022-07-06 20:34:39631 days ago1657139679IN
0x2c2b362e...50090D6C3
0 ETH0.0011737724.82133855
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PCVGuardian

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 21 : PCVGuardian.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {CoreRef} from "../refs/CoreRef.sol";
import {IPCVGuardian} from "./IPCVGuardian.sol";
import {IPCVDeposit} from "./IPCVDeposit.sol";
import {CoreRefPausableLib} from "../libs/CoreRefPausableLib.sol";
import {TribeRoles} from "../core/TribeRoles.sol";

/// @notice PCV Guardian is a contract to safeguard protocol funds
/// by being able to withdraw whitelisted PCV deposits to an immutable safe address
contract PCVGuardian is IPCVGuardian, CoreRef {
    using CoreRefPausableLib for address;
    using EnumerableSet for EnumerableSet.AddressSet;

    ///@notice set of whitelisted pcvDeposit addresses for withdrawal
    EnumerableSet.AddressSet private whitelistAddresses;

    ///@notice safe address where PCV funds can be withdrawn to
    address public immutable safeAddress;

    constructor(
        address _core,
        address _safeAddress,
        address[] memory _whitelistAddresses
    ) CoreRef(_core) {
        safeAddress = _safeAddress;

        // improbable to ever overflow
        unchecked {
            for (uint256 i = 0; i < _whitelistAddresses.length; i++) {
                _addWhitelistAddress(_whitelistAddresses[i]);
            }
        }
    }

    /// @dev checks if a pcv deposit address is whitelisted, reverts if not
    modifier onlyWhitelist(address pcvDeposit) {
        require(
            isWhitelistAddress(pcvDeposit),
            "PCVGuardian: Provided address is not whitelisted"
        );
        _;
    }

    // ---------- Read-Only API ----------

    /// @notice returns true if the the provided address is a valid destination to withdraw funds from
    /// @param pcvDeposit the pcvDeposit address to check if whitelisted
    function isWhitelistAddress(address pcvDeposit)
        public
        view
        override
        returns (bool)
    {
        return whitelistAddresses.contains(pcvDeposit);
    }

    /// @notice returns all whitelisted pcvDeposit addresses
    function getWhitelistAddresses()
        public
        view
        override
        returns (address[] memory)
    {
        return whitelistAddresses.values();
    }

    // ---------- Governor-Only State-Changing API ----------

    /// @notice governor-only method to whitelist a pcvDeposit address to withdraw funds from
    /// @param pcvDeposit the address to whitelist
    function addWhitelistAddress(address pcvDeposit)
        external
        override
        onlyGovernor
    {
        _addWhitelistAddress(pcvDeposit);
    }

    /// @notice batch version of addWhiteListaddress
    /// @param _whitelistAddresses the addresses to whitelist, as calldata
    function addWhitelistAddresses(address[] calldata _whitelistAddresses)
        external
        override
        onlyGovernor
    {
        // improbable to ever overflow
        unchecked {
            for (uint256 i = 0; i < _whitelistAddresses.length; i++) {
                _addWhitelistAddress(_whitelistAddresses[i]);
            }
        }
    }

    // ---------- Governor-Or-Guardian-Only State-Changing API ----------

    /// @notice governor-or-guardian-only method to remove pcvDeposit address from the whitelist to withdraw funds from
    /// @param pcvDeposit the address to remove from whitelist
    function removeWhitelistAddress(address pcvDeposit)
        external
        override
        onlyGuardianOrGovernor
    {
        _removeWhitelistAddress(pcvDeposit);
    }

    /// @notice batch version of removeWhitelistAddress
    /// @param _whitelistAddresses the addresses to remove from whitelist
    function removeWhitelistAddresses(address[] calldata _whitelistAddresses)
        external
        override
        onlyGuardianOrGovernor
    {
        // improbable to ever overflow
        unchecked {
            for (uint256 i = 0; i < _whitelistAddresses.length; i++) {
                _removeWhitelistAddress(_whitelistAddresses[i]);
            }
        }
    }

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw funds from a pcv deposit, by calling the withdraw() method on it
    /// @param pcvDeposit the address of the pcv deposit contract
    /// @param amount the amount to withdraw
    function withdrawToSafeAddress(address pcvDeposit, uint256 amount)
        external
        override
        hasAnyOfThreeRoles(
            TribeRoles.GOVERNOR,
            TribeRoles.GUARDIAN,
            TribeRoles.PCV_GUARD
        )
        onlyWhitelist(pcvDeposit)
    {
        _withdrawToSafeAddress(pcvDeposit, amount);
    }

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw all at once funds from a pcv deposit, by calling the withdraw() method on it
    /// @param pcvDeposit the address of the pcv deposit contract
    function withdrawAllToSafeAddress(address pcvDeposit)
        external
        override
        hasAnyOfThreeRoles(
            TribeRoles.GOVERNOR,
            TribeRoles.GUARDIAN,
            TribeRoles.PCV_GUARD
        )
        onlyWhitelist(pcvDeposit)
    {
        _withdrawToSafeAddress(pcvDeposit, IPCVDeposit(pcvDeposit).balance());
    }

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw an ERC20 from a pcv deposit, by calling the withdrawERC20() method on it
    /// @param pcvDeposit the deposit to pull funds from
    /// @param token the address of the token to withdraw
    /// @param amount the amount of funds to withdraw
    function withdrawERC20ToSafeAddress(
        address pcvDeposit,
        address token,
        uint256 amount
    )
        external
        override
        hasAnyOfThreeRoles(
            TribeRoles.GOVERNOR,
            TribeRoles.GUARDIAN,
            TribeRoles.PCV_GUARD
        )
        onlyWhitelist(pcvDeposit)
    {
        _withdrawERC20ToSafeAddress(pcvDeposit, token, amount);
    }

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw all of an ERC20 balance from a pcv deposit, by calling the withdrawERC20() method on it
    /// @param pcvDeposit the deposit to pull funds from
    /// @param token the address of the token to withdraw
    function withdrawAllERC20ToSafeAddress(address pcvDeposit, address token)
        external
        override
        hasAnyOfThreeRoles(
            TribeRoles.GOVERNOR,
            TribeRoles.GUARDIAN,
            TribeRoles.PCV_GUARD
        )
        onlyWhitelist(pcvDeposit)
    {
        _withdrawERC20ToSafeAddress(
            pcvDeposit,
            token,
            IERC20(token).balanceOf(pcvDeposit)
        );
    }

    // ---------- Internal Functions ----------

    function _withdrawToSafeAddress(address pcvDeposit, uint256 amount)
        internal
    {
        if (pcvDeposit._paused()) {
            pcvDeposit._unpause();
            IPCVDeposit(pcvDeposit).withdraw(safeAddress, amount);
            pcvDeposit._pause();
        } else {
            IPCVDeposit(pcvDeposit).withdraw(safeAddress, amount);
        }

        emit PCVGuardianWithdrawal(pcvDeposit, amount);
    }

    function _withdrawERC20ToSafeAddress(
        address pcvDeposit,
        address token,
        uint256 amount
    ) internal {
        IPCVDeposit(pcvDeposit).withdrawERC20(token, safeAddress, amount);
        emit PCVGuardianERC20Withdrawal(pcvDeposit, token, amount);
    }

    function _addWhitelistAddress(address pcvDeposit) internal {
        require(
            whitelistAddresses.add(pcvDeposit),
            "PCVGuardian: Failed to add address to whitelist"
        );
        emit WhitelistAddressAdded(pcvDeposit);
    }

    function _removeWhitelistAddress(address pcvDeposit) internal {
        require(
            whitelistAddresses.remove(pcvDeposit),
            "PCVGuardian: Failed to remove address from whitelist"
        );
        emit WhitelistAddressRemoved(pcvDeposit);
    }
}

File 3 of 21 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 5 of 21 : CoreRef.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import "./ICoreRef.sol";
import "@openzeppelin/contracts/security/Pausable.sol";

/// @title A Reference to Core
/// @author Fei Protocol
/// @notice defines some modifiers and utilities around interacting with Core
abstract contract CoreRef is ICoreRef, Pausable {
    ICore private immutable _core;
    IVolt private immutable _volt;
    IERC20 private immutable _vcon;

    /// @notice a role used with a subset of governor permissions for this contract only
    bytes32 public override CONTRACT_ADMIN_ROLE;

    constructor(address coreAddress) {
        _core = ICore(coreAddress);

        _volt = ICore(coreAddress).volt();
        _vcon = ICore(coreAddress).vcon();

        _setContractAdminRole(ICore(coreAddress).GOVERN_ROLE());
    }

    function _initialize() internal {} // no-op for backward compatibility

    modifier ifMinterSelf() {
        if (_core.isMinter(address(this))) {
            _;
        }
    }

    modifier onlyMinter() {
        require(_core.isMinter(msg.sender), "CoreRef: Caller is not a minter");
        _;
    }

    modifier onlyBurner() {
        require(_core.isBurner(msg.sender), "CoreRef: Caller is not a burner");
        _;
    }

    modifier onlyPCVController() {
        require(
            _core.isPCVController(msg.sender),
            "CoreRef: Caller is not a PCV controller"
        );
        _;
    }

    modifier onlyGovernorOrAdmin() {
        require(
            _core.isGovernor(msg.sender) || isContractAdmin(msg.sender),
            "CoreRef: Caller is not a governor or contract admin"
        );
        _;
    }

    modifier onlyGovernor() {
        require(
            _core.isGovernor(msg.sender),
            "CoreRef: Caller is not a governor"
        );
        _;
    }

    modifier onlyGuardianOrGovernor() {
        require(
            _core.isGovernor(msg.sender) || _core.isGuardian(msg.sender),
            "CoreRef: Caller is not a guardian or governor"
        );
        _;
    }

    modifier onlyGovernorOrGuardianOrAdmin() {
        require(
            _core.isGovernor(msg.sender) ||
                _core.isGuardian(msg.sender) ||
                isContractAdmin(msg.sender),
            "CoreRef: Caller is not governor or guardian or admin"
        );
        _;
    }

    // Named onlyTribeRole to prevent collision with OZ onlyRole modifier
    modifier onlyTribeRole(bytes32 role) {
        require(_core.hasRole(role, msg.sender), "UNAUTHORIZED");
        _;
    }

    // Modifiers to allow any combination of roles
    modifier hasAnyOfTwoRoles(bytes32 role1, bytes32 role2) {
        require(
            _core.hasRole(role1, msg.sender) ||
                _core.hasRole(role2, msg.sender),
            "UNAUTHORIZED"
        );
        _;
    }

    modifier hasAnyOfThreeRoles(
        bytes32 role1,
        bytes32 role2,
        bytes32 role3
    ) {
        require(
            _core.hasRole(role1, msg.sender) ||
                _core.hasRole(role2, msg.sender) ||
                _core.hasRole(role3, msg.sender),
            "UNAUTHORIZED"
        );
        _;
    }

    modifier hasAnyOfFourRoles(
        bytes32 role1,
        bytes32 role2,
        bytes32 role3,
        bytes32 role4
    ) {
        require(
            _core.hasRole(role1, msg.sender) ||
                _core.hasRole(role2, msg.sender) ||
                _core.hasRole(role3, msg.sender) ||
                _core.hasRole(role4, msg.sender),
            "UNAUTHORIZED"
        );
        _;
    }

    modifier hasAnyOfFiveRoles(
        bytes32 role1,
        bytes32 role2,
        bytes32 role3,
        bytes32 role4,
        bytes32 role5
    ) {
        require(
            _core.hasRole(role1, msg.sender) ||
                _core.hasRole(role2, msg.sender) ||
                _core.hasRole(role3, msg.sender) ||
                _core.hasRole(role4, msg.sender) ||
                _core.hasRole(role5, msg.sender),
            "UNAUTHORIZED"
        );
        _;
    }

    modifier onlyVolt() {
        require(msg.sender == address(_volt), "CoreRef: Caller is not VOLT");
        _;
    }

    /// @notice sets a new admin role for this contract
    function setContractAdminRole(bytes32 newContractAdminRole)
        external
        override
        onlyGovernor
    {
        _setContractAdminRole(newContractAdminRole);
    }

    /// @notice returns whether a given address has the admin role for this contract
    function isContractAdmin(address _admin)
        public
        view
        override
        returns (bool)
    {
        return _core.hasRole(CONTRACT_ADMIN_ROLE, _admin);
    }

    /// @notice set pausable methods to paused
    function pause() public override onlyGuardianOrGovernor {
        _pause();
    }

    /// @notice set pausable methods to unpaused
    function unpause() public override onlyGuardianOrGovernor {
        _unpause();
    }

    /// @notice address of the Core contract referenced
    /// @return ICore implementation address
    function core() public view override returns (ICore) {
        return _core;
    }

    /// @notice address of the Fei contract referenced by Core
    /// @return IFei implementation address
    function volt() public view override returns (IVolt) {
        return _volt;
    }

    /// @notice address of the Tribe contract referenced by Core
    /// @return IERC20 implementation address
    function vcon() public view override returns (IERC20) {
        return _vcon;
    }

    /// @notice volt balance of contract
    /// @return volt amount held
    function voltBalance() public view override returns (uint256) {
        return _volt.balanceOf(address(this));
    }

    /// @notice vcon balance of contract
    /// @return vcon amount held
    function vconBalance() public view override returns (uint256) {
        return _vcon.balanceOf(address(this));
    }

    function _burnVoltHeld() internal {
        _volt.burn(voltBalance());
    }

    function _mintVolt(address to, uint256 amount) internal virtual {
        if (amount != 0) {
            _volt.mint(to, amount);
        }
    }

    function _setContractAdminRole(bytes32 newContractAdminRole) internal {
        bytes32 oldContractAdminRole = CONTRACT_ADMIN_ROLE;
        CONTRACT_ADMIN_ROLE = newContractAdminRole;
        emit ContractAdminRoleUpdate(
            oldContractAdminRole,
            newContractAdminRole
        );
    }
}

File 6 of 21 : IPCVGuardian.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

/// @title IPCVGuardian
/// @notice an interface for defining how the PCVGuardian functions
/// @dev any implementation of this contract should be granted the roles of Guardian and PCVController in order to work correctly
interface IPCVGuardian {
    // ---------- Events ----------

    event WhitelistAddressAdded(address indexed pcvDeposit);

    event WhitelistAddressRemoved(address indexed pcvDeposit);

    event PCVGuardianWithdrawal(address indexed pcvDeposit, uint256 amount);

    event PCVGuardianERC20Withdrawal(
        address indexed pcvDeposit,
        address indexed token,
        uint256 amount
    );

    // ---------- Read-Only API ----------

    /// @notice returns true if the pcvDeposit address is whitelisted
    /// @param pcvDeposit the address to check
    function isWhitelistAddress(address pcvDeposit)
        external
        view
        returns (bool);

    /// @notice returns all whitelisted addresses
    function getWhitelistAddresses() external view returns (address[] memory);

    // ---------- Governor-Only State-Changing API ----------

    /// @notice governor-only method to whitelist a pcvDeposit address to withdraw funds from
    /// @param pcvDeposit the address to whitelist
    function addWhitelistAddress(address pcvDeposit) external;

    /// @notice batch version of addWhitelistAddress
    /// @param whitelistAddresses the pcvDespoit addresses to whitelist, as calldata
    function addWhitelistAddresses(address[] calldata whitelistAddresses)
        external;

    // ---------- Governor-or-Guardian-Only State-Changing API ----------

    /// @notice governor-or-guardian-only method to remove pcvDeposit address from the whitelist to withdraw funds from
    /// @param pcvDeposit the address to un-whitelist
    function removeWhitelistAddress(address pcvDeposit) external;

    /// @notice batch version of removeWhitelistAddress
    /// @param whitelistAddresses the addresses to un-whitelist
    function removeWhitelistAddresses(address[] calldata whitelistAddresses)
        external;

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw funds from a pcv deposit, by calling the withdraw() method on it
    /// @param pcvDeposit the address of the pcv deposit contract
    /// @param amount the amount to withdraw
    function withdrawToSafeAddress(address pcvDeposit, uint256 amount) external;

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw all at once funds from a pcv deposit, by calling the withdraw() method on it
    /// @param pcvDeposit the address of the pcv deposit contract
    function withdrawAllToSafeAddress(address pcvDeposit) external;

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw an ERC20 from a pcv deposit, by calling the withdrawERC20() method on it
    /// @param pcvDeposit the deposit to pull funds from
    /// @param token the address of the token to withdraw
    /// @param amount the amount of funds to withdraw
    function withdrawERC20ToSafeAddress(
        address pcvDeposit,
        address token,
        uint256 amount
    ) external;

    /// @notice governor-or-guardian-or-pcv-guard method to withdraw all of an ERC20 balance from a pcv deposit, by calling the withdrawERC20() method on it
    /// @param pcvDeposit the deposit to pull funds from
    /// @param token the address of the token to withdraw
    function withdrawAllERC20ToSafeAddress(address pcvDeposit, address token)
        external;
}

File 7 of 21 : IPCVDeposit.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import "./IPCVDepositBalances.sol";

/// @title a PCV Deposit interface
/// @author Fei Protocol
interface IPCVDeposit is IPCVDepositBalances {
    // ----------- Events -----------
    event Deposit(address indexed _from, uint256 _amount);

    event Withdrawal(
        address indexed _caller,
        address indexed _to,
        uint256 _amount
    );

    event WithdrawERC20(
        address indexed _caller,
        address indexed _token,
        address indexed _to,
        uint256 _amount
    );

    event WithdrawETH(
        address indexed _caller,
        address indexed _to,
        uint256 _amount
    );

    // ----------- State changing api -----------

    function deposit() external;

    // ----------- PCV Controller only state changing api -----------

    function withdraw(address to, uint256 amount) external;

    function withdrawERC20(
        address token,
        address to,
        uint256 amount
    ) external;

    function withdrawETH(address payable to, uint256 amount) external;
}

File 8 of 21 : CoreRefPausableLib.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import {CoreRef} from "../refs/CoreRef.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";

/// @title PausableLib
/// @notice PausableLib is a library that can be used to pause and unpause contracts, among other utilities.
/// @dev This library should only be used on contracts that implement CoreRef.
library CoreRefPausableLib {
    function _pause(address _pauseableCoreRefAddress) internal {
        CoreRef(_pauseableCoreRefAddress).pause();
    }

    function _unpause(address _pauseableCoreRefAddress) internal {
        CoreRef(_pauseableCoreRefAddress).unpause();
    }

    function _paused(address _pauseableCoreRefAddres)
        internal
        view
        returns (bool)
    {
        return CoreRef(_pauseableCoreRefAddres).paused();
    }
}

File 9 of 21 : TribeRoles.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

/**
 @title Tribe DAO ACL Roles
 @notice Holds a complete list of all roles which can be held by contracts inside Tribe DAO.
         Roles are broken up into 3 categories:
         * Major Roles - the most powerful roles in the Tribe DAO which should be carefully managed.
         * Admin Roles - roles with management capability over critical functionality. Should only be held by automated or optimistic mechanisms
         * Minor Roles - operational roles. May be held or managed by shorter optimistic timelocks or trusted multisigs.
 */
library TribeRoles {
    /*///////////////////////////////////////////////////////////////
                                 Major Roles
    //////////////////////////////////////////////////////////////*/

    /// @notice the ultimate role of Tribe. Controls all other roles and protocol functionality.
    bytes32 internal constant GOVERNOR = keccak256("GOVERN_ROLE");

    /// @notice the protector role of Tribe. Admin of pause, veto, revoke, and minor roles
    bytes32 internal constant GUARDIAN = keccak256("GUARDIAN_ROLE");

    /// @notice the role which can arbitrarily move PCV in any size from any contract
    bytes32 internal constant PCV_CONTROLLER = keccak256("PCV_CONTROLLER_ROLE");

    /// @notice can mint FEI arbitrarily
    bytes32 internal constant MINTER = keccak256("MINTER_ROLE");

    ///@notice is able to withdraw whitelisted PCV deposits to a safe address
    bytes32 internal constant PCV_GUARD = keccak256("PCV_GUARD_ROLE");

    /*///////////////////////////////////////////////////////////////
                                 Admin Roles
    //////////////////////////////////////////////////////////////*/

    /// @notice can manage the majority of Tribe protocol parameters. Sets boundaries for MINOR_PARAM_ROLE.
    bytes32 internal constant PARAMETER_ADMIN = keccak256("PARAMETER_ADMIN");

    /// @notice manages the Collateralization Oracle as well as other protocol oracles.
    bytes32 internal constant ORACLE_ADMIN = keccak256("ORACLE_ADMIN_ROLE");

    /// @notice manages TribalChief incentives and related functionality.
    bytes32 internal constant TRIBAL_CHIEF_ADMIN =
        keccak256("TRIBAL_CHIEF_ADMIN_ROLE");

    /// @notice admin of PCVGuardian
    bytes32 internal constant PCV_GUARDIAN_ADMIN =
        keccak256("PCV_GUARDIAN_ADMIN_ROLE");

    /// @notice admin of all Minor Roles
    bytes32 internal constant MINOR_ROLE_ADMIN = keccak256("MINOR_ROLE_ADMIN");

    /// @notice admin of the Fuse protocol
    bytes32 internal constant FUSE_ADMIN = keccak256("FUSE_ADMIN");

    /// @notice capable of vetoing DAO votes or optimistic timelocks
    bytes32 internal constant VETO_ADMIN = keccak256("VETO_ADMIN");

    /// @notice capable of setting FEI Minters within global rate limits and caps
    bytes32 internal constant MINTER_ADMIN = keccak256("MINTER_ADMIN");

    /// @notice manages the constituents of Optimistic Timelocks, including Proposers and Executors
    bytes32 internal constant OPTIMISTIC_ADMIN = keccak256("OPTIMISTIC_ADMIN");

    /// @notice manages the granting and revocation of PCV Guard roles
    bytes32 internal constant PCV_GUARD_ADMIN =
        keccak256("PCV_GUARD_ADMIN_ROLE");

    /*///////////////////////////////////////////////////////////////
                                 Minor Roles
    //////////////////////////////////////////////////////////////*/

    /// @notice capable of poking existing LBP auctions to exchange tokens.
    bytes32 internal constant LBP_SWAP_ROLE = keccak256("SWAP_ADMIN_ROLE");

    /// @notice capable of engaging with Votium for voting incentives.
    bytes32 internal constant VOTIUM_ROLE = keccak256("VOTIUM_ADMIN_ROLE");

    /// @notice capable of changing parameters within non-critical ranges
    bytes32 internal constant MINOR_PARAM_ROLE = keccak256("MINOR_PARAM_ROLE");

    /// @notice capable of adding an address to multi rate limited
    bytes32 internal constant ADD_MINTER_ROLE = keccak256("ADD_MINTER_ROLE");

    /// @notice capable of changing PCV Deposit and Global Rate Limited Minter in the PSM
    bytes32 internal constant PSM_ADMIN_ROLE = keccak256("PSM_ADMIN_ROLE");
}

File 10 of 21 : ICoreRef.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import "../core/ICore.sol";

/// @title CoreRef interface
/// @author Fei Protocol
interface ICoreRef {
    // ----------- Events -----------

    event CoreUpdate(address indexed oldCore, address indexed newCore);

    event ContractAdminRoleUpdate(
        bytes32 indexed oldContractAdminRole,
        bytes32 indexed newContractAdminRole
    );

    // ----------- Governor only state changing api -----------

    function setContractAdminRole(bytes32 newContractAdminRole) external;

    // ----------- Governor or Guardian only state changing api -----------

    function pause() external;

    function unpause() external;

    // ----------- Getters -----------

    function core() external view returns (ICore);

    function volt() external view returns (IVolt);

    function vcon() external view returns (IERC20);

    function voltBalance() external view returns (uint256);

    function vconBalance() external view returns (uint256);

    function CONTRACT_ADMIN_ROLE() external view returns (bytes32);

    function isContractAdmin(address admin) external view returns (bool);
}

File 11 of 21 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

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

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

    bool private _paused;

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

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

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

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

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

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

File 12 of 21 : ICore.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import {IPermissions} from "./IPermissions.sol";
import {IVolt, IERC20} from "../volt/IVolt.sol";

/// @title Core Interface
/// @author Fei Protocol
interface ICore is IPermissions {
    // ----------- Events -----------
    event VoltUpdate(IERC20 indexed _volt);
    event VconUpdate(IERC20 indexed _vcon);

    // ----------- Getters -----------

    function volt() external view returns (IVolt);

    function vcon() external view returns (IERC20);
}

File 13 of 21 : IPermissions.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./IPermissionsRead.sol";

/// @title Permissions interface
/// @author Fei Protocol
interface IPermissions is IAccessControl, IPermissionsRead {
    // ----------- Governor only state changing api -----------

    function createRole(bytes32 role, bytes32 adminRole) external;

    function grantMinter(address minter) external;

    function grantBurner(address burner) external;

    function grantPCVController(address pcvController) external;

    function grantGovernor(address governor) external;

    function grantGuardian(address guardian) external;

    function revokeMinter(address minter) external;

    function revokeBurner(address burner) external;

    function revokePCVController(address pcvController) external;

    function revokeGovernor(address governor) external;

    function revokeGuardian(address guardian) external;

    // ----------- Revoker only state changing api -----------

    function revokeOverride(bytes32 role, address account) external;

    // ----------- Getters -----------

    function GUARDIAN_ROLE() external view returns (bytes32);

    function GOVERN_ROLE() external view returns (bytes32);

    function BURNER_ROLE() external view returns (bytes32);

    function MINTER_ROLE() external view returns (bytes32);

    function PCV_CONTROLLER_ROLE() external view returns (bytes32);
}

File 14 of 21 : IVolt.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// @title FEI stablecoin interface
/// @author Fei Protocol
interface IVolt is IERC20 {
    // ----------- Events -----------

    event Minting(
        address indexed _to,
        address indexed _minter,
        uint256 _amount
    );

    event Burning(
        address indexed _to,
        address indexed _burner,
        uint256 _amount
    );

    event IncentiveContractUpdate(
        address indexed _incentivized,
        address indexed _incentiveContract
    );

    // ----------- State changing api -----------

    function burn(uint256 amount) external;

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

    // ----------- Minter only state changing api -----------

    function mint(address account, uint256 amount) external;
}

File 15 of 21 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

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

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

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

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

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

        _revokeRole(role, account);
    }

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

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

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 16 of 21 : IPermissionsRead.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

/// @title Permissions Read interface
/// @author Fei Protocol
interface IPermissionsRead {
    // ----------- Getters -----------

    function isBurner(address _address) external view returns (bool);

    function isMinter(address _address) external view returns (bool);

    function isGovernor(address _address) external view returns (bool);

    function isGuardian(address _address) external view returns (bool);

    function isPCVController(address _address) external view returns (bool);
}

File 17 of 21 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

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

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

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

File 18 of 21 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 19 of 21 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 20 of 21 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 21 of 21 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 22 of 21 : IPCVDepositBalances.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.4;

/// @title a PCV Deposit interface for only balance getters
/// @author Fei Protocol
interface IPCVDepositBalances {
    // ----------- Getters -----------

    /// @notice gets the effective balance of "balanceReportedIn" token if the deposit were fully withdrawn
    function balance() external view returns (uint256);

    /// @notice gets the token address in which this deposit returns its balance
    function balanceReportedIn() external view returns (address);

    /// @notice gets the resistant token balance and protocol owned fei of this deposit
    function resistantBalanceAndVolt() external view returns (uint256, uint256);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"address","name":"_safeAddress","type":"address"},{"internalType":"address[]","name":"_whitelistAddresses","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"oldContractAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newContractAdminRole","type":"bytes32"}],"name":"ContractAdminRoleUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldCore","type":"address"},{"indexed":true,"internalType":"address","name":"newCore","type":"address"}],"name":"CoreUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pcvDeposit","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PCVGuardianERC20Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pcvDeposit","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PCVGuardianWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"WhitelistAddressAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"WhitelistAddressRemoved","type":"event"},{"inputs":[],"name":"CONTRACT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"addWhitelistAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_whitelistAddresses","type":"address[]"}],"name":"addWhitelistAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"contract ICore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"isContractAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"isWhitelistAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"removeWhitelistAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_whitelistAddresses","type":"address[]"}],"name":"removeWhitelistAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newContractAdminRole","type":"bytes32"}],"name":"setContractAdminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vcon","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vconBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"volt","outputs":[{"internalType":"contract IVolt","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voltBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"withdrawAllERC20ToSafeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"}],"name":"withdrawAllToSafeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20ToSafeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvDeposit","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToSafeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040523480156200001257600080fd5b50604051620027b4380380620027b48339810160408190526200003591620003ba565b6000805460ff191690556001600160a01b0383166080819052604080516317607ad960e01b815290518592916317607ad99160048083019260209291908290030181865afa1580156200008c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b29190620004ba565b6001600160a01b031660a0816001600160a01b031681525050806001600160a01b031663315d2f5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200010a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001309190620004ba565b6001600160a01b031660c0816001600160a01b031681525050620001b8816001600160a01b03166338b7f4466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200018c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b29190620004e1565b62000213565b506001600160a01b03821660e05260005b8151811015620002095762000200828281518110620001ec57620001ec620004fb565b60200260200101516200024c60201b60201c565b600101620001c9565b5050505062000511565b6001805490829055604051829082907f29ddd278ef9169e35aa84e424b39048b89af9c0b50f85497e40f97dff6946cf590600090a35050565b620002678160026200030760201b620016051790919060201c565b620002d05760405162461bcd60e51b815260206004820152602f60248201527f504356477561726469616e3a204661696c656420746f2061646420616464726560448201526e1cdcc81d1bc81dda1a5d195b1a5cdd608a1b606482015260840160405180910390fd5b6040516001600160a01b038216907f7e82e36808082f76da270c3c5e72976b35dd02ffdd5e28dc06990b08c959f7c090600090a250565b60006200031e836001600160a01b03841662000327565b90505b92915050565b6000818152600183016020526040812054620003705750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000321565b50600062000321565b6001600160a01b03811681146200038f57600080fd5b50565b80516200039f8162000379565b919050565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620003d057600080fd5b8351620003dd8162000379565b80935050602080850151620003f28162000379565b60408601519093506001600160401b03808211156200041057600080fd5b818701915087601f8301126200042557600080fd5b8151818111156200043a576200043a620003a4565b8060051b604051601f19603f83011681018181108582111715620004625762000462620003a4565b60405291825284820192508381018501918a8311156200048157600080fd5b938501935b82851015620004aa576200049a8562000392565b8452938501939285019262000486565b8096505050505050509250925092565b600060208284031215620004cd57600080fd5b8151620004da8162000379565b9392505050565b600060208284031215620004f457600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161219e62000616600039600081816101ed01528181611786015281816119a90152611a420152600081816101b4015261043b01526000818161015e01526115290152600081816102f001528181610344015281816104c90152818161055701528181610650015281816106dd0152818161077201528181610850015281816108de0152818161098a01528181610a3a01528181610ac801528181610b7501528181610c0301528181610d2801528181610db501528181610e4a01528181610fc501528181611052015281816110e7015281816111c3015281816112c20152818161134f015281816113e4015261157d015261219e6000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806394a7ef15116100b8578063d34884421161007c578063d3488442146102b5578063d7aed245146102c8578063ec16866e146102db578063f2f4eb26146102ee578063fa9ee68b14610314578063fc81a12a1461031c57600080fd5b806394a7ef1514610256578063b7ecbaae14610269578063b83921a61461027c578063bf0417721461028f578063c1a96789146102a257600080fd5b80633f4ba83a1161010a5780633f4ba83a146101e05780635578110c146101e8578063578cbd1f1461020f5780635c975abb146102245780637f1697081461023b5780638456cb591461024e57600080fd5b80630e256a5e1461014757806317607ad91461015c5780631da033121461019b578063315d2f5b146101b25780633872cdb1146101d8575b600080fd5b61015a610155366004611dcd565b61032f565b005b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b6101a460015481565b604051908152602001610192565b7f000000000000000000000000000000000000000000000000000000000000000061017e565b6101a4610423565b61015a6104b4565b61017e7f000000000000000000000000000000000000000000000000000000000000000081565b6102176105f0565b6040516101929190611e42565b60005460ff165b6040519015158152602001610192565b61015a610249366004611eab565b6105fc565b61015a61083b565b61015a610264366004611ee7565b610975565b61015a610277366004611ee7565b610a25565b61015a61028a366004611dcd565b610b60565b61015a61029d366004611ee7565b610cd4565b61015a6102b0366004611f02565b610f71565b61015a6102c3366004611f2c565b6111ae565b61022b6102d6366004611ee7565b61125b565b61015a6102e9366004611f45565b61126e565b7f000000000000000000000000000000000000000000000000000000000000000061017e565b6101a4611511565b61022b61032a366004611ee7565b611560565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa158015610393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b79190611f78565b6103dc5760405162461bcd60e51b81526004016103d390611f9a565b60405180910390fd5b60005b8181101561041e576104168383838181106103fc576103fc611fdb565b90506020020160208101906104119190611ee7565b611621565b6001016103df565b505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024015b602060405180830381865afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af9190611ff1565b905090565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190611f78565b806105ca5750604051630c68ba2160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630c68ba2190602401602060405180830381865afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190611f78565b6105e65760405162461bcd60e51b81526004016103d39061200a565b6105ee6116c7565b565b60606104af600261175a565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d1485490604401602060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190611f78565b806107505750604051632474521560e21b8152600481018390523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa15801561072c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107509190611f78565b806107e55750604051632474521560e21b8152600481018290523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa1580156107c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e59190611f78565b6108015760405162461bcd60e51b81526004016103d390612057565b8561080b8161125b565b6108275760405162461bcd60e51b81526004016103d39061207d565b610832878787611767565b50505050505050565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa15801561089f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c39190611f78565b806109515750604051630c68ba2160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630c68ba2190602401602060405180830381865afa15801561092d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109519190611f78565b61096d5760405162461bcd60e51b81526004016103d39061200a565b6105ee611843565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa1580156109d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fd9190611f78565b610a195760405162461bcd60e51b81526004016103d390611f9a565b610a2281611621565b50565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa158015610a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aad9190611f78565b80610b3b5750604051630c68ba2160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630c68ba2190602401602060405180830381865afa158015610b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3b9190611f78565b610b575760405162461bcd60e51b81526004016103d39061200a565b610a22816118be565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be89190611f78565b80610c765750604051630c68ba2160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630c68ba2190602401602060405180830381865afa158015610c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c769190611f78565b610c925760405162461bcd60e51b81526004016103d39061200a565b60005b8181101561041e57610ccc838383818110610cb257610cb2611fdb565b9050602002016020810190610cc79190611ee7565b6118be565b600101610c95565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d1485490604401602060405180830381865afa158015610d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d939190611f78565b80610e285750604051632474521560e21b8152600481018390523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa158015610e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e289190611f78565b80610ebd5750604051632474521560e21b8152600481018290523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa158015610e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebd9190611f78565b610ed95760405162461bcd60e51b81526004016103d390612057565b83610ee38161125b565b610eff5760405162461bcd60e51b81526004016103d39061207d565b610f6a85866001600160a01b031663b69ef8a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f659190611ff1565b611969565b5050505050565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d1485490604401602060405180830381865afa15801561100c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110309190611f78565b806110c55750604051632474521560e21b8152600481018390523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c59190611f78565b8061115a5750604051632474521560e21b8152600481018290523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa158015611136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115a9190611f78565b6111765760405162461bcd60e51b81526004016103d390612057565b846111808161125b565b61119c5760405162461bcd60e51b81526004016103d39061207d565b6111a68686611969565b505050505050565b604051631c86b03760e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e43581b890602401602060405180830381865afa158015611212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112369190611f78565b6112525760405162461bcd60e51b81526004016103d390611f9a565b610a2281611af5565b6000611268600283611b2e565b92915050565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d1485490604401602060405180830381865afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d9190611f78565b806113c25750604051632474521560e21b8152600481018390523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa15801561139e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c29190611f78565b806114575750604051632474521560e21b8152600481018290523360248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906391d1485490604401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190611f78565b6114735760405162461bcd60e51b81526004016103d390612057565b8461147d8161125b565b6114995760405162461bcd60e51b81526004016103d39061207d565b6040516370a0823160e01b81526001600160a01b0380881660048301526111a69188918891908216906370a0823190602401602060405180830381865afa1580156114e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150c9190611ff1565b611767565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240161046e565b600154604051632474521560e21b81526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916391d14854916115c49186906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa1580156115e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112689190611f78565b600061161a836001600160a01b038416611b50565b9392505050565b61162c600282611605565b6116905760405162461bcd60e51b815260206004820152602f60248201527f504356477561726469616e3a204661696c656420746f2061646420616464726560448201526e1cdcc81d1bc81dda1a5d195b1a5cdd608a1b60648201526084016103d3565b6040516001600160a01b038216907f7e82e36808082f76da270c3c5e72976b35dd02ffdd5e28dc06990b08c959f7c090600090a250565b60005460ff166117105760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016103d3565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6060600061161a83611b9f565b6040516344004cc160e01b81526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018390528416906344004cc190606401600060405180830381600087803b1580156117d957600080fd5b505af11580156117ed573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b03167fb49ac05ea1ed28a84001a618e01b7e80029818aedd09fcdc902dc54399f1bfea8360405161183691815260200190565b60405180910390a3505050565b60005460ff16156118895760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016103d3565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861173d3390565b6118c9600282611bfb565b6119325760405162461bcd60e51b815260206004820152603460248201527f504356477561726469616e3a204661696c656420746f2072656d6f7665206164604482015273191c995cdcc8199c9bdb481dda1a5d195b1a5cdd60621b60648201526084016103d3565b6040516001600160a01b038216907f45dcd9ab8c61f0629f2904906111e617d542ed4af59ecb4af2586823382a408c90600090a250565b61197b826001600160a01b0316611c10565b15611a2b57611992826001600160a01b0316611c50565b60405163f3fef3a360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820183905283169063f3fef3a390604401600060405180830381600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b50505050611a26826001600160a01b0316611c9f565b611aae565b60405163f3fef3a360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820183905283169063f3fef3a390604401600060405180830381600087803b158015611a9557600080fd5b505af1158015611aa9573d6000803e3d6000fd5b505050505b816001600160a01b03167f1e828f834bd61581f4e8a1d7d05db6fdc58bbf2ed479ddbdac31d53720379f1a82604051611ae991815260200190565b60405180910390a25050565b6001805490829055604051829082907f29ddd278ef9169e35aa84e424b39048b89af9c0b50f85497e40f97dff6946cf590600090a35050565b6001600160a01b0381166000908152600183016020526040812054151561161a565b6000818152600183016020526040812054611b9757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611268565b506000611268565b606081600001805480602002602001604051908101604052809291908181526020018280548015611bef57602002820191906000526020600020905b815481526020019060010190808311611bdb575b50505050509050919050565b600061161a836001600160a01b038416611cda565b6000816001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115e1573d6000803e3d6000fd5b806001600160a01b0316633f4ba83a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c8b57600080fd5b505af1158015610f6a573d6000803e3d6000fd5b806001600160a01b0316638456cb596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c8b57600080fd5b60008181526001830160205260408120548015611dc3576000611cfe6001836120cd565b8554909150600090611d12906001906120cd565b9050818114611d77576000866000018281548110611d3257611d32611fdb565b9060005260206000200154905080876000018481548110611d5557611d55611fdb565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d8857611d886120f2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611268565b6000915050611268565b60008060208385031215611de057600080fd5b823567ffffffffffffffff80821115611df857600080fd5b818501915085601f830112611e0c57600080fd5b813581811115611e1b57600080fd5b8660208260051b8501011115611e3057600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015611e835783516001600160a01b031683529284019291840191600101611e5e565b50909695505050505050565b80356001600160a01b0381168114611ea657600080fd5b919050565b600080600060608486031215611ec057600080fd5b611ec984611e8f565b9250611ed760208501611e8f565b9150604084013590509250925092565b600060208284031215611ef957600080fd5b61161a82611e8f565b60008060408385031215611f1557600080fd5b611f1e83611e8f565b946020939093013593505050565b600060208284031215611f3e57600080fd5b5035919050565b60008060408385031215611f5857600080fd5b611f6183611e8f565b9150611f6f60208401611e8f565b90509250929050565b600060208284031215611f8a57600080fd5b8151801515811461161a57600080fd5b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561200357600080fd5b5051919050565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60208082526030908201527f504356477561726469616e3a2050726f7669646564206164647265737320697360408201526f081b9bdd081dda1a5d195b1a5cdd195960821b606082015260800190565b6000828210156120ed57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052603160045260246000fdfe899bd46557473cb80307a9dabc297131ced39608330a2d29b2d52b660c03923eedc791ca53f3965e2de7052b8838f0cf7b879a3ba96f4833316638505bef55e355435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041a2646970667358221220b8d80f6e02149dbc2c4fe2620895cecf23c05c048050662619441e1d93e9345664736f6c634300080a0033000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e8196000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000003000000000000000000000000febdf448c8484834bb399d930d7e1bdc773e23ba0000000000000000000000004188fbd7adc72853e3275f1c3503e170994888d7000000000000000000000000985f9c331a9e4447c782b98d6693f5c7df8e560e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101425760003560e01c806394a7ef15116100b8578063d34884421161007c578063d3488442146102b5578063d7aed245146102c8578063ec16866e146102db578063f2f4eb26146102ee578063fa9ee68b14610314578063fc81a12a1461031c57600080fd5b806394a7ef1514610256578063b7ecbaae14610269578063b83921a61461027c578063bf0417721461028f578063c1a96789146102a257600080fd5b80633f4ba83a1161010a5780633f4ba83a146101e05780635578110c146101e8578063578cbd1f1461020f5780635c975abb146102245780637f1697081461023b5780638456cb591461024e57600080fd5b80630e256a5e1461014757806317607ad91461015c5780631da033121461019b578063315d2f5b146101b25780633872cdb1146101d8575b600080fd5b61015a610155366004611dcd565b61032f565b005b7f000000000000000000000000559ebc30b0e58a45cc9ff573f77ef1e5eb1b3e185b6040516001600160a01b0390911681526020015b60405180910390f35b6101a460015481565b604051908152602001610192565b7f000000000000000000000000000000000000000000000000000000000000000061017e565b6101a4610423565b61015a6104b4565b61017e7f000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf81565b6102176105f0565b6040516101929190611e42565b60005460ff165b6040519015158152602001610192565b61015a610249366004611eab565b6105fc565b61015a61083b565b61015a610264366004611ee7565b610975565b61015a610277366004611ee7565b610a25565b61015a61028a366004611dcd565b610b60565b61015a61029d366004611ee7565b610cd4565b61015a6102b0366004611f02565b610f71565b61015a6102c3366004611f2c565b6111ae565b61022b6102d6366004611ee7565b61125b565b61015a6102e9366004611f45565b61126e565b7f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819661017e565b6101a4611511565b61022b61032a366004611ee7565b611560565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa158015610393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b79190611f78565b6103dc5760405162461bcd60e51b81526004016103d390611f9a565b60405180910390fd5b60005b8181101561041e576104168383838181106103fc576103fc611fdb565b90506020020160208101906104119190611ee7565b611621565b6001016103df565b505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a08231906024015b602060405180830381865afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af9190611ff1565b905090565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190611f78565b806105ca5750604051630c68ba2160e01b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b031690630c68ba2190602401602060405180830381865afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190611f78565b6105e65760405162461bcd60e51b81526004016103d39061200a565b6105ee6116c7565b565b60606104af600261175a565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819616906391d1485490604401602060405180830381865afa158015610697573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bb9190611f78565b806107505750604051632474521560e21b8152600481018390523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa15801561072c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107509190611f78565b806107e55750604051632474521560e21b8152600481018290523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa1580156107c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e59190611f78565b6108015760405162461bcd60e51b81526004016103d390612057565b8561080b8161125b565b6108275760405162461bcd60e51b81526004016103d39061207d565b610832878787611767565b50505050505050565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa15801561089f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c39190611f78565b806109515750604051630c68ba2160e01b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b031690630c68ba2190602401602060405180830381865afa15801561092d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109519190611f78565b61096d5760405162461bcd60e51b81526004016103d39061200a565b6105ee611843565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa1580156109d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fd9190611f78565b610a195760405162461bcd60e51b81526004016103d390611f9a565b610a2281611621565b50565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa158015610a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aad9190611f78565b80610b3b5750604051630c68ba2160e01b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b031690630c68ba2190602401602060405180830381865afa158015610b17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3b9190611f78565b610b575760405162461bcd60e51b81526004016103d39061200a565b610a22816118be565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be89190611f78565b80610c765750604051630c68ba2160e01b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b031690630c68ba2190602401602060405180830381865afa158015610c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c769190611f78565b610c925760405162461bcd60e51b81526004016103d39061200a565b60005b8181101561041e57610ccc838383818110610cb257610cb2611fdb565b9050602002016020810190610cc79190611ee7565b6118be565b600101610c95565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819616906391d1485490604401602060405180830381865afa158015610d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d939190611f78565b80610e285750604051632474521560e21b8152600481018390523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa158015610e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e289190611f78565b80610ebd5750604051632474521560e21b8152600481018290523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa158015610e99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebd9190611f78565b610ed95760405162461bcd60e51b81526004016103d390612057565b83610ee38161125b565b610eff5760405162461bcd60e51b81526004016103d39061207d565b610f6a85866001600160a01b031663b69ef8a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f659190611ff1565b611969565b5050505050565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819616906391d1485490604401602060405180830381865afa15801561100c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110309190611f78565b806110c55750604051632474521560e21b8152600481018390523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c59190611f78565b8061115a5750604051632474521560e21b8152600481018290523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa158015611136573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115a9190611f78565b6111765760405162461bcd60e51b81526004016103d390612057565b846111808161125b565b61119c5760405162461bcd60e51b81526004016103d39061207d565b6111a68686611969565b505050505050565b604051631c86b03760e31b81523360048201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b03169063e43581b890602401602060405180830381865afa158015611212573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112369190611f78565b6112525760405162461bcd60e51b81526004016103d390611f9a565b610a2281611af5565b6000611268600283611b2e565b92915050565b604051632474521560e21b8152600080516020612109833981519152600482018190523360248301529060008051602061214983398151915290600080516020612129833981519152906001600160a01b037f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819616906391d1485490604401602060405180830381865afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d9190611f78565b806113c25750604051632474521560e21b8152600481018390523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa15801561139e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c29190611f78565b806114575750604051632474521560e21b8152600481018290523360248201527f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e81966001600160a01b0316906391d1485490604401602060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114579190611f78565b6114735760405162461bcd60e51b81526004016103d390612057565b8461147d8161125b565b6114995760405162461bcd60e51b81526004016103d39061207d565b6040516370a0823160e01b81526001600160a01b0380881660048301526111a69188918891908216906370a0823190602401602060405180830381865afa1580156114e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150c9190611ff1565b611767565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000559ebc30b0e58a45cc9ff573f77ef1e5eb1b3e186001600160a01b0316906370a082319060240161046e565b600154604051632474521560e21b81526000916001600160a01b037f000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e819616916391d14854916115c49186906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa1580156115e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112689190611f78565b600061161a836001600160a01b038416611b50565b9392505050565b61162c600282611605565b6116905760405162461bcd60e51b815260206004820152602f60248201527f504356477561726469616e3a204661696c656420746f2061646420616464726560448201526e1cdcc81d1bc81dda1a5d195b1a5cdd608a1b60648201526084016103d3565b6040516001600160a01b038216907f7e82e36808082f76da270c3c5e72976b35dd02ffdd5e28dc06990b08c959f7c090600090a250565b60005460ff166117105760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016103d3565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6060600061161a83611b9f565b6040516344004cc160e01b81526001600160a01b0383811660048301527f000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf81166024830152604482018390528416906344004cc190606401600060405180830381600087803b1580156117d957600080fd5b505af11580156117ed573d6000803e3d6000fd5b50505050816001600160a01b0316836001600160a01b03167fb49ac05ea1ed28a84001a618e01b7e80029818aedd09fcdc902dc54399f1bfea8360405161183691815260200190565b60405180910390a3505050565b60005460ff16156118895760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016103d3565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861173d3390565b6118c9600282611bfb565b6119325760405162461bcd60e51b815260206004820152603460248201527f504356477561726469616e3a204661696c656420746f2072656d6f7665206164604482015273191c995cdcc8199c9bdb481dda1a5d195b1a5cdd60621b60648201526084016103d3565b6040516001600160a01b038216907f45dcd9ab8c61f0629f2904906111e617d542ed4af59ecb4af2586823382a408c90600090a250565b61197b826001600160a01b0316611c10565b15611a2b57611992826001600160a01b0316611c50565b60405163f3fef3a360e01b81526001600160a01b037f000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf811660048301526024820183905283169063f3fef3a390604401600060405180830381600087803b1580156119fc57600080fd5b505af1158015611a10573d6000803e3d6000fd5b50505050611a26826001600160a01b0316611c9f565b611aae565b60405163f3fef3a360e01b81526001600160a01b037f000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf811660048301526024820183905283169063f3fef3a390604401600060405180830381600087803b158015611a9557600080fd5b505af1158015611aa9573d6000803e3d6000fd5b505050505b816001600160a01b03167f1e828f834bd61581f4e8a1d7d05db6fdc58bbf2ed479ddbdac31d53720379f1a82604051611ae991815260200190565b60405180910390a25050565b6001805490829055604051829082907f29ddd278ef9169e35aa84e424b39048b89af9c0b50f85497e40f97dff6946cf590600090a35050565b6001600160a01b0381166000908152600183016020526040812054151561161a565b6000818152600183016020526040812054611b9757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611268565b506000611268565b606081600001805480602002602001604051908101604052809291908181526020018280548015611bef57602002820191906000526020600020905b815481526020019060010190808311611bdb575b50505050509050919050565b600061161a836001600160a01b038416611cda565b6000816001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115e1573d6000803e3d6000fd5b806001600160a01b0316633f4ba83a6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c8b57600080fd5b505af1158015610f6a573d6000803e3d6000fd5b806001600160a01b0316638456cb596040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c8b57600080fd5b60008181526001830160205260408120548015611dc3576000611cfe6001836120cd565b8554909150600090611d12906001906120cd565b9050818114611d77576000866000018281548110611d3257611d32611fdb565b9060005260206000200154905080876000018481548110611d5557611d55611fdb565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d8857611d886120f2565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611268565b6000915050611268565b60008060208385031215611de057600080fd5b823567ffffffffffffffff80821115611df857600080fd5b818501915085601f830112611e0c57600080fd5b813581811115611e1b57600080fd5b8660208260051b8501011115611e3057600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015611e835783516001600160a01b031683529284019291840191600101611e5e565b50909695505050505050565b80356001600160a01b0381168114611ea657600080fd5b919050565b600080600060608486031215611ec057600080fd5b611ec984611e8f565b9250611ed760208501611e8f565b9150604084013590509250925092565b600060208284031215611ef957600080fd5b61161a82611e8f565b60008060408385031215611f1557600080fd5b611f1e83611e8f565b946020939093013593505050565b600060208284031215611f3e57600080fd5b5035919050565b60008060408385031215611f5857600080fd5b611f6183611e8f565b9150611f6f60208401611e8f565b90509250929050565b600060208284031215611f8a57600080fd5b8151801515811461161a57600080fd5b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561200357600080fd5b5051919050565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60208082526030908201527f504356477561726469616e3a2050726f7669646564206164647265737320697360408201526f081b9bdd081dda1a5d195b1a5cdd195960821b606082015260800190565b6000828210156120ed57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052603160045260246000fdfe899bd46557473cb80307a9dabc297131ced39608330a2d29b2d52b660c03923eedc791ca53f3965e2de7052b8838f0cf7b879a3ba96f4833316638505bef55e355435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041a2646970667358221220b8d80f6e02149dbc2c4fe2620895cecf23c05c048050662619441e1d93e9345664736f6c634300080a0033

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

000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e8196000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000003000000000000000000000000febdf448c8484834bb399d930d7e1bdc773e23ba0000000000000000000000004188fbd7adc72853e3275f1c3503e170994888d7000000000000000000000000985f9c331a9e4447c782b98d6693f5c7df8e560e

-----Decoded View---------------
Arg [0] : _core (address): 0xEC7AD284f7Ad256b64c6E69b84Eb0F48f42e8196
Arg [1] : _safeAddress (address): 0xcBB83206698E8788F85EFbEeeCAd17e53366EBDf
Arg [2] : _whitelistAddresses (address[]): 0xFeBDf448C8484834bb399d930d7E1bdC773E23bA,0x4188fbD7aDC72853E3275F1c3503E170994888D7,0x985f9C331a9E4447C782B98D6693F5c7dF8e560e

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000ec7ad284f7ad256b64c6e69b84eb0f48f42e8196
Arg [1] : 000000000000000000000000cbb83206698e8788f85efbeeecad17e53366ebdf
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [4] : 000000000000000000000000febdf448c8484834bb399d930d7e1bdc773e23ba
Arg [5] : 0000000000000000000000004188fbd7adc72853e3275f1c3503e170994888d7
Arg [6] : 000000000000000000000000985f9c331a9e4447c782b98d6693f5c7df8e560e


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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