ETH Price: $2,144.79 (+8.28%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Epoch Manage...191402112024-02-02 10:47:35761 days ago1706870855IN
0xdf95Bd23...De5d0971a
0 ETH0.000985420.87732532

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RegisterSweepTrigger

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion
// 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;
    }
}

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

File 3 of 16 : Errors.sol
// 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);

// 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');
        _;
    }
}

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

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

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@uniswap-v3/=lib/",
    "@uniswap/v3-periphery/=lib/v3-periphery/",
    "@chainlink/=lib/chainlink/",
    "@murky/=lib/murky/src/",
    "@solidity-math-utils/=lib/solidity-math-utils/project/contracts/",
    "@solidity-trigonometry/=lib/solidity-trigonometry/src/",
    "@1inch/=lib/",
    "@charmfi/=lib/charmfi-contracts-0.8.0-support/",
    "@sudoswap/=lib/lssvm/src/",
    "@floor/=src/contracts/",
    "@floor-interfaces/=src/interfaces/",
    "@floor-scripts/=script/",
    "@ERC721A/=lib/ERC721A/contracts/",
    "foundry-random/=lib/foundry-random/src/",
    "lssvm2/=lib/lssvm2/src/",
    "@nftx-protocol-v3/=lib/nftx-protocol-v3/src/",
    "@manifoldxyz/=lib/lssvm2/lib/",
    "@mocks/=lib/nftx-protocol-v3/src/mocks/",
    "@permit2/=lib/nftx-protocol-v3/lib/permit2/src/",
    "@prb/math/=lib/lssvm2/lib/prb-math/src/",
    "@prb/test/=lib/foundry-random/lib/prb-test/src/",
    "@src/=lib/nftx-protocol-v3/src/",
    "@test/=lib/nftx-protocol-v3/test/",
    "@uni-core/=lib/nftx-protocol-v3/src/uniswap/v3-core/",
    "@uni-periphery/=lib/nftx-protocol-v3/src/uniswap/v3-periphery/",
    "@uniswap/lib/=lib/nftx-protocol-v3/lib/solidity-lib/",
    "@uniswap/v2-core/=lib/nftx-protocol-v3/lib/v2-core/",
    "@uniswap/v3-core/contracts/=lib/nftx-protocol-v3/src/uniswap/v3-core/",
    "CramBit/=lib/foundry-random/lib/CramBit/",
    "ERC721A/=lib/ERC721A/contracts/",
    "base64-sol/=lib/nftx-protocol-v3/src/uniswap/v3-periphery/libraries/",
    "chainlink/=lib/chainlink/",
    "charmfi-contracts-0.8.0-support/=lib/charmfi-contracts-0.8.0-support/",
    "clones-with-immutable-args/=lib/lssvm2/lib/clones-with-immutable-args/src/",
    "crambit/=lib/foundry-random/lib/CramBit/src/",
    "create2-helpers/=lib/lssvm2/lib/royalty-registry-solidity/lib/create2-helpers/",
    "create3-factory/=lib/lssvm2/lib/create3-factory/",
    "foundry-huff/=lib/lssvm2/lib/foundry-huff/src/",
    "foundry-random/=lib/foundry-random/src/",
    "huffmate/=lib/lssvm2/lib/huffmate/src/",
    "libraries-solidity/=lib/lssvm2/lib/libraries-solidity/contracts/",
    "lssvm/=lib/lssvm/src/",
    "lssvm2/=lib/lssvm2/src/",
    "manifoldxyz/=lib/lssvm2/lib/royalty-registry-solidity/contracts/",
    "murky/=lib/murky/src/",
    "nftx-protocol-v3/=lib/nftx-protocol-v3/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "prb-math/=lib/solidity-trigonometry/lib/prb-math/contracts/",
    "prb-test/=lib/foundry-random/lib/prb-test/src/",
    "royalty-registry-solidity.git/=lib/lssvm/lib/royalty-registry-solidity.git/contracts/",
    "royalty-registry-solidity/=lib/lssvm2/lib/royalty-registry-solidity/",
    "solidity-bytes-utils/=lib/foundry-random/lib/solidity-bytes-utils/contracts/",
    "solidity-math-utils/=lib/solidity-math-utils/",
    "solidity-stringutils/=lib/lssvm2/lib/foundry-huff/lib/solidity-stringutils/",
    "solidity-trigonometry/=lib/solidity-trigonometry/src/",
    "solidity-utils/=lib/solidity-utils/contracts/",
    "solmate/=lib/lssvm2/lib/solmate/src/",
    "src/=lib/foundry-random/src/",
    "stringutils/=lib/lssvm2/lib/foundry-huff/lib/solidity-stringutils/",
    "v3-core/=lib/v3-core/contracts/",
    "v3-periphery/=lib/v3-periphery/contracts/",
    "weird-erc20/=lib/lssvm/lib/solmate/lib/weird-erc20/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_newCollectionWars","type":"address"},{"internalType":"address","name":"_strategyFactory","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_voteContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotSetNullAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"epochManager","type":"address"}],"name":"EpochManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"endEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epochManager","outputs":[{"internalType":"contract IEpochManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newCollectionWars","outputs":[{"internalType":"contract INewCollectionWars","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_epochManager","type":"address"}],"name":"setEpochManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategyFactory","outputs":[{"internalType":"contract IStrategyFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"contract ITreasury","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voteContract","outputs":[{"internalType":"contract ISweepWars","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6101006040523480156200001257600080fd5b5060405162000f5438038062000f54833981016040819052620000359162000133565b6200004033620000c6565b6001600160a01b03841615806200005e57506001600160a01b038316155b806200007157506001600160a01b038216155b806200008457506001600160a01b038116155b15620000a35760405163d713c59760e01b815260040160405180910390fd5b6001600160a01b0393841660805291831660e052821660c0521660a05262000190565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200012e57600080fd5b919050565b600080600080608085870312156200014a57600080fd5b620001558562000116565b9350620001656020860162000116565b9250620001756040860162000116565b9150620001856060860162000116565b905092959194509250565b60805160a05160c05160e051610d61620001f360003960008181610140015261023a015260008181610100015281816102bb015281816104e901526106ff01526000818161018d015261058101526000818160a801526103e10152610d616000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80639ef35710116100665780639ef357101461013b578063d4d59edb14610162578063e2d2bfe314610175578063ee183c4a14610188578063f2fde38b146101af57600080fd5b806318c3d4fe146100a35780636164e45d146100e657806361d027b3146100fb578063715018a6146101225780638da5cb5b1461012a575b600080fd5b6100ca7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100f96100f43660046109c8565b6101c2565b005b6100ca7f000000000000000000000000000000000000000000000000000000000000000081565b6100f96107d3565b6000546001600160a01b03166100ca565b6100ca7f000000000000000000000000000000000000000000000000000000000000000081565b6100f96101703660046109f6565b6107e7565b6001546100ca906001600160a01b031681565b6100ca7f000000000000000000000000000000000000000000000000000000000000000081565b6100f96101bd3660046109f6565b6107fb565b6001546001600160a01b031633146102215760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792045706f63684d616e616765722063616e2063616c6c00000000000060448201526064015b60405180910390fd5b604051638f1dd80960e01b8152600481018290526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638f1dd809906024016000604051808303816000875af115801561028b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102b39190810190610b54565b9250505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635313bff46040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033d9190610bc1565b90508082101561034b578091505b60015460405163197e4f9b60e01b8152600481018590526001600160a01b039091169063197e4f9b90602401602060405180830381865afa158015610394573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b89190610bda565b1561055e57604080516001808252818301909252600091602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631febf1ad6040518163ffffffff1660e01b81526004016020604051808303816000875af115801561043f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104639190610bfc565b8160008151811061047657610476610c19565b6001600160a01b03929092166020928302919091019091015260408051600180825281830190925260009181602001602082028036833701905050905083816000815181106104c7576104c7610c19565b60209081029190910101526040516306cab49b60e51b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d95693609061052590889086908690600090600401610c51565b600060405180830381600087803b15801561053f57600080fd5b505af1158015610553573d6000803e3d6000fd5b505050505050610770565b604051638f1dd80960e01b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638f1dd809906024016000604051808303816000875af11580156105ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105f29190810190610cf0565b9150915060005b82518110156106e7576002600084838151811061061857610618610c19565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205482828151811061065357610653610c19565b6020026020010151116106675760006106c2565b6002600084838151811061067d5761067d610c19565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020548282815181106106b8576106b8610c19565b6020026020010151035b8282815181106106d4576106d4610c19565b60209081029190910101526001016105f9565b506040516306cab49b60e51b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d95693609061073b90889086908690600190600401610c51565b600060405180830381600087803b15801561075557600080fd5b505af1158015610769573d6000803e3d6000fd5b5050505050505b60005b6003548110156107c157600260006003838154811061079457610794610c19565b60009182526020808320909101546001600160a01b03168352820192909252604001812055600101610773565b506107ce60036000610996565b505050565b6107db610871565b6107e560006108cb565b565b6107ef610871565b6107f88161091b565b50565b610803610871565b6001600160a01b0381166108685760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610218565b6107f8816108cb565b6000546001600160a01b031633146107e55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610218565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166109425760405163d713c59760e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4b9d66d8e64dff6d9d2728f9a38da9739d3cfdbe676fde05564aae22f85084659060200160405180910390a150565b50805460008255906000526020600020908101906107f891905b808211156109c457600081556001016109b0565b5090565b6000602082840312156109da57600080fd5b5035919050565b6001600160a01b03811681146107f857600080fd5b600060208284031215610a0857600080fd5b8135610a13816109e1565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610a5957610a59610a1a565b604052919050565b600067ffffffffffffffff821115610a7b57610a7b610a1a565b5060051b60200190565b600082601f830112610a9657600080fd5b81516020610aab610aa683610a61565b610a30565b82815260059290921b84018101918181019086841115610aca57600080fd5b8286015b84811015610aee578051610ae1816109e1565b8352918301918301610ace565b509695505050505050565b600082601f830112610b0a57600080fd5b81516020610b1a610aa683610a61565b82815260059290921b84018101918181019086841115610b3957600080fd5b8286015b84811015610aee5780518352918301918301610b3d565b600080600060608486031215610b6957600080fd5b835167ffffffffffffffff80821115610b8157600080fd5b610b8d87838801610a85565b94506020860151915080821115610ba357600080fd5b50610bb086828701610af9565b925050604084015190509250925092565b600060208284031215610bd357600080fd5b5051919050565b600060208284031215610bec57600080fd5b81518015158114610a1357600080fd5b600060208284031215610c0e57600080fd5b8151610a13816109e1565b634e487b7160e01b600052603260045260246000fd5b60028110610c4d57634e487b7160e01b600052602160045260246000fd5b9052565b600060808201868352602060808185015281875180845260a086019150828901935060005b81811015610c9b5784516001600160a01b031683529383019391830191600101610c76565b50508481036040860152865180825290820192508187019060005b81811015610cd257825185529383019391830191600101610cb6565b5050505080915050610ce76060830184610c2f565b95945050505050565b60008060408385031215610d0357600080fd5b825167ffffffffffffffff80821115610d1b57600080fd5b610d2786838701610a85565b93506020850151915080821115610d3d57600080fd5b50610d4a85828601610af9565b915050925092905056fea164736f6c6343000811000a00000000000000000000000072d6c121d0cdd773da8ba75057c5f4f2ef8755a1000000000000000000000000df2e023ea56d752d0b5be79f65557987976676cc0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d6800000000000000000000000009c9381417e0ecff536ec33375f1d5b2efa97d78

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80639ef35710116100665780639ef357101461013b578063d4d59edb14610162578063e2d2bfe314610175578063ee183c4a14610188578063f2fde38b146101af57600080fd5b806318c3d4fe146100a35780636164e45d146100e657806361d027b3146100fb578063715018a6146101225780638da5cb5b1461012a575b600080fd5b6100ca7f00000000000000000000000072d6c121d0cdd773da8ba75057c5f4f2ef8755a181565b6040516001600160a01b03909116815260200160405180910390f35b6100f96100f43660046109c8565b6101c2565b005b6100ca7f0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d6881565b6100f96107d3565b6000546001600160a01b03166100ca565b6100ca7f000000000000000000000000df2e023ea56d752d0b5be79f65557987976676cc81565b6100f96101703660046109f6565b6107e7565b6001546100ca906001600160a01b031681565b6100ca7f00000000000000000000000009c9381417e0ecff536ec33375f1d5b2efa97d7881565b6100f96101bd3660046109f6565b6107fb565b6001546001600160a01b031633146102215760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792045706f63684d616e616765722063616e2063616c6c00000000000060448201526064015b60405180910390fd5b604051638f1dd80960e01b8152600481018290526000907f000000000000000000000000df2e023ea56d752d0b5be79f65557987976676cc6001600160a01b031690638f1dd809906024016000604051808303816000875af115801561028b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102b39190810190610b54565b9250505060007f0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d686001600160a01b0316635313bff46040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610319573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033d9190610bc1565b90508082101561034b578091505b60015460405163197e4f9b60e01b8152600481018590526001600160a01b039091169063197e4f9b90602401602060405180830381865afa158015610394573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b89190610bda565b1561055e57604080516001808252818301909252600091602080830190803683370190505090507f00000000000000000000000072d6c121d0cdd773da8ba75057c5f4f2ef8755a16001600160a01b0316631febf1ad6040518163ffffffff1660e01b81526004016020604051808303816000875af115801561043f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104639190610bfc565b8160008151811061047657610476610c19565b6001600160a01b03929092166020928302919091019091015260408051600180825281830190925260009181602001602082028036833701905050905083816000815181106104c7576104c7610c19565b60209081029190910101526040516306cab49b60e51b81526001600160a01b037f0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d68169063d95693609061052590889086908690600090600401610c51565b600060405180830381600087803b15801561053f57600080fd5b505af1158015610553573d6000803e3d6000fd5b505050505050610770565b604051638f1dd80960e01b81526004810183905260009081906001600160a01b037f00000000000000000000000009c9381417e0ecff536ec33375f1d5b2efa97d781690638f1dd809906024016000604051808303816000875af11580156105ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105f29190810190610cf0565b9150915060005b82518110156106e7576002600084838151811061061857610618610c19565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205482828151811061065357610653610c19565b6020026020010151116106675760006106c2565b6002600084838151811061067d5761067d610c19565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020548282815181106106b8576106b8610c19565b6020026020010151035b8282815181106106d4576106d4610c19565b60209081029190910101526001016105f9565b506040516306cab49b60e51b81526001600160a01b037f0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d68169063d95693609061073b90889086908690600190600401610c51565b600060405180830381600087803b15801561075557600080fd5b505af1158015610769573d6000803e3d6000fd5b5050505050505b60005b6003548110156107c157600260006003838154811061079457610794610c19565b60009182526020808320909101546001600160a01b03168352820192909252604001812055600101610773565b506107ce60036000610996565b505050565b6107db610871565b6107e560006108cb565b565b6107ef610871565b6107f88161091b565b50565b610803610871565b6001600160a01b0381166108685760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610218565b6107f8816108cb565b6000546001600160a01b031633146107e55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610218565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166109425760405163d713c59760e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4b9d66d8e64dff6d9d2728f9a38da9739d3cfdbe676fde05564aae22f85084659060200160405180910390a150565b50805460008255906000526020600020908101906107f891905b808211156109c457600081556001016109b0565b5090565b6000602082840312156109da57600080fd5b5035919050565b6001600160a01b03811681146107f857600080fd5b600060208284031215610a0857600080fd5b8135610a13816109e1565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610a5957610a59610a1a565b604052919050565b600067ffffffffffffffff821115610a7b57610a7b610a1a565b5060051b60200190565b600082601f830112610a9657600080fd5b81516020610aab610aa683610a61565b610a30565b82815260059290921b84018101918181019086841115610aca57600080fd5b8286015b84811015610aee578051610ae1816109e1565b8352918301918301610ace565b509695505050505050565b600082601f830112610b0a57600080fd5b81516020610b1a610aa683610a61565b82815260059290921b84018101918181019086841115610b3957600080fd5b8286015b84811015610aee5780518352918301918301610b3d565b600080600060608486031215610b6957600080fd5b835167ffffffffffffffff80821115610b8157600080fd5b610b8d87838801610a85565b94506020860151915080821115610ba357600080fd5b50610bb086828701610af9565b925050604084015190509250925092565b600060208284031215610bd357600080fd5b5051919050565b600060208284031215610bec57600080fd5b81518015158114610a1357600080fd5b600060208284031215610c0e57600080fd5b8151610a13816109e1565b634e487b7160e01b600052603260045260246000fd5b60028110610c4d57634e487b7160e01b600052602160045260246000fd5b9052565b600060808201868352602060808185015281875180845260a086019150828901935060005b81811015610c9b5784516001600160a01b031683529383019391830191600101610c76565b50508481036040860152865180825290820192508187019060005b81811015610cd257825185529383019391830191600101610cb6565b5050505080915050610ce76060830184610c2f565b95945050505050565b60008060408385031215610d0357600080fd5b825167ffffffffffffffff80821115610d1b57600080fd5b610d2786838701610a85565b93506020850151915080821115610d3d57600080fd5b50610d4a85828601610af9565b915050925092905056fea164736f6c6343000811000a

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

00000000000000000000000072d6c121d0cdd773da8ba75057c5f4f2ef8755a1000000000000000000000000df2e023ea56d752d0b5be79f65557987976676cc0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d6800000000000000000000000009c9381417e0ecff536ec33375f1d5b2efa97d78

-----Decoded View---------------
Arg [0] : _newCollectionWars (address): 0x72d6C121D0cdd773DA8bA75057C5f4F2Ef8755a1
Arg [1] : _strategyFactory (address): 0xdf2e023Ea56d752D0B5bE79f65557987976676CC
Arg [2] : _treasury (address): 0x3b91f74Ae890dc97bb83E7b8eDd36D8296902d68
Arg [3] : _voteContract (address): 0x09c9381417E0ECff536EC33375f1d5b2EFa97D78

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000072d6c121d0cdd773da8ba75057c5f4f2ef8755a1
Arg [1] : 000000000000000000000000df2e023ea56d752d0b5be79f65557987976676cc
Arg [2] : 0000000000000000000000003b91f74ae890dc97bb83e7b8edd36d8296902d68
Arg [3] : 00000000000000000000000009c9381417e0ecff536ec33375f1d5b2efa97d78


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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