ETH Price: $2,112.92 (+7.74%)

Contract Diff Checker

Contract Name:
RegisterSweepTrigger

Contract Source Code:

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {ERC20} from '@openzeppelin/contracts/token/ERC20/ERC20.sol';

import {CannotSetNullAddress} from '@floor/utils/Errors.sol';
import {EpochManaged} from '@floor/utils/EpochManaged.sol';

import {IBaseStrategy} from '@floor-interfaces/strategies/BaseStrategy.sol';
import {IStrategyFactory} from '@floor-interfaces/strategies/StrategyFactory.sol';
import {IEpochEndTriggered} from '@floor-interfaces/utils/EpochEndTriggered.sol';
import {INewCollectionWars} from '@floor-interfaces/voting/NewCollectionWars.sol';
import {ISweepWars} from '@floor-interfaces/voting/SweepWars.sol';
import {ITreasury, TreasuryEnums} from '@floor-interfaces/Treasury.sol';

/**
 * If the current epoch is a Collection Addition, then the floor war is ended and the
 * winning collection is chosen. The losing collections are released to be claimed, but
 * the winning collection remains locked for an additional epoch to allow the DAO to
 * exercise the option(s).
 *
 * If the current epoch is just a gauge vote, then we look at the top voted collections
 * and calculates the distribution of yield to each of them based on the vote amounts. This
 * yield is then allocated to a Sweep structure that can be executed by the {Treasury}
 * at a later date.
 *
 * @dev Requires `TREASURY_MANAGER` role.
 * @dev Requires `COLLECTION_MANAGER` role.
 */
