Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Epoch Manage... | 19140211 | 761 days ago | IN | 0 ETH | 0.0009854 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RegisterSweepTrigger
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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 {}
}// 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;
}{
"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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.