contract RegisterSweepTrigger is EpochManaged, IEpochEndTriggered {
    /// Holds our internal contract references
    INewCollectionWars public immutable newCollectionWars;
    ISweepWars public immutable voteContract;
    ITreasury public immutable treasury;
    IStrategyFactory public immutable strategyFactory;

    /// Stores yield generated in the epoch for temporary held calculations
    mapping(address => uint) private _yield;

    /// Temp. stores our epoch tokens that have generated yield
    address[] private _epochTokens;

    /**
     * Define our required contracts.
     */
    constructor(address _newCollectionWars, address _strategyFactory, address _treasury, address _voteContract) {
        if (_newCollectionWars == address(0) || _strategyFactory == address(0) ||
            _treasury == address(0) || _voteContract == address(0)) {
            revert CannotSetNullAddress();
        }

        newCollectionWars = INewCollectionWars(_newCollectionWars);
        strategyFactory = IStrategyFactory(_strategyFactory);
        treasury = ITreasury(_treasury);
        voteContract = ISweepWars(_voteContract);
    }

    /**
     * When our epoch ends, we need to find the tokens yielded from each strategy, as well as
     * the respective amounts.
     */
    function endEpoch(uint epoch) external onlyEpochManager {

        // Capture the amount of ETH / WETH rewards from our strategies
        (,, uint ethRewards) = strategyFactory.snapshot(epoch);

        // We want the ability to set a minimum sweep amount, so that when we are first
        // starting out the sweeps aren't pathetic.
        uint minSweepAmount = treasury.minSweepAmount();
        if (ethRewards < minSweepAmount) {
            ethRewards = minSweepAmount;
        }

        // If we are currently looking at a new collection addition, rather than a gauge weight
        // vote, then we can bypass additional logic and just end of Floor War.
        if (epochManager.isCollectionAdditionEpoch(epoch)) {
            // At this point we still need to calculate yield, but just attribute it to
            // the winner of the Floor War instead. This will be allocated the full yield
            // amount. Format the collection and amount into the array format that our
            // sweep registration is expecting.
            address[] memory tokens = new address[](1);
            tokens[0] = newCollectionWars.endFloorWar();

            // Allocate the full yield rewards into the single collection
            uint[] memory amounts = new uint[](1);
            amounts[0] = ethRewards;

            // Now that we have the results of the new collection addition we can register them
            // against our a pending sweep. This will need to be assigned a "sweep type" to show
            // that it is a Floor War and that we can additionally include "mercenary sweep
            // amounts" in the call.
            treasury.registerSweep(epoch, tokens, amounts, TreasuryEnums.SweepType.COLLECTION_ADDITION);
        } else {
            // Process the snapshot to find the floor war collection winners and the allocated amount
            // of the sweep.
            (address[] memory snapshotTokens, uint[] memory snapshotAmounts) = voteContract.snapshot(ethRewards);

            // We can now remove yield from our collections based on the yield that they generated
            // in the previous epoch.
            unchecked {
                // The linked mathematical operation is guaranteed to be performed safely by surrounding
                // conditionals evaluated in either require checks or if-else constructs.
                for (uint i; i < snapshotTokens.length; ++i) {
                    snapshotAmounts[i] = (snapshotAmounts[i] > _yield[snapshotTokens[i]]) ? snapshotAmounts[i] - _yield[snapshotTokens[i]] : 0;
                }
            }

            // Now that we have the results of the snapshot we can register them against our
            // pending sweeps.
            treasury.registerSweep(epoch, snapshotTokens, snapshotAmounts, TreasuryEnums.SweepType.SWEEP);
        }

        // Reset our yield monitoring
        for (uint i; i < _epochTokens.length;) {
            delete _yield[_epochTokens[i]];
            unchecked { ++i; }
        }

        delete _epochTokens;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

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

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

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

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

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

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

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

        return true;
    }

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

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

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

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

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

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

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

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

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

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

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

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

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

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

/**
 * A collection of generic errors that can be referenced across multiple
 * contracts. Contract-specific errors should still be stored in their
 * individual Solidity files.
 */

/// If a NULL address tries to be stored which should not be accepted
error CannotSetNullAddress();

/// If the caller has entered an insufficient amount to process the action. This
/// will likely be a zero amount.
error InsufficientAmount();

/// If the caller enters a percentage value that is too high for the requirements
error PercentageTooHigh(uint amount);

/// If a required ETH or token `transfer` call fails
error TransferFailed();

/// If a user calls a deposit related function with a zero amount
error CannotDepositZeroAmount();

/// If a user calls a withdrawal related function with a zero amount
error CannotWithdrawZeroAmount();

/// If there are no rewards available to be claimed
error NoRewardsAvailableToClaim();

/// If the requested collection is not approved
/// @param collection Address of the collection requested
error CollectionNotApproved(address collection);

/// If the requested strategy implementation is not approved
/// @param strategyImplementation Address of the strategy implementation requested
error StrategyNotApproved(address strategyImplementation);

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';

import {CannotSetNullAddress} from '@floor/utils/Errors.sol';

import {IEpochManager} from '@floor-interfaces/EpochManager.sol';

abstract contract EpochManaged is Ownable {
    /// Emits when {EpochManager} is updated
    event EpochManagerUpdated(address epochManager);

    /// Stores the current {EpochManager} contract
    IEpochManager public epochManager;

    /**
     * Allows an updated {EpochManager} address to be set.
     */
    function setEpochManager(address _epochManager) external virtual onlyOwner {
        _setEpochManager(_epochManager);
    }

    /**
     * Allows an updated {EpochManager} address to be set by an inheriting contract.
     */
    function _setEpochManager(address _epochManager) internal virtual {
        if (_epochManager == address(0)) revert CannotSetNullAddress();
        epochManager = IEpochManager(_epochManager);
        emit EpochManagerUpdated(_epochManager);
    }

    /**
     * Gets the current epoch from our {EpochManager}.
     */
    function currentEpoch() internal view virtual returns (uint) {
        return epochManager.currentEpoch();
    }

    /**
     * Checks that the contract caller is the {EpochManager}.
     */
    modifier onlyEpochManager() {
        require(msg.sender == address(epochManager), 'Only EpochManager can call');
        _;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * Strategies will hold the logic for interacting with external platforms to stake
 * and harvest reward yield. Each strategy will require its own strategy implementation
 * to allow for different immutable variables to be defined during construct.
 *
 * This will follow a similar approach to how NFTX offer their eligibility module
 * logic, with a lot of the power coming from inheritence.
 *
 * When constructed, we want to give the {Treasury} a max uint approval of the yield
 * and underlying tokens.
 */
interface IBaseStrategy {
    /// @dev When strategy receives a deposit
    event Deposit(address token, uint amount, address caller);

    /// @dev When strategy is harvested
    event Harvest(address token, uint amount);

    /// @dev When a staked user exits their position
    event Withdraw(address token, uint amount, address recipient);

    /**
     * Allows the strategy to be initialised.
     */
    function initialize(bytes32 name, uint strategyId, bytes calldata initData) external;

    /**
     * Name of the strategy.
     */
    function name() external view returns (bytes32);

    /**
     * The numerical ID of the strategy that acts as an index for the {StrategyFactory}.
     */
    function strategyId() external view returns (uint);

    /**
     * Total rewards generated by the strategy in all time. This is pure bragging rights.
     */
    function lifetimeRewards(address token) external returns (uint amount_);

    /**
     * The amount of rewards claimed in the last claim call.
     */
    function lastEpochRewards(address token) external returns (uint amount_);

    /**
     * Gets rewards that are available to harvest.
     */
    function available() external returns (address[] memory, uint[] memory);

    /**
     * Extracts all rewards from third party and moves it to a recipient. This should
     * only be called by a specific action.
     *
     * @dev This _should_ always be imposed to be the {Treasury} by the {StrategyFactory}.
     */
    function harvest(address /* _recipient */ ) external;

    /**
     * Returns an array of tokens that the strategy supports.
     *
     * @return address[] The address of valid tokens
     */
    function validTokens() external view returns (address[] memory);

    /**
     * Makes a call to a strategy to withdraw a percentage of the deposited holdings.
     *
     * @param recipient Strategy address to be updated
     * @param percentage The 2 decimal accuracy of the percentage to withdraw (e.g. 100% = 10000)
     *
     * @return address[] Array of tokens withdrawn
     * @return uint[] Amounts of respective tokens withdrawn
     */
    function withdrawPercentage(address recipient, uint percentage) external returns (address[] memory, uint[] memory);

    /**
     * Pauses deposits from being made into the strategy. This should only be called by
     * a guardian or governor.
     *
     * @param _p Boolean value for if the strategy should be paused
     */
    function pause(bool _p) external;

    /**
     * Gets a read of new yield since the last call. This is what can be called when
     * the epoch ends to determine the amount generated within the epoch.
     */
    function snapshot() external returns (address[] memory, uint[] memory);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * Allows for strategies to be created, pairing them with a {Strategy} and an approved
 * collection. The strategy creation script needs to be as highly optimised as possible
 * to ensure that the gas costs are kept down.
 *
 * This factory will keep an index of created strategies and secondary information to ensure
 * that external applications can display and maintain a list of available strategies.
 *
 * The contract can be paused to prevent the creation of new strategies.
 */

interface IStrategyFactory {
    /// @dev Sent when a strategy is created successfully
    event StrategyCreated(uint indexed strategyId, address strategyAddress, address assetAddress);

    /// @dev Sent when a snapshot is taken
    event StrategySnapshot(uint epoch, address[] tokens, uint[] amounts);

    /// @dev Sent when the Treasury address is updated
    event TreasuryUpdated(address treasury);

    /**
     * Our stored {Treasury} address.
     */
    function treasury() external view returns (address);

    /**
     * Provides a list of all strategies created.
     *
     * @return Array of all strategies created by the {StrategyFactory}
     */
    function strategies() external view returns (address[] memory);

    /**
     * Returns an array of all strategies that belong to a specific collection.
     */
    function collectionStrategies(address _collection) external view returns (address[] memory);

    /**
     * Provides a strategy against the provided `strategyId` (index). If the index does not exist,
     * then address(0) will be returned.
     *
     * @param _strategyId ID of the strategy to retrieve
     *
     * @return Address of the strategy
     */
    function strategy(uint _strategyId) external view returns (address);

    /**
     * Creates a strategy with an approved collection.
     *
     * @dev The strategy is not created using Clones as there are complications when allocated
     * roles and permissions.
     *
     * @param _name Human-readable name of the strategy
     * @param _strategy The strategy implemented by the strategy
     * @param _strategyInitData Bytes data required by the {Strategy} for initialization
     * @param _collection The address of the collection attached to the strategy
     *
     * @return strategyId_ ID of the newly created strategy
     * @return strategyAddr_ Address of the newly created strategy
     */
    function deployStrategy(bytes32 _name, address _strategy, bytes calldata _strategyInitData, address _collection)
        external
        returns (uint strategyId_, address strategyAddr_);

    /**
     * Allows individual strategies to be paused, meaning that assets can no longer be deposited,
     * although staked assets can always be withdrawn.
     *
     * @dev Events are fired within the strategy to allow listeners to update.
     *
     * @param _strategyId Strategy ID to be paused
     * @param _paused If the strategy should be paused or unpaused
     */
    function pause(uint _strategyId, bool _paused) external;

    /**
     * Reads the yield generated by a strategy since the last time that this function was called.
     *
     * @param _epoch The current epoch being snapshotted
     *
     * @return tokens Tokens that have been generated as yield
     * @return amounts The amount of yield generated for the corresponding token
     */
    function snapshot(uint _epoch) external returns (address[] memory tokens, uint[] memory amounts, uint totalAmount);

    /**
     * Harvest available reward yield from the strategy. This won't affect the amount
     * depositted into the contract and should only harvest rewards directly into the
     * {Treasury}.
     *
     * @param _strategyId Strategy ID to be harvested
     */
    function harvest(uint _strategyId) external;

    /**
     * Makes a call to a strategy withdraw function by passing the strategy ID and
     * `abi.encodeWithSelector` to build the bytes `_data` parameter. This will then
     * pass the data on to the strategy function and inject the treasury recipient
     * address within the call as the first function parameter.
     *
     * @dev It is required for the transaction to return a successful call, otherwise
     * the transaction will be reverted. The error response will be standardised so
     * debugging will require a trace, rather than just the end message.
     *
     * @param _strategyId Strategy ID to be withdrawn from
     * @param _data Strategy withdraw function call, using `encodeWithSelector`
     */
    function withdraw(uint _strategyId, bytes calldata _data) external;

    /**
     * Makes a call to a strategy to withdraw a percentage of the deposited holdings.
     *
     * @param _strategy Strategy address to be updated
     * @param _percentage The 2 decimal accuracy of the percentage to withdraw (e.g. 100% = 10000)
     */
    function withdrawPercentage(address _strategy, uint _percentage) external returns (address[] memory, uint[] memory);

    /**
     * Allows the {Treasury} contract address to be updated. All withdrawals will
     * be requested to be sent to this address when the `withdraw` is called.
     *
     * @dev This address is dynamically injected into the subsequent strategy
     * withdraw call.
     *
     * @param _treasury The new {Treasury} contract address
     */
    function setTreasury(address _treasury) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IEpochEndTriggered {
    /**
     * Function that is triggered when an epoch ends.
     */
    function endEpoch(uint epoch) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface INewCollectionWars {
    /**
     * For each FloorWar that is created, this structure will be created. When
     * the epoch ends, the FloorWar will remain and will be updated with information
     * on the winning collection and the votes attributed to each collection.
     */
    struct FloorWar {
        uint index;
        uint startEpoch;
        address[] collections;
    }

    /// Sent when a user casts a vote
    event VoteCast(address sender, address collection, uint userVotes, uint collectionVotes);

    /// Sent when a collection vote is revoked
    event VoteRevoked(address sender, address collection, uint collectionVotes);

    /// Sent when a collection NFT is staked to vote
    event NftVoteCast(address sender, uint war, address collection, uint collectionVotes, uint collectionNftVotes);

    /// Sent when a Collection Addition War is created
    event CollectionAdditionWarCreated(uint epoch, address[] collections, uint[] floorPrices);

    /// Sent when a Collection Addition War is started
    event CollectionAdditionWarStarted(uint warIndex);

    /// Sent when a Collection Addition War ends
    event CollectionAdditionWarEnded(uint warIndex, address collection);

    /// Sent when Collection Addition War NFTs are exercised
    event CollectionExercised(uint warIndex, address collection, uint value);

    /// Sent when the {NewCollectionWarOptions} contract address is updated
    event NewCollectionWarOptionsUpdated(address newCollectionWarOptions);

    /// Stores the number of votes a user has placed against a war collection
    function userVotes(bytes32) external view returns (uint);

    /// Stores the floor spot price of a collection token against a war collection
    function collectionSpotPrice(bytes32) external view returns (uint);

    /// Stores the total number of votes against a war collection
    function collectionVotes(bytes32) external view returns (uint);
    function collectionNftVotes(bytes32) external view returns (uint);

    /// Stores which collection the user has cast their votes towards to allow for
    /// reallocation on subsequent votes if needed.
    function userCollectionVote(bytes32) external view returns (address);

    /// Stores the address of the collection that won a Floor War
    function floorWarWinner(uint _epoch) external view returns (address);

    /// Stores if a collection has been flagged as ERC1155
    function is1155(address) external returns (bool);

    /// Stores the unlock epoch of a collection in a floor war
    function collectionEpochLock(bytes32) external returns (uint);

    /**
     * The total voting power of a user, regardless of if they have cast votes
     * or not.
     *
     * @param _user User address being checked
     */
    function userVotingPower(address _user) external view returns (uint);

    /**
     * The total number of votes that a user has available.
     *
     * @param _user User address being checked
     *
     * @return uint Number of votes available to the user
     */
    function userVotesAvailable(uint _war, address _user) external view returns (uint);

    /**
     * Allows the user to cast 100% of their voting power against an individual
     * collection. If the user has already voted on the FloorWar then this will
     * additionally reallocate their votes.
     */
    function vote(address collection) external;

    /**
     * Allows an approved contract to submit option-related votes against a collection
     * in the current war.
     *
     * @param sender The address of the user that staked the token
     * @param collection The collection to cast the vote against
     * @param votingPower The voting power added from the option creation
     */
    function optionVote(address sender, uint war, address collection, uint votingPower) external;

    /**
     * Revokes a user's current votes in the current war.
     *
     * @dev This is used when a user unstakes their floor
     *
     * @param account The address of the account that is having their vote revoked
     */
    function revokeVotes(address account) external;

    /**
     * Allow an authorised user to create a new floor war to start with a range of
     * collections from a specific epoch.
     */
    function createFloorWar(uint epoch, address[] calldata collections, bool[] calldata isErc1155, uint[] calldata floorPrices)
        external
        returns (uint);

    /**
     * Sets a scheduled {FloorWar} to be active.
     *
     * @dev This function is called by the {EpochManager} when a new epoch starts
     *
     * @param index The index of the {FloorWar} being started
     */
    function startFloorWar(uint index) external;

    /**
     * When the epoch has come to an end, this function will be called to finalise
     * the votes and decide which collection has won. This collection will then need
     * to be added to the {CollectionRegistry}.
     *
     * Any NFTs that have been staked will be timelocked for an additional epoch to
     * give the DAO time to exercise or reject any options.
     *
     * @dev We can't action this in one single call as we will need information about
     * the underlying NFTX token as well.
     */
    function endFloorWar() external returns (address highestVoteCollection);

    /**
     * Allows us to update our collection floor prices if we have seen a noticable difference
     * since the start of the epoch. This will need to be called for this reason as the floor
     * price of the collection heavily determines the amount of voting power awarded when
     * creating an option.
     */
    function updateCollectionFloorPrice(address collection, uint floorPrice) external;

    /**
     * Allows our options contract to be updated.
     *
     * @param _contract The new contract to use
     */
    function setOptionsContract(address _contract) external;

    /**
     * Check if a collection is in a FloorWar.
     */
    function isCollectionInWar(bytes32 warCollection) external view returns (bool);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * The GWV will allow users to assign their veFloor position to a strategy, or
 * optionally case it to a veFloor, which will use a constant value. As the
 * strategies will be rendered as an address, the veFloor vote will take a NULL
 * address value.
 *
 * At point of development this can take influence from:
 * https://github.com/saddle-finance/saddle-contract/blob/master/contracts/tokenomics/gauges/GaugeController.vy
 */
interface ISweepWars {
    /// Sent when a user casts or revokes their vote
    event VoteCast(address sender, address collection, int amount);

    /// Sent when a user has revoked their vote, or it is revoked on their behalf
    event VotesRevoked(address account, address collection, uint forVotesRevoked, uint againstVotesRevoked);

    /// Sent when the Sample Size is updated
    event SampleSizeUpdated(uint size);

    /// Sent when the {NftStaking} contract address is updated
    event NftStakingUpdated(address nftStaking);

    /**
     * Gets the number of votes for a collection at the current epoch.
     */
    function votes(address) external view returns (int);

    /**
     * The total voting power of a user, regardless of if they have cast votes
     * or not.
     */
    function userVotingPower(address _user) external view returns (uint);

    /**
     * The total number of votes that a user has available, calculated by:
     *
     * ```
     * votesAvailable_ = balanceOf(_user) - SUM(userVotes.votes_)
     * ```
     */
    function userVotesAvailable(address _user) external view returns (uint votesAvailable_);

    /**
     * Provides a list of collection addresses that can be voted on.
     */
    function voteOptions() external view returns (address[] memory collections_);

    /**
     * Allows a user to cast a vote using their veFloor allocation. We don't
     * need to monitor transfers as veFloor can only be minted or burned, and
     * we check the voters balance during the `snapshot` call.
     *
     * A user can vote with a partial amount of their veFloor holdings, and when
     * it comes to calculating their voting power this will need to be taken into
     * consideration that it will be:
     *
     * ```
     * staked balance + (gains from staking * (total balance - staked balance)%)
     * ```
     *
     * The {Treasury} cannot vote with it's holdings, as it shouldn't be holding
     * any staked Floor.
     */
    function vote(address _collection, int _amount) external;

    /**
     * Allows a user to revoke their votes from strategies. This will free up the
     * user's available votes that can subsequently be voted again with.
     */
    function revokeVotes(address[] memory _collection) external;

    /**
     * Allows an authorised contract or wallet to revoke all user votes. This
     * can be called when the veFLOOR balance is reduced.
     */
    function revokeAllUserVotes(address _account) external;

    /**
     * The snapshot function will need to iterate over all strategies that have
     * more than 0 votes against them. With that we will need to find each
     * strategy percentage share in relation to other strategies.
     *
     * This percentage share will instruct the {Treasury} on how much additional
     * FLOOR to allocate to the users staked in the strategies. These rewards will
     * become available in the {RewardLedger}.
     *
     * +----------------+-----------------+-------------------+-------------------+
     * | Voter          | veFloor         | Vote Weight       | Strategy          |
     * +----------------+-----------------+-------------------+-------------------+
     * | Alice          | 30              | 40                | 1                 |
     * | Bob            | 20              | 30                | 2                 |
     * | Carol          | 40              | 55                | 3                 |
     * | Dave           | 20              | 40                | 2                 |
     * | Emily          | 25              | 35                | 0                 |
     * +----------------+-----------------+-------------------+-------------------+
     *
     * With the above information, and assuming that the {Treasury} has allocated
     * 1000 FLOOR tokens to be additionally distributed in this snapshot, we would
     * have the following allocations going to the strategies.
     *
     * +----------------+-----------------+-------------------+-------------------+
     * | Strategy       | Votes Total     | Vote Percent      | veFloor Rewards   |
     * +----------------+-----------------+-------------------+-------------------+
     * | 0 (veFloor)    | 35              | 17.5%             | 175               |
     * | 1              | 40              | 20%               | 200               |
     * | 2              | 70              | 35%               | 350               |
     * | 3              | 55              | 27.5%             | 275               |
     * | 4              | 0               | 0%                | 0                 |
     * +----------------+-----------------+-------------------+-------------------+
     *
     * This would distribute the strategies allocated rewards against the staked
     * percentage in the strategy. Any Treasury holdings that would be given in rewards
     * are just deposited into the {Treasury} as FLOOR, bypassing the {RewardsLedger}.
     */
    function snapshot(uint tokens) external returns (address[] memory collections, uint[] memory amounts);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {IWETH} from '@floor-interfaces/tokens/WETH.sol';


library TreasuryEnums {
    /// Different sweep types that can be specified.
    enum SweepType {
        COLLECTION_ADDITION,
        SWEEP
    }

    /// Different approval types that can be specified.
    enum ApprovalType {
        NATIVE,
        ERC20,
        ERC721,
        ERC1155
    }
}

/**
 * @dev The Treasury will hold all assets.
 */
interface ITreasury {
    /// Stores data that allows the Treasury to action a sweep.
    struct Sweep {
        TreasuryEnums.SweepType sweepType;
        address[] collections;
        uint[] amounts;
        bool completed;
        string message;
    }

    /// The data structure format that will be mapped against to define a token
    /// approval request.
    struct ActionApproval {
        TreasuryEnums.ApprovalType _type; // Token type
        address assetContract; // Used by 20, 721 and 1155
        address target; // Used by 20, 721 and 1155
        uint amount; // Used by native and 20 tokens
    }

    /// @dev When native network token is withdrawn from the Treasury
    event Deposit(uint amount);

    /// @dev When an ERC20 is depositted into the Treasury
    event DepositERC20(address token, uint amount);

    /// @dev When an ERC721 is depositted into the Treasury
    event DepositERC721(address token, uint tokenId);

    /// @dev When an ERC1155 is depositted into the Treasury
    event DepositERC1155(address token, uint tokenId, uint amount);

    /// @dev When native network token is withdrawn from the Treasury
    event Withdraw(uint amount, address recipient);

    /// @dev When an ERC20 token is withdrawn from the Treasury
    event WithdrawERC20(address token, uint amount, address recipient);

    /// @dev When an ERC721 token is withdrawn from the Treasury
    event WithdrawERC721(address token, uint tokenId, address recipient);

    /// @dev When an ERC1155 is withdrawn from the Treasury
    event WithdrawERC1155(address token, uint tokenId, uint amount, address recipient);

    /// @dev When FLOOR is minted
    event FloorMinted(uint amount);

    /// @dev When a {Treasury} action is processed
    event ActionProcessed(address action, bytes data);

    /// @dev When a sweep is registered against an epoch
    event SweepRegistered(uint sweepEpoch, TreasuryEnums.SweepType sweepType, address[] collections, uint[] amounts);

    /// @dev When an action is assigned to a sweep epoch
    event SweepAction(uint sweepEpoch);

    /// @dev When an epoch is swept
    event EpochSwept(uint epochIndex);

    /// Emitted when the {MercenarySweeper} contract address is updated
    event MercenarySweeperUpdated(address mercSweeper);

    /// Emitted when the minimum sweep amount is updated
    event MinSweepAmountUpdated(uint minSweepAmount);

    /// Emitted when the {VeFloorStaking} contract is updated
    event VeFloorStakingUpdated(address veFloorStaking);

    /// Emitted when the {StrategyFactory} contract is updated
    event StrategyFactoryUpdated(address strategyFactory);

    /**
     * Our stored WETH address for the {Treasury}
     */
    function weth() external returns (IWETH);

    /**
     * Allow FLOOR token to be minted. This should be called from the deposit method
     * internally, but a public method will allow a {TreasuryManager} to bypass this
     * and create additional FLOOR tokens if needed.
     *
     * @dev We only want to do this on creation and for inflation. Have a think on how
     * we can implement this!
     */
    function mint(uint amount) external;

    /**
     * Allows an ERC20 token to be deposited and generates FLOOR tokens based on
     * the current determined value of FLOOR and the token.
     */
    function depositERC20(address token, uint amount) external;

    /**
     * Allows an ERC721 token to be deposited and generates FLOOR tokens based on
     * the current determined value of FLOOR and the token.
     */
    function depositERC721(address token, uint tokenId) external;

    /**
     * Allows an ERC1155 token(s) to be deposited and generates FLOOR tokens based on
     * the current determined value of FLOOR and the token.
     */
    function depositERC1155(address token, uint tokenId, uint amount) external;

    /**
     * Allows an approved user to withdraw native token.
     */
    function withdraw(address recipient, uint amount) external;

    /**
     * Allows an approved user to withdraw and ERC20 token from the Treasury.
     */
    function withdrawERC20(address recipient, address token, uint amount) external;

    /**
     * Allows an approved user to withdraw and ERC721 token from the Treasury.
     */
    function withdrawERC721(address recipient, address token, uint tokenId) external;

    /**
     * Allows an approved user to withdraw an ERC1155 token(s) from the Treasury.
     */
    function withdrawERC1155(address recipient, address token, uint tokenId, uint amount) external;

    /**
     * Actions a sweep to be used against a contract that implements {ISweeper}. This
     * will fulfill the sweep and we then mark the sweep as completed.
     */
    function sweepEpoch(uint epochIndex, address sweeper, bytes calldata data, uint mercSweep) external;

    /**
     * Allows the DAO to resweep an already swept "Sweep" struct, using a contract that
     * implements {ISweeper}. This will fulfill the sweep again and keep the sweep marked
     * as completed.
     */
    function resweepEpoch(uint epochIndex, address sweeper, bytes calldata data, uint mercSweep) external;

    /**
     * When an epoch ends, we have the ability to register a sweep against the {Treasury}
     * via an approved contract. This will store a DAO sweep that will need to be actioned
     * using the `sweepEpoch` function.
     */
    function registerSweep(uint epoch, address[] calldata collections, uint[] calldata amounts, TreasuryEnums.SweepType sweepType)
        external;

    /**
     * The minimum sweep amount that can be implemented, or excluded, as desired by the DAO.
     */
    function minSweepAmount() external returns (uint);

    /**
     * Allows the mercenary sweeper contract to be updated.
     */
    function setMercenarySweeper(address _mercSweeper) external;

    /**
     * Allows us to set a new VeFloorStaking contract that is used when sweeping epochs.
     */
    function setVeFloorStaking(address _veFloorStaking) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// 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;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

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

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * Handles epoch management for all other contracts.
 */
interface IEpochManager {

    /// Emitted when an epoch is ended
    event EpochEnded(uint epoch, uint timestamp);

    /// Emitted when a new collection war is scheduled
    event CollectionAdditionWarScheduled(uint epoch, uint index);

    /// Emitted when required contracts are updated
    event EpochManagerContractsUpdated(address newCollectionWars, address voteMarket);

    /**
     * The current epoch that is running across the codebase.
     *
     * @return The current epoch
     */
    function currentEpoch() external view returns (uint);

    /**
     * Stores a mapping of an epoch to a collection addition war index.
     *
     * @param _epoch Epoch to check
     *
     * @return Index of the collection addition war. Will return 0 if none found
     */
    function collectionEpochs(uint _epoch) external view returns (uint);

    /**
     * Will return if the current epoch is a collection addition vote.
     *
     * @return If the current epoch is a collection addition
     */
    function isCollectionAdditionEpoch() external view returns (bool);

    /**
     * Will return if the specified epoch is a collection addition vote.
     *
     * @param epoch The epoch to check
     *
     * @return If the specified epoch is a collection addition
     */
    function isCollectionAdditionEpoch(uint epoch) external view returns (bool);

    /**
     * Allows an epoch to be scheduled to be a collection addition vote. An index will
     * be specified to show which collection addition will be used. The index will not
     * be a zero value.
     *
     * @param epoch The epoch that the Collection Addition will take place in
     * @param index The Collection Addition array index
     */
    function scheduleCollectionAdditionEpoch(uint epoch, uint index) external;

    /**
     * Triggers an epoch to end.
     *
     * @dev More information about this function can be found in the actual contract
     */
    function endEpoch() external;

    /**
     * Provides an estimated timestamp of when an epoch started, and also the earliest
     * that an epoch in the future could start.
     *
     * @param _epoch The epoch to find the estimated timestamp of
     *
     * @return The estimated timestamp of when the specified epoch started
     */
    function epochIterationTimestamp(uint _epoch) external returns (uint);

    /**
     * The length of an epoch in seconds.
     *
     * @return The length of the epoch in seconds
     */
    function EPOCH_LENGTH() external returns (uint);

    /**
     * Sets contracts that the epoch manager relies on. This doesn't have to include
     * all of the contracts that are {EpochManaged}, but only needs to set ones that the
     * {EpochManager} needs to interact with.
     */
    function setContracts(address _newCollectionWars, address _voteMarket) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IWETH is IERC20 {
    function allowance(address, address) external view returns (uint);

    function balanceOf(address) external view returns (uint);

    function approve(address, uint) external returns (bool);

    function transfer(address, uint) external returns (bool);

    function transferFrom(address, address, uint) external returns (bool);

    function deposit() external payable;

    function withdraw(uint) external;
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):