ETH Price: $3,916.41 (+0.81%)

Contract

0xD06ec117bAEC840f4Dc4FC43aF32f4f199296719

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AuctionMiddleMan

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
shanghai EvmVersion, GNU AGPLv3 license
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {Governance} from "@periphery/utils/Governance.sol";
import {IAuction} from "./interfaces/IAuction.sol";
import {IStrategyInterface} from "./interfaces/IStrategyInterface.sol";
import {IDistributionCreator, CampaignParameters} from "./interfaces/IDistributionCreator.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

interface IAuctionFactory {
    function createNewAuction(
        address _want,
        address _receiver,
        address _governance
    ) external returns (address);
}

/// @title AuctionMiddleMan
/// @dev Serves as the `auction` contract for strategies that receive KAT tokens.
///    Will simply forward any kicks to a real auction contract for non-KAT tokens.
///    For KAT tokens, it will create a campaign with MERKL for the amount kicked.
contract AuctionMiddleMan is Governance {
    using SafeERC20 for ERC20;

    event StrategyAdded(address indexed strategy);
    event StrategyRemoved(address indexed strategy);
    event CampaignDurationSet(uint32 campaignDuration);
    event KatFeeSet(uint256 katFee);
    event FeeRecipientSet(address feeRecipient);

    struct Strategy {
        address auction;
        bytes campaignData;
    }

    modifier onlyAddedStrategy() {
        require(
            _isAddedStrategy(msg.sender),
            "AuctionMiddleMan: Not a strategy"
        );
        _;
    }

    function _isAddedStrategy(address _strategy) internal view returns (bool) {
        return strategies[_strategy].auction != address(0);
    }

    IAuctionFactory public constant AUCTION_FACTORY =
        IAuctionFactory(0xCfA510188884F199fcC6e750764FAAbE6e56ec40);

    IDistributionCreator public constant DISTRIBUTION_CREATOR =
        IDistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);

    address public constant KAT = 0x7F1f4b4b29f5058fA32CC7a97141b8D7e5ABDC2d;

    address public constant WKAT = 0x6E9C1F88a960fE63387eb4b71BC525a9313d8461;

    mapping(address => Strategy) public strategies;

    uint256 public lastKatBalance;

    uint32 public campaignDuration;

    uint256 public katFee;

    address public feeRecipient;

    constructor(
        address _governance,
        address _feeRecipient
    ) Governance(_governance) {
        campaignDuration = 1 weeks;
        DISTRIBUTION_CREATOR.acceptConditions();
        katFee = 500;
        feeRecipient = _feeRecipient;
    }

    function addStrategy(
        address _strategy,
        bytes calldata _campaignData
    ) external onlyGovernance {
        require(
            !_isAddedStrategy(_strategy),
            "AuctionMiddleMan: Strategy already added"
        );
        require(_campaignData.length > 0, "AuctionMiddleMan: campaign data");

        address asset = IStrategyInterface(_strategy).asset();
        address management = IStrategyInterface(_strategy).management();
        address auction = AUCTION_FACTORY.createNewAuction(
            asset, // want
            _strategy, // receiver
            management // governance
        );

        strategies[_strategy] = Strategy({
            auction: auction,
            campaignData: _campaignData
        });

        emit StrategyAdded(_strategy);
    }

    function removeStrategy(address _strategy) external onlyGovernance {
        require(
            _isAddedStrategy(_strategy),
            "AuctionMiddleMan: Strategy not added"
        );
        delete strategies[_strategy];

        emit StrategyRemoved(_strategy);
    }

    function setAuction(
        address _strategy,
        address _auction
    ) external onlyGovernance {
        require(
            _isAddedStrategy(_strategy),
            "AuctionMiddleMan: Strategy not added"
        );
        require(_auction != address(0), "AuctionMiddleMan: zero address");
        strategies[_strategy].auction = _auction;
    }

    function setCampaignData(
        address _strategy,
        bytes calldata _campaignData
    ) external onlyGovernance {
        require(
            _isAddedStrategy(_strategy),
            "AuctionMiddleMan: Strategy not added"
        );
        require(_campaignData.length > 0, "AuctionMiddleMan: campaign data");
        strategies[_strategy].campaignData = _campaignData;
    }

    function setCampaignDuration(
        uint32 _campaignDuration
    ) external onlyGovernance {
        require(
            _campaignDuration > 1 days,
            "AuctionMiddleMan: Campaign duration"
        );
        campaignDuration = _campaignDuration;

        emit CampaignDurationSet(_campaignDuration);
    }

    function setKatFee(uint256 _katFee) external onlyGovernance {
        require(_katFee <= 1000, "AuctionMiddleMan: kat fee");
        katFee = _katFee;

        emit KatFeeSet(_katFee);
    }

    function setFeeRecipient(address _feeRecipient) external onlyGovernance {
        require(_feeRecipient != address(0), "AuctionMiddleMan: zero address");
        feeRecipient = _feeRecipient;

        emit FeeRecipientSet(_feeRecipient);
    }
    function isActive(address _token) external view returns (bool) {
        return IAuction(strategies[msg.sender].auction).isActive(_token);
    }

    function available(address _token) external view returns (uint256) {
        return IAuction(strategies[msg.sender].auction).available(_token);
    }

    function kick(address _token) external onlyAddedStrategy returns (uint256) {
        if (_token == KAT || _token == WKAT) {
            return _createCampaign(strategies[msg.sender].campaignData);
        } else {
            uint256 _kicked = ERC20(_token).balanceOf(address(this));
            address auction = strategies[msg.sender].auction;

            if (_kicked > 0) {
                ERC20(_token).safeTransfer(auction, _kicked);
            }

            return IAuction(auction).kick(_token);
        }
    }

    function _createCampaign(
        bytes memory _campaignData
    ) internal returns (uint256) {
        uint256 katBalance = ERC20(KAT).balanceOf(address(this));
        uint256 kicked = katBalance - lastKatBalance;

        if (kicked == 0) return 0;

        require(
            ERC20(WKAT).balanceOf(address(this)) >= kicked,
            "AuctionMiddleMan: not enough WKAT"
        );

        if (katFee > 0) {
            uint256 fee = (kicked * katFee) / 10_000;
            kicked -= fee;
            katBalance -= fee;

            ERC20(KAT).safeTransfer(feeRecipient, fee);
        }

        // Update lastKatBalance for next kick
        lastKatBalance = katBalance;

        ERC20(WKAT).forceApprove(address(DISTRIBUTION_CREATOR), kicked);

        DISTRIBUTION_CREATOR.createCampaign(
            CampaignParameters({
                campaignId: bytes32(0),
                creator: address(0),
                rewardToken: WKAT,
                amount: kicked,
                campaignType: 18,
                startTimestamp: uint32(block.timestamp),
                duration: campaignDuration,
                campaignData: _campaignData
            })
        );

        return kicked;
    }

    function wrapKat(uint256 _amount) external onlyGovernance {
        require(
            ERC20(KAT).balanceOf(address(this)) >= _amount,
            "AuctionMiddleMan: not enough KAT"
        );
        ERC20(KAT).safeTransfer(WKAT, _amount);

        lastKatBalance -= _amount;
    }

    function syncKatBalance() external onlyGovernance {
        lastKatBalance = ERC20(KAT).balanceOf(address(this));
    }

    function sweep(
        address _token,
        uint256 _amount,
        address _to
    ) external onlyGovernance {
        uint256 balance = ERC20(_token).balanceOf(address(this));
        if (balance < _amount) {
            _amount = balance;
        }

        if (_token == KAT) {
            lastKatBalance -= _amount;
        }

        ERC20(_token).safeTransfer(_to, _amount);
    }
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

contract Governance {
    /// @notice Emitted when the governance address is updated.
    event GovernanceTransferred(
        address indexed previousGovernance,
        address indexed newGovernance
    );

    modifier onlyGovernance() {
        _checkGovernance();
        _;
    }

    /// @notice Checks if the msg sender is the governance.
    function _checkGovernance() internal view virtual {
        require(governance == msg.sender, "!governance");
    }

    /// @notice Address that can set the default base fee and provider
    address public governance;

    constructor(address _governance) {
        governance = _governance;

        emit GovernanceTransferred(address(0), _governance);
    }

    /**
     * @notice Sets a new address as the governance of the contract.
     * @dev Throws if the caller is not current governance.
     * @param _newGovernance The new governance address.
     */
    function transferGovernance(
        address _newGovernance
    ) external virtual onlyGovernance {
        require(_newGovernance != address(0), "ZERO ADDRESS");
        address oldGovernance = governance;
        governance = _newGovernance;

        emit GovernanceTransferred(oldGovernance, _newGovernance);
    }
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.18;

interface IAuction {
    event AuctionDisabled(address indexed from, address indexed to);
    event AuctionEnabled(address indexed from, address indexed to);
    event AuctionKicked(address from, uint256 available);
    event GovernanceTransferred(
        address indexed previousGovernance,
        address indexed newGovernance
    );
    event UpdatePendingGovernance(address indexed newPendingGovernance);
    event UpdatedStartingPrice(uint256 startingPrice);

    struct AuctionInfo {
        uint64 kicked;
        uint64 scaler;
        uint128 initialAvailable;
    }

    function acceptGovernance() external;
    function auctionLength() external view returns (uint256);
    function auctions(address) external view returns (AuctionInfo memory);
    function available(address _from) external view returns (uint256);
    function disable(address _from) external;
    function disable(address _from, uint256 _index) external;
    function enable(address _from) external;
    function enabledAuctions(uint256) external view returns (address);
    function getAllEnabledAuctions() external view returns (address[] memory);
    function getAmountNeeded(address _from) external view returns (uint256);
    function getAmountNeeded(
        address _from,
        uint256 _amountToTake,
        uint256 _timestamp
    ) external view returns (uint256);
    function getAmountNeeded(
        address _from,
        uint256 _amountToTake
    ) external view returns (uint256);
    function governance() external view returns (address);
    function initialize(
        address _want,
        address _receiver,
        address _governance,
        uint256 _auctionLength,
        uint256 _startingPrice
    ) external;
    function isActive(address _from) external view returns (bool);
    function isValidSignature(
        bytes32 _hash,
        bytes calldata signature
    ) external view returns (bytes4);
    function kick(address _from) external returns (uint256 _available);
    function kickable(address _from) external view returns (uint256);
    function kicked(address _from) external view returns (uint256);
    function pendingGovernance() external view returns (address);
    function price(
        address _from,
        uint256 _timestamp
    ) external view returns (uint256);
    function price(address _from) external view returns (uint256);
    function receiver() external view returns (address);
    function setStartingPrice(uint256 _startingPrice) external;
    function settle(address _from) external;
    function startingPrice() external view returns (uint256);
    function sweep(address _token) external;
    function take(address _from) external returns (uint256);
    function take(address _from, uint256 _maxAmount) external returns (uint256);
    function take(
        address _from,
        uint256 _maxAmount,
        address _receiver,
        bytes calldata _data
    ) external returns (uint256);
    function take(
        address _from,
        uint256 _maxAmount,
        address _receiver
    ) external returns (uint256);
    function transferGovernance(address _newGovernance) external;
    function want() external view returns (address);
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.18;

import {IBaseHealthCheck} from "@periphery/Bases/HealthCheck/IBaseHealthCheck.sol";
import {IMerklDistributor} from "./IMerklDistributor.sol";

interface IStrategyInterface is IBaseHealthCheck {
    function lpValueInAsset()
        external
        view
        returns (uint256 valueLpInAssetTerms);

    function STEER_LP() external view returns (address);
    function MERKL_DISTRIBUTOR() external view returns (IMerklDistributor);

    function estimatedTotalAsset() external view returns (uint256);

    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata _data
    ) external;

    // Management parameters
    function targetIdleAssetBps() external view returns (uint16);
    function targetIdleBufferBps() external view returns (uint16);
    function pairedTokenDiscountBps() external view returns (uint16);
    function depositLimit() external view returns (uint256);
    function maxSwapValue() external view returns (uint256);
    function minAsset() external view returns (uint128);
    function useAuctions() external view returns (bool);
    function auction() external view returns (address);
    function minTendWait() external view returns (uint24);
    function maxTendBaseFeeGwei() external view returns (uint8);
    function lastTend() external view returns (uint64);

    // Management functions
    function setAuction(address _auction) external;
    function setDepositLimit(uint256 _depositLimit) external;
    function setTargetIdleAssetBps(uint16 _targetIdleAssetBps) external;
    function setTargetIdleBufferBps(uint16 _targetIdleBufferBps) external;
    function setPairedTokenDiscountBps(uint16 _pairedTokenDiscountBps) external;
    function setMinAsset(uint128 _minAsset) external;
    function setMaxSwapValue(uint256 _maxSwapValue) external;
    function setUseAuctions(bool _useAuctions) external;
    function setMinTendWait(uint24 _minTendWait) external;
    function setMaxTendBaseFee(uint8 _maxTendBaseFeeGwei) external;
    function manualSwapPairedTokenToAsset(uint256 _amount) external;
    function manualWithdrawFromLp(uint256 _amount) external;

    // Auction functions
    function kickAuction(address _from) external returns (uint256);
    function claim(
        address[] calldata users,
        address[] calldata tokens,
        uint256[] calldata amounts,
        bytes32[][] calldata proofs
    ) external;
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

struct CampaignParameters {
    // POPULATED ONCE CREATED

    // ID of the campaign. This can be left as a null bytes32 when creating campaigns
    // on Merkl.
    bytes32 campaignId;
    // CHOSEN BY CAMPAIGN CREATOR

    // Address of the campaign creator, if marked as address(0), it will be overriden with the
    // address of the `msg.sender` creating the campaign
    address creator;
    // Address of the token used as a reward
    address rewardToken;
    // Amount of `rewardToken` to distribute across all the epochs
    // Amount distributed per epoch is `amount/numEpoch`
    uint256 amount;
    // Type of campaign
    uint32 campaignType;
    // Timestamp at which the campaign should start
    uint32 startTimestamp;
    // Duration of the campaign in seconds. Has to be a multiple of EPOCH = 3600
    uint32 duration;
    // Extra data to pass to specify the campaign
    bytes campaignData;
}

interface IDistributionCreator {
    function createCampaign(
        CampaignParameters calldata _campaignParameters
    ) external returns (bytes32);
    function acceptConditions() external;
}

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

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.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}.
 *
 * 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 ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both 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 returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual 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 returns (uint8) {
        return 18;
    }

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

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual 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 `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` 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 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * 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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` 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.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` 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.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import {IStrategy} from "@tokenized-strategy/interfaces/IStrategy.sol";

interface IBaseHealthCheck is IStrategy {
    function doHealthCheck() external view returns (bool);

    function profitLimitRatio() external view returns (uint256);

    function lossLimitRatio() external view returns (uint256);

    function setProfitLimitRatio(uint256 _newProfitLimitRatio) external;

    function setLossLimitRatio(uint256 _newLossLimitRatio) external;

    function setDoHealthCheck(bool _doHealthCheck) external;
}

File 9 of 22 : IMerklDistributor.sol
pragma solidity ^0.8.18;

interface IMerklDistributor {
    /// @notice Claims rewards for a given set of users
    /// @dev Anyone may call this function for anyone else, funds go to destination regardless, it's just a question of
    /// who provides the proof and pays the gas: `msg.sender` is used only for addresses that require a trusted operator
    /// @param users Recipient of tokens
    /// @param tokens ERC20 claimed
    /// @param amounts Amount of tokens that will be sent to the corresponding users
    /// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root
    function claim(
        address[] calldata users,
        address[] calldata tokens,
        uint256[] calldata amounts,
        bytes32[][] calldata proofs
    ) external;
}

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

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
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 (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 15 of 22 : IStrategy.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import {ITokenizedStrategy} from "./ITokenizedStrategy.sol";
import {IBaseStrategy} from "./IBaseStrategy.sol";

interface IStrategy is IBaseStrategy, ITokenizedStrategy {}

File 16 of 22 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 17 of 22 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";

// Interface that implements the 4626 standard and the implementation functions
interface ITokenizedStrategy is IERC4626, IERC20Permit {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event StrategyShutdown();

    event NewTokenizedStrategy(
        address indexed strategy,
        address indexed asset,
        string apiVersion
    );

    event Reported(
        uint256 profit,
        uint256 loss,
        uint256 protocolFees,
        uint256 performanceFees
    );

    event UpdatePerformanceFeeRecipient(
        address indexed newPerformanceFeeRecipient
    );

    event UpdateKeeper(address indexed newKeeper);

    event UpdatePerformanceFee(uint16 newPerformanceFee);

    event UpdateManagement(address indexed newManagement);

    event UpdateEmergencyAdmin(address indexed newEmergencyAdmin);

    event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime);

    event UpdatePendingManagement(address indexed newPendingManagement);

    /*//////////////////////////////////////////////////////////////
                           INITIALIZATION
    //////////////////////////////////////////////////////////////*/

    function initialize(
        address _asset,
        string memory _name,
        address _management,
        address _performanceFeeRecipient,
        address _keeper
    ) external;

    /*//////////////////////////////////////////////////////////////
                    NON-STANDARD 4626 OPTIONS
    //////////////////////////////////////////////////////////////*/

    function withdraw(
        uint256 assets,
        address receiver,
        address owner,
        uint256 maxLoss
    ) external returns (uint256);

    function redeem(
        uint256 shares,
        address receiver,
        address owner,
        uint256 maxLoss
    ) external returns (uint256);

    function maxWithdraw(
        address owner,
        uint256 /*maxLoss*/
    ) external view returns (uint256);

    function maxRedeem(
        address owner,
        uint256 /*maxLoss*/
    ) external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                        MODIFIER HELPERS
    //////////////////////////////////////////////////////////////*/

    function requireManagement(address _sender) external view;

    function requireKeeperOrManagement(address _sender) external view;

    function requireEmergencyAuthorized(address _sender) external view;

    /*//////////////////////////////////////////////////////////////
                        KEEPERS FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    function tend() external;

    function report() external returns (uint256 _profit, uint256 _loss);

    /*//////////////////////////////////////////////////////////////
                        CONSTANTS
    //////////////////////////////////////////////////////////////*/

    function MAX_FEE() external view returns (uint16);

    function FACTORY() external view returns (address);

    /*//////////////////////////////////////////////////////////////
                            GETTERS
    //////////////////////////////////////////////////////////////*/

    function apiVersion() external view returns (string memory);

    function pricePerShare() external view returns (uint256);

    function management() external view returns (address);

    function pendingManagement() external view returns (address);

    function keeper() external view returns (address);

    function emergencyAdmin() external view returns (address);

    function performanceFee() external view returns (uint16);

    function performanceFeeRecipient() external view returns (address);

    function fullProfitUnlockDate() external view returns (uint256);

    function profitUnlockingRate() external view returns (uint256);

    function profitMaxUnlockTime() external view returns (uint256);

    function lastReport() external view returns (uint256);

    function isShutdown() external view returns (bool);

    function unlockedShares() external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                            SETTERS
    //////////////////////////////////////////////////////////////*/

    function setPendingManagement(address) external;

    function acceptManagement() external;

    function setKeeper(address _keeper) external;

    function setEmergencyAdmin(address _emergencyAdmin) external;

    function setPerformanceFee(uint16 _performanceFee) external;

    function setPerformanceFeeRecipient(
        address _performanceFeeRecipient
    ) external;

    function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external;

    function setName(string calldata _newName) external;

    function shutdownStrategy() external;

    function emergencyWithdraw(uint256 _amount) external;
}

// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;

interface IBaseStrategy {
    function tokenizedStrategyAddress() external view returns (address);

    /*//////////////////////////////////////////////////////////////
                            IMMUTABLE FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    function availableDepositLimit(
        address _owner
    ) external view returns (uint256);

    function availableWithdrawLimit(
        address _owner
    ) external view returns (uint256);

    function deployFunds(uint256 _assets) external;

    function freeFunds(uint256 _amount) external;

    function harvestAndReport() external returns (uint256);

    function tendThis(uint256 _totalIdle) external;

    function shutdownWithdraw(uint256 _amount) external;

    function tendTrigger() external view returns (bool, bytes memory);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

Settings
{
  "evmVersion": "shanghai",
  "metadata": {
    "appendCBOR": true,
    "bytecodeHash": "ipfs",
    "useLiteralContent": false
  },
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "forge-std/=lib/forge-std/src/",
    "@tokenized-strategy/=lib/tokenized-strategy/src/",
    "@periphery/=lib/tokenized-strategy-periphery/src/",
    "@uniswap-v3-core/=lib/uniswap-v3-core/contracts/",
    "@yearn-vaults/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/contracts/",
    "createx-forge/=lib/createx-forge/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/tokenized-strategy/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/",
    "tokenized-strategy-periphery/=lib/tokenized-strategy-periphery/",
    "tokenized-strategy/=lib/tokenized-strategy/",
    "uniswap-v3-core/=lib/uniswap-v3-core/contracts/",
    "yearn-vaults-v3/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/"
  ],
  "viaIR": true
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"campaignDuration","type":"uint32"}],"name":"CampaignDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernance","type":"address"}],"name":"GovernanceTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"katFee","type":"uint256"}],"name":"KatFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyRemoved","type":"event"},{"inputs":[],"name":"AUCTION_FACTORY","outputs":[{"internalType":"contract IAuctionFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISTRIBUTION_CREATOR","outputs":[{"internalType":"contract IDistributionCreator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KAT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WKAT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"bytes","name":"_campaignData","type":"bytes"}],"name":"addStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"available","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"campaignDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"katFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"kick","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastKatBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"removeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_auction","type":"address"}],"name":"setAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"bytes","name":"_campaignData","type":"bytes"}],"name":"setCampaignData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignDuration","type":"uint32"}],"name":"setCampaignDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_katFee","type":"uint256"}],"name":"setKatFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategies","outputs":[{"internalType":"address","name":"auction","type":"address"},{"internalType":"bytes","name":"campaignData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncKatBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"wrapKat","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60803462000145576200252d906001600160401b0390601f38849003908101601f19168201908382118383101762000127578083916040968794855283398101031262000145576200005f6020620000578362000149565b920162000149565b5f80546001600160a01b039384166001600160a01b0319918216811783558651919591927f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808180a362093a8063ffffffff196003541617600355738bb4c975ff3c250e0ceea271728547f3802b36fd803b156200014557826004815f809463063b87bf60e41b83525af180156200013b5762000116575b50506101f460045516906005541617600555516123ce90816200015f8239f35b8111620001275784525f80620000f6565b634e487b7160e01b5f52604160045260245ffd5b86513d5f823e3d90fd5b5f80fd5b51906001600160a01b0382168203620001455756fe6080604090808252600480361015610015575f80fd5b5f3560e01c91826310098ad51461159d57508163175188e81461149157816321d2e9c2146113c05781632af5e92a146112ea57816339ebf82314611265578163412ceaaa1461122b57816346904840146111d95781634a58265e1461119d5781635aa6e6751461114c5781635ad3009014610fb1578163670b827114610f6557816368df239514610f195781636f96c62e14610ecd5781637aeedf2a14610a45578163849fd6f7146109175781638561253e146108cb57816396c55175146107ee5781639f8a13d714610703578163b7612fff14610532578163c398d56d146104f0578163d2ebe32f14610429578163d38bfff414610319578163dc2c256f146101e2575063e74b981b14610128575f80fd5b346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760207fbf9a9534339a9d6b81696e05dcfb614b7dc518a31d48be3cfb757988381fb3239173ffffffffffffffffffffffffffffffffffffffff61019861166f565b6101a0611cc2565b16906101ad8215156119b2565b817fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055551908152a1005b5f80fd5b82346101de5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761021a61166f565b906024356044359173ffffffffffffffffffffffffffffffffffffffff80841684036101de57610248611cc2565b829416918151957f70a082310000000000000000000000000000000000000000000000000000000087523090870152602086602481865afa91821561031057505f916102da575b6102bc955081106102d2575b50737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81146102be57611d40565b005b6102ca83600254611a17565b600255611d40565b92508461029b565b90506020853d602011610308575b816102f56020938361172c565b810103126101de576102bc94519061028f565b3d91506102e8565b513d5f823e3d90fd5b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761035261166f565b9061035b611cc2565b73ffffffffffffffffffffffffffffffffffffffff8092169283156103cc5750505f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce805f80a3005b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600c60248201527f5a45524f204144445245535300000000000000000000000000000000000000006044820152fd5b9050346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57610461611cc2565b8151907f70a082310000000000000000000000000000000000000000000000000000000082523090820152602081602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa91821561031057505f916104be575b50600255005b90506020813d6020116104e8575b816104d96020938361172c565b810103126101de57515f6104b8565b3d91506104cc565b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209063ffffffff600354169051908152f35b9050346101de5773ffffffffffffffffffffffffffffffffffffffff6105573661188a565b929091610562611cc2565b6105986105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b611912565b6105a3841515611a51565b165f526001906001602095816020525f20019367ffffffffffffffff84116106d757506105da836105d48654611692565b86611ae2565b5f91601f8411600114610639575061062a9394509082915f9261062e575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055005b013590505f806105f8565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616979094925b8883106106c057505050836001959610610688575b505050811b019055005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690555f808061067e565b848401358655948501949281019291810191610669565b6041907f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b9050346101de57602091827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578261073f61166f565b335f5260018252602473ffffffffffffffffffffffffffffffffffffffff9182855f205416855196879485937f9f8a13d700000000000000000000000000000000000000000000000000000000855216908301525afa9182156107e4575f926107ac575b50519015158152f35b9091508281813d83116107dd575b6107c4818361172c565b810103126101de575180151581036101de57905f6107a3565b503d6107ba565b50513d5f823e3d90fd5b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761082761166f565b906108563373ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1561086e5760208361086784611b25565b9051908152f35b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f41756374696f6e4d6964646c654d616e3a204e6f7420612073747261746567796044820152fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051736e9c1f88a960fe63387eb4b71bc525a9313d84618152f35b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5780359063ffffffff82168092036101de57610961611cc2565b620151808211156109c2577fe570f66abd3e707c8ca3441f975afd46fda1f068e338c2af1b93abe412ae658d60208385817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000600354161760035551908152a1005b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602360248201527f41756374696f6e4d6964646c654d616e3a2043616d706169676e20647572617460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152fd5b82346101de57610a543661188a565b91610a60939193611cc2565b610a8e8173ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b610e4a57610a9d831515611a51565b73ffffffffffffffffffffffffffffffffffffffff809116938251927f38d52e0f000000000000000000000000000000000000000000000000000000008452602091828589818a5afa948515610dfa575f95610e2b575b5081517f88a8d60200000000000000000000000000000000000000000000000000000000815283818a818b5afa908115610e21579085915f91610e04575b50818451977f8ed5e3a3000000000000000000000000000000000000000000000000000000008952168a88015288602488015216604486015282856064815f73cfa510188884f199fcc6e750764faabe6e56ec405af1948515610dfa575f95610dcb575b50815167ffffffffffffffff9581840187811183821017610d9f57845285168152858711610d73577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe094835197610bf48688601f840116018a61172c565b80895236818501116101de5785815f92600196838d01378a010152848201978852885f5282938386525f209151167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781550194519687519485116106d75750610c6b84610c658754611692565b87611ae2565b8192601f8511600114610cef575050508190610cbb9394955f92610ce45750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b7f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f15f80a2005b0151905085806105f8565b849791979392931696855f52835f20935f915b898310610d5c5750505083600195969710610d25575b505050811b019055610cbe565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055848080610d18565b838501518655948501949381019391810191610d02565b6041897f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b60418b7f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b610dec919550833d8511610df3575b610de4818361172c565b810190611ab6565b9388610b96565b503d610dda565b82513d5f823e3d90fd5b610e1b9150853d8711610df357610de4818361172c565b8a610b32565b83513d5f823e3d90fd5b610e43919550833d8511610df357610de4818361172c565b9388610af4565b60848560208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f41756374696f6e4d6964646c654d616e3a20537472617465677920616c72656160448201527f64792061646465640000000000000000000000000000000000000000000000006064820152fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051738bb4c975ff3c250e0ceea271728547f3802b36fd8152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d8152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de576020905173cfa510188884f199fcc6e750764faabe6e56ec408152f35b9050346101de576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57813591610fee611cc2565b83517f70a0823100000000000000000000000000000000000000000000000000000000815230828201528281602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa80156111425784915f91611111575b50106110b757506110aa907fa9059cbb000000000000000000000000000000000000000000000000000000006110b2945191820152736e9c1f88a960fe63387eb4b71bc525a9313d84616024820152826044820152604481526110a5816116e3565b612360565b600254611a17565b600255005b816064928551927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f756768204b41546044820152fd5b809250848092503d831161113b575b61112a818361172c565b810103126101de578390515f611043565b503d611120565b85513d5f823e3d90fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209073ffffffffffffffffffffffffffffffffffffffff5f54169051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de576020906002549051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57602091549051908152f35b82346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5773ffffffffffffffffffffffffffffffffffffffff806112b361166f565b165f5260016020526112e66112d16001845f2093845416930161176d565b8351938493845280602085015283019061182e565b0390f35b82346101de57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761132161166f565b906024359173ffffffffffffffffffffffffffffffffffffffff908184168094036101de5761134e611cc2565b61137f6105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b61138a8415156119b2565b165f5260016020525f20907fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790555f80f35b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578035906113fc611cc2565b6103e8821161143457907f5e737898ddbd1f3490e56ee5e6fa392c8916a59bdd5714fbe5f8c7ef9a9f273f92816020935551908152a1005b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601960248201527f41756374696f6e4d6964646c654d616e3a206b617420666565000000000000006044820152fd5b82346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57600173ffffffffffffffffffffffffffffffffffffffff6114e061166f565b6114e8611cc2565b6115196105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1691825f52816020525f205f8155016115328154611692565b9081611560575b827f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea45f80a2005b81601f5f93116001146115775750555b8180611539565b908083918252611596601f60208420940160051c84016001850161199c565b5555611570565b83346101de57602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578260248186936115dd61166f565b90335f526001865273ffffffffffffffffffffffffffffffffffffffff80885f205416927f10098ad500000000000000000000000000000000000000000000000000000000855216908301525afa9182156107e4575f92611640575b5051908152f35b9091508281813d8311611668575b611658818361172c565b810103126101de57519083611639565b503d61164e565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101de57565b90600182811c921680156116d9575b60208310146116ac57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916116a1565b6080810190811067ffffffffffffffff8211176116ff57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176116ff57604052565b9060405191825f825461177f81611692565b908184526020946001916001811690815f146117ed57506001146117af575b5050506117ad9250038361172c565b565b5f90815285812095935091905b8183106117d55750506117ad93508201015f808061179e565b855488840185015294850194879450918301916117bc565b9150506117ad9593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f808061179e565b91908251928382525f5b8481106118765750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201611838565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101de5760043573ffffffffffffffffffffffffffffffffffffffff811681036101de579160243567ffffffffffffffff928382116101de57806023830112156101de5781600401359384116101de57602484830101116101de576024019190565b1561191957565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f41756374696f6e4d6964646c654d616e3a205374726174656779206e6f74206160448201527f64646564000000000000000000000000000000000000000000000000000000006064820152fd5b8181106119a7575050565b5f815560010161199c565b156119b957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f41756374696f6e4d6964646c654d616e3a207a65726f206164647265737300006044820152fd5b91908203918211611a2457565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b15611a5857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41756374696f6e4d6964646c654d616e3a2063616d706169676e2064617461006044820152fd5b908160209103126101de575173ffffffffffffffffffffffffffffffffffffffff811681036101de5790565b9190601f8111611af157505050565b6117ad925f5260205f20906020601f840160051c83019310611b1b575b601f0160051c019061199c565b9091508190611b0e565b73ffffffffffffffffffffffffffffffffffffffff809116737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81148015611ca5575b15611b84575050335f526001602052611b81611b7c600160405f200161176d565b611e4e565b90565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020928382602481865afa908115611c545784925f92611c70575b505f93602491338652600185526040862054169280611c5f575b5060405194859384927f96c5517500000000000000000000000000000000000000000000000000000000845260048401525af1918215611c54575f92611c2a57505090565b90809250813d8311611c4d575b611c41818361172c565b810103126101de575190565b503d611c37565b6040513d5f823e3d90fd5b611c6a908483611d40565b5f611be5565b838195949293503d8311611c9e575b611c89818361172c565b810103126101de57915190918391905f611bcb565b503d611c7f565b50736e9c1f88a960fe63387eb4b71bc525a9313d84618114611b5b565b73ffffffffffffffffffffffffffffffffffffffff5f54163303611ce257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21676f7665726e616e63650000000000000000000000000000000000000000006044820152fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082810191825273ffffffffffffffffffffffffffffffffffffffff9094166024830152604482019490945290925f91611dca81606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261172c565b519082855af115611c54575f513d611e45575073ffffffffffffffffffffffffffffffffffffffff81163b155b611dfe5750565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f5274afe7000000000000000000000000000000000000000000000000000000008352166004820152fd5b60011415611df7565b604051907f70a0823100000000000000000000000000000000000000000000000000000000808352306004840152602083602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa928315611c54575f936122b9575b5082611eb560025485611a17565b9384156122b057604051928352306004840152736e9c1f88a960fe63387eb4b71bc525a9313d846192602081602481875afa8015611c545786915f9161227b575b50106121f75760045480612163575b5050600255604051602081019060205f7f095ea7b30000000000000000000000000000000000000000000000000000000093848152738bb4c975ff3c250e0ceea271728547f3802b36fd602485015287604485015260448452611f67846116e3565b83519082875af15f513d82612147575b5050156120e7575b505063ffffffff600354169160405161010081019181831067ffffffffffffffff8411176116ff576120979460209460e0946040525f84525f8685015260408401528660608401526012608084015263ffffffff421660a084015260c08301528282015260405193849283927fa63f05ad000000000000000000000000000000000000000000000000000000008452856004850152805160248501528581015173ffffffffffffffffffffffffffffffffffffffff809116604486015260408201511660648501526060810151608485015263ffffffff60808201511660a485015263ffffffff60a08201511660c485015263ffffffff60c08201511660e4850152015161010061010484015261012483019061182e565b03815f738bb4c975ff3c250e0ceea271728547f3802b36fd5af18015611c54576120bf575090565b602090813d83116120e0575b6120d5818361172c565b810103126101de5790565b503d6120cb565b604051916020830152738bb4c975ff3c250e0ceea271728547f3802b36fd60248301525f6044830152604482526080820182811067ffffffffffffffff8211176116ff576121409261213b916040526122ed565b6122ed565b5f80611f7f565b90915061215b5750823b15155b5f80611f77565b600114612154565b809250859195029181830403611a24576121916121f09161271061218b940493848092611a17565b96611a17565b6005546040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff90911660248201526044810193909352916110a58160648101611d9e565b5f80611f05565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f75676820574b4160448201527f54000000000000000000000000000000000000000000000000000000000000006064820152fd5b9150506020813d6020116122a8575b816122976020938361172c565b810103126101de578590515f611ef6565b3d915061228a565b50505050505f90565b9092506020813d6020116122e5575b816122d56020938361172c565b810103126101de5751915f611ea7565b3d91506122c8565b60205f825182736e9c1f88a960fe63387eb4b71bc525a9313d8461940182855af115611c54575f513d6123575750803b155b6123265750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001141561231f565b60205f825182737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d940182855af115611c54575f513d6123575750803b15612326575056fea2646970667358221220fcfe8b6d43d40039894f341674791c700bfdc6160d060da403e263b1a8c003a764736f6c63430008170033000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6

Deployed Bytecode

0x6080604090808252600480361015610015575f80fd5b5f3560e01c91826310098ad51461159d57508163175188e81461149157816321d2e9c2146113c05781632af5e92a146112ea57816339ebf82314611265578163412ceaaa1461122b57816346904840146111d95781634a58265e1461119d5781635aa6e6751461114c5781635ad3009014610fb1578163670b827114610f6557816368df239514610f195781636f96c62e14610ecd5781637aeedf2a14610a45578163849fd6f7146109175781638561253e146108cb57816396c55175146107ee5781639f8a13d714610703578163b7612fff14610532578163c398d56d146104f0578163d2ebe32f14610429578163d38bfff414610319578163dc2c256f146101e2575063e74b981b14610128575f80fd5b346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760207fbf9a9534339a9d6b81696e05dcfb614b7dc518a31d48be3cfb757988381fb3239173ffffffffffffffffffffffffffffffffffffffff61019861166f565b6101a0611cc2565b16906101ad8215156119b2565b817fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055551908152a1005b5f80fd5b82346101de5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761021a61166f565b906024356044359173ffffffffffffffffffffffffffffffffffffffff80841684036101de57610248611cc2565b829416918151957f70a082310000000000000000000000000000000000000000000000000000000087523090870152602086602481865afa91821561031057505f916102da575b6102bc955081106102d2575b50737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81146102be57611d40565b005b6102ca83600254611a17565b600255611d40565b92508461029b565b90506020853d602011610308575b816102f56020938361172c565b810103126101de576102bc94519061028f565b3d91506102e8565b513d5f823e3d90fd5b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761035261166f565b9061035b611cc2565b73ffffffffffffffffffffffffffffffffffffffff8092169283156103cc5750505f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce805f80a3005b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600c60248201527f5a45524f204144445245535300000000000000000000000000000000000000006044820152fd5b9050346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57610461611cc2565b8151907f70a082310000000000000000000000000000000000000000000000000000000082523090820152602081602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa91821561031057505f916104be575b50600255005b90506020813d6020116104e8575b816104d96020938361172c565b810103126101de57515f6104b8565b3d91506104cc565b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209063ffffffff600354169051908152f35b9050346101de5773ffffffffffffffffffffffffffffffffffffffff6105573661188a565b929091610562611cc2565b6105986105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b611912565b6105a3841515611a51565b165f526001906001602095816020525f20019367ffffffffffffffff84116106d757506105da836105d48654611692565b86611ae2565b5f91601f8411600114610639575061062a9394509082915f9261062e575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055005b013590505f806105f8565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616979094925b8883106106c057505050836001959610610688575b505050811b019055005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690555f808061067e565b848401358655948501949281019291810191610669565b6041907f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b9050346101de57602091827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578261073f61166f565b335f5260018252602473ffffffffffffffffffffffffffffffffffffffff9182855f205416855196879485937f9f8a13d700000000000000000000000000000000000000000000000000000000855216908301525afa9182156107e4575f926107ac575b50519015158152f35b9091508281813d83116107dd575b6107c4818361172c565b810103126101de575180151581036101de57905f6107a3565b503d6107ba565b50513d5f823e3d90fd5b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761082761166f565b906108563373ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1561086e5760208361086784611b25565b9051908152f35b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f41756374696f6e4d6964646c654d616e3a204e6f7420612073747261746567796044820152fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051736e9c1f88a960fe63387eb4b71bc525a9313d84618152f35b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5780359063ffffffff82168092036101de57610961611cc2565b620151808211156109c2577fe570f66abd3e707c8ca3441f975afd46fda1f068e338c2af1b93abe412ae658d60208385817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000600354161760035551908152a1005b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602360248201527f41756374696f6e4d6964646c654d616e3a2043616d706169676e20647572617460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152fd5b82346101de57610a543661188a565b91610a60939193611cc2565b610a8e8173ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b610e4a57610a9d831515611a51565b73ffffffffffffffffffffffffffffffffffffffff809116938251927f38d52e0f000000000000000000000000000000000000000000000000000000008452602091828589818a5afa948515610dfa575f95610e2b575b5081517f88a8d60200000000000000000000000000000000000000000000000000000000815283818a818b5afa908115610e21579085915f91610e04575b50818451977f8ed5e3a3000000000000000000000000000000000000000000000000000000008952168a88015288602488015216604486015282856064815f73cfa510188884f199fcc6e750764faabe6e56ec405af1948515610dfa575f95610dcb575b50815167ffffffffffffffff9581840187811183821017610d9f57845285168152858711610d73577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe094835197610bf48688601f840116018a61172c565b80895236818501116101de5785815f92600196838d01378a010152848201978852885f5282938386525f209151167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781550194519687519485116106d75750610c6b84610c658754611692565b87611ae2565b8192601f8511600114610cef575050508190610cbb9394955f92610ce45750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b7f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f15f80a2005b0151905085806105f8565b849791979392931696855f52835f20935f915b898310610d5c5750505083600195969710610d25575b505050811b019055610cbe565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055848080610d18565b838501518655948501949381019391810191610d02565b6041897f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b60418b7f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b610dec919550833d8511610df3575b610de4818361172c565b810190611ab6565b9388610b96565b503d610dda565b82513d5f823e3d90fd5b610e1b9150853d8711610df357610de4818361172c565b8a610b32565b83513d5f823e3d90fd5b610e43919550833d8511610df357610de4818361172c565b9388610af4565b60848560208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f41756374696f6e4d6964646c654d616e3a20537472617465677920616c72656160448201527f64792061646465640000000000000000000000000000000000000000000000006064820152fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051738bb4c975ff3c250e0ceea271728547f3802b36fd8152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209051737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d8152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de576020905173cfa510188884f199fcc6e750764faabe6e56ec408152f35b9050346101de576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57813591610fee611cc2565b83517f70a0823100000000000000000000000000000000000000000000000000000000815230828201528281602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa80156111425784915f91611111575b50106110b757506110aa907fa9059cbb000000000000000000000000000000000000000000000000000000006110b2945191820152736e9c1f88a960fe63387eb4b71bc525a9313d84616024820152826044820152604481526110a5816116e3565b612360565b600254611a17565b600255005b816064928551927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f756768204b41546044820152fd5b809250848092503d831161113b575b61112a818361172c565b810103126101de578390515f611043565b503d611120565b85513d5f823e3d90fd5b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209073ffffffffffffffffffffffffffffffffffffffff5f54169051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de576020906002549051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b82346101de575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57602091549051908152f35b82346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5773ffffffffffffffffffffffffffffffffffffffff806112b361166f565b165f5260016020526112e66112d16001845f2093845416930161176d565b8351938493845280602085015283019061182e565b0390f35b82346101de57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de5761132161166f565b906024359173ffffffffffffffffffffffffffffffffffffffff908184168094036101de5761134e611cc2565b61137f6105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b61138a8415156119b2565b165f5260016020525f20907fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790555f80f35b9050346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578035906113fc611cc2565b6103e8821161143457907f5e737898ddbd1f3490e56ee5e6fa392c8916a59bdd5714fbe5f8c7ef9a9f273f92816020935551908152a1005b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601960248201527f41756374696f6e4d6964646c654d616e3a206b617420666565000000000000006044820152fd5b82346101de5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de57600173ffffffffffffffffffffffffffffffffffffffff6114e061166f565b6114e8611cc2565b6115196105938273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1691825f52816020525f205f8155016115328154611692565b9081611560575b827f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea45f80a2005b81601f5f93116001146115775750555b8180611539565b908083918252611596601f60208420940160051c84016001850161199c565b5555611570565b83346101de57602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101de578260248186936115dd61166f565b90335f526001865273ffffffffffffffffffffffffffffffffffffffff80885f205416927f10098ad500000000000000000000000000000000000000000000000000000000855216908301525afa9182156107e4575f92611640575b5051908152f35b9091508281813d8311611668575b611658818361172c565b810103126101de57519083611639565b503d61164e565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101de57565b90600182811c921680156116d9575b60208310146116ac57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916116a1565b6080810190811067ffffffffffffffff8211176116ff57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176116ff57604052565b9060405191825f825461177f81611692565b908184526020946001916001811690815f146117ed57506001146117af575b5050506117ad9250038361172c565b565b5f90815285812095935091905b8183106117d55750506117ad93508201015f808061179e565b855488840185015294850194879450918301916117bc565b9150506117ad9593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f808061179e565b91908251928382525f5b8481106118765750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201611838565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101de5760043573ffffffffffffffffffffffffffffffffffffffff811681036101de579160243567ffffffffffffffff928382116101de57806023830112156101de5781600401359384116101de57602484830101116101de576024019190565b1561191957565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f41756374696f6e4d6964646c654d616e3a205374726174656779206e6f74206160448201527f64646564000000000000000000000000000000000000000000000000000000006064820152fd5b8181106119a7575050565b5f815560010161199c565b156119b957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f41756374696f6e4d6964646c654d616e3a207a65726f206164647265737300006044820152fd5b91908203918211611a2457565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b15611a5857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41756374696f6e4d6964646c654d616e3a2063616d706169676e2064617461006044820152fd5b908160209103126101de575173ffffffffffffffffffffffffffffffffffffffff811681036101de5790565b9190601f8111611af157505050565b6117ad925f5260205f20906020601f840160051c83019310611b1b575b601f0160051c019061199c565b9091508190611b0e565b73ffffffffffffffffffffffffffffffffffffffff809116737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81148015611ca5575b15611b84575050335f526001602052611b81611b7c600160405f200161176d565b611e4e565b90565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020928382602481865afa908115611c545784925f92611c70575b505f93602491338652600185526040862054169280611c5f575b5060405194859384927f96c5517500000000000000000000000000000000000000000000000000000000845260048401525af1918215611c54575f92611c2a57505090565b90809250813d8311611c4d575b611c41818361172c565b810103126101de575190565b503d611c37565b6040513d5f823e3d90fd5b611c6a908483611d40565b5f611be5565b838195949293503d8311611c9e575b611c89818361172c565b810103126101de57915190918391905f611bcb565b503d611c7f565b50736e9c1f88a960fe63387eb4b71bc525a9313d84618114611b5b565b73ffffffffffffffffffffffffffffffffffffffff5f54163303611ce257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21676f7665726e616e63650000000000000000000000000000000000000000006044820152fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082810191825273ffffffffffffffffffffffffffffffffffffffff9094166024830152604482019490945290925f91611dca81606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261172c565b519082855af115611c54575f513d611e45575073ffffffffffffffffffffffffffffffffffffffff81163b155b611dfe5750565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f5274afe7000000000000000000000000000000000000000000000000000000008352166004820152fd5b60011415611df7565b604051907f70a0823100000000000000000000000000000000000000000000000000000000808352306004840152602083602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa928315611c54575f936122b9575b5082611eb560025485611a17565b9384156122b057604051928352306004840152736e9c1f88a960fe63387eb4b71bc525a9313d846192602081602481875afa8015611c545786915f9161227b575b50106121f75760045480612163575b5050600255604051602081019060205f7f095ea7b30000000000000000000000000000000000000000000000000000000093848152738bb4c975ff3c250e0ceea271728547f3802b36fd602485015287604485015260448452611f67846116e3565b83519082875af15f513d82612147575b5050156120e7575b505063ffffffff600354169160405161010081019181831067ffffffffffffffff8411176116ff576120979460209460e0946040525f84525f8685015260408401528660608401526012608084015263ffffffff421660a084015260c08301528282015260405193849283927fa63f05ad000000000000000000000000000000000000000000000000000000008452856004850152805160248501528581015173ffffffffffffffffffffffffffffffffffffffff809116604486015260408201511660648501526060810151608485015263ffffffff60808201511660a485015263ffffffff60a08201511660c485015263ffffffff60c08201511660e4850152015161010061010484015261012483019061182e565b03815f738bb4c975ff3c250e0ceea271728547f3802b36fd5af18015611c54576120bf575090565b602090813d83116120e0575b6120d5818361172c565b810103126101de5790565b503d6120cb565b604051916020830152738bb4c975ff3c250e0ceea271728547f3802b36fd60248301525f6044830152604482526080820182811067ffffffffffffffff8211176116ff576121409261213b916040526122ed565b6122ed565b5f80611f7f565b90915061215b5750823b15155b5f80611f77565b600114612154565b809250859195029181830403611a24576121916121f09161271061218b940493848092611a17565b96611a17565b6005546040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff90911660248201526044810193909352916110a58160648101611d9e565b5f80611f05565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f75676820574b4160448201527f54000000000000000000000000000000000000000000000000000000000000006064820152fd5b9150506020813d6020116122a8575b816122976020938361172c565b810103126101de578590515f611ef6565b3d915061228a565b50505050505f90565b9092506020813d6020116122e5575b816122d56020938361172c565b810103126101de5751915f611ea7565b3d91506122c8565b60205f825182736e9c1f88a960fe63387eb4b71bc525a9313d8461940182855af115611c54575f513d6123575750803b155b6123265750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001141561231f565b60205f825182737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d940182855af115611c54575f513d6123575750803b15612326575056fea2646970667358221220fcfe8b6d43d40039894f341674791c700bfdc6160d060da403e263b1a8c003a764736f6c63430008170033

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

000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6

-----Decoded View---------------
Arg [0] : _governance (address): 0xBe7c7efc1ef3245d37E3157F76A512108D6D7aE6
Arg [1] : _feeRecipient (address): 0xBe7c7efc1ef3245d37E3157F76A512108D6D7aE6

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6
Arg [1] : 000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6


Deployed Bytecode Sourcemap

946:7057:17:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5103:30;946:7057;;;;:::i;:::-;277:72:13;;:::i;:::-;946:7057:17;4987:27;4979:70;4987:27;;;4979:70;:::i;:::-;946:7057;;5059:28;946:7057;;;5059:28;946:7057;;;;;5103:30;946:7057;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;277:72:13;;:::i;:::-;341:1;946:7057:17;;;;;7752:38;946:7057;7752:38;;7784:4;7752:38;;;946:7057;;7752:38;946:7057;7752:38;;;;;;;;;;946:7057;7752:38;;;946:7057;7986:7;7804:17;;;;7800:65;;946:7057;7879:13;1963:42;7879:13;;7875:69;;7986:7;:::i;:::-;946:7057;7875:69;7908:25;946:7057;7908:25;946:7057;7908:25;:::i;:::-;;946:7057;7986:7;:::i;7800:65::-;7837:17;-1:-1:-1;7800:65:17;;;7752:38;;;946:7057;7752:38;;946:7057;7752:38;;;;;;946:7057;7752:38;;;:::i;:::-;;;946:7057;;;;7986:7;946:7057;;7752:38;;;;;;-1:-1:-1;7752:38:17;;;946:7057;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;277:72:13;;;:::i;:::-;946:7057:17;;;;1099:28:13;;;946:7057:17;;;;;;;;;;;;;;1241:52:13;946:7057:17;1241:52:13;;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;277:72:13;;:::i;:::-;946:7057:17;;7561:35;946:7057;7561:35;;7590:4;7561:35;;;946:7057;7561:35;;946:7057;7561:35;1963:42;7561:35;;;;;;;;946:7057;7561:35;;;946:7057;-1:-1:-1;7544:52:17;946:7057;;7561:35;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;7561:35;;;;;;-1:-1:-1;7561:35:17;;946:7057;;;;;;;;;;;;;;;2181:30;946:7057;;;;;;;;;;;;;;;;;;:::i;:::-;277:72:13;;;;;:::i;:::-;4116:110:17;4137:27;;946:7057;;;;-1:-1:-1;946:7057:17;1614:10;946:7057;;;-1:-1:-1;946:7057:17;;;1614:43;;1523:141;;4137:27;4116:110;:::i;:::-;4236:68;4244:24;;;4236:68;:::i;:::-;946:7057;;;4314:10;946:7057;4314:10;946:7057;;;;;;;4314:34;946:7057;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4314:10;946:7057;;;;;;-1:-1:-1;;;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5245:10;946:7057;;5234:10;946:7057;;;;;;;;;;;;;5225:57;;;;;946:7057;5225:57;;946:7057;5225:57;;;946:7057;5225:57;;;;;;;946:7057;5225:57;;;946:7057;;;;;;;;;5225:57;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;;;;;;;;5225:57;;;;;;;;;;946:7057;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1430:10;1413:28;1430:10;946:7057;;;;-1:-1:-1;946:7057:17;1614:10;946:7057;;;-1:-1:-1;946:7057:17;;;1614:43;;1523:141;;1413:28;946:7057;;;;1509:1;;;;:::i;:::-;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2043:42;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;277:72:13;;:::i;:::-;4521:6:17;4501:26;;946:7057;;;4650:38;946:7057;;;;;4598:36;946:7057;;;4598:36;946:7057;;;;;4650:38;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;277:72:13;;;;;;:::i;:::-;2688:27:17;;946:7057;;;;-1:-1:-1;946:7057:17;1614:10;946:7057;;;-1:-1:-1;946:7057:17;;;1614:43;;1523:141;;2688:27;946:7057;;2791:68;2799:24;;;2791:68;:::i;:::-;946:7057;;;;;;;2886:37;946:7057;2886:37;;;;;;;;;;;;;;;;946:7057;2886:37;;;946:7057;;;;;2954:42;;;;;;;;;;;;;;;;;946:7057;2954:42;;;946:7057;;;;;3024:142;946:7057;3024:142;;946:7057;3024:142;;;946:7057;;;;;;;;;;;3024:142;;946:7057;3024:142;946:7057;1744:42;3024:142;;;;;;;946:7057;3024:142;;;946:7057;-1:-1:-1;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;3177:10;946:7057;;;;;;;;;3201:91;;;946:7057;;;;;;3177:10;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3308:24;946:7057;3308:24;;946:7057;;;;;-1:-1:-1;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3177:10;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3024:142;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;946:7057;;;;;;;;;2954:42;;;;;;;;;;;;;;:::i;:::-;;;;;946:7057;;;;;;;;;2886:37;;;;;;;;;;;;;;;:::i;:::-;;;;;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1883:42;946:7057;;;;;;;;;;;;;;;;;;1963:42;946:7057;;;;;;;;;;;;;;;;;;1744:42;946:7057;;;;;;;;;;;;;;;;;;;277:72:13;;;:::i;:::-;946:7057:17;;;7283:35;;7312:4;7283:35;;;946:7057;7283:35;;946:7057;7283:35;1963:42;7283:35;;;;;;;;946:7057;7283:35;;;946:7057;7283:46;;946:7057;;;1328:43:9;946:7057:17;;7446:25;946:7057;;1328:43:9;;;;2043:42:17;946:7057;1328:43:9;;946:7057:17;;;;;;;1328:43:9;;;;;:::i;:::-;;:::i;:::-;7446:25:17;946:7057;7446:25;:::i;:::-;;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;7283:35;;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;;;7283:35;;;;;;;;;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2145:29;946:7057;;;;;;;;;;;;;;;;;;;;;;2246:27;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;2092:46;946:7057;;;2092:46;;946:7057;;;;;;;2092:46;;;:::i;:::-;946:7057;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;277:72:13;;:::i;:::-;3738:110:17;3759:27;;946:7057;;;;-1:-1:-1;946:7057:17;1614:10;946:7057;;;-1:-1:-1;946:7057:17;;;1614:43;;1523:141;;3738:110;3858:65;3866:22;;;3858:65;:::i;:::-;946:7057;;;3933:10;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;277:72:13;;;:::i;:::-;4790:4:17;4779:15;;946:7057;;;4866:18;946:7057;;;;;;;;;4866:18;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3549:10;946:7057;;;:::i;:::-;277:72:13;;:::i;:::-;3422:110:17;3443:27;;946:7057;;;;-1:-1:-1;946:7057:17;1614:10;946:7057;;;-1:-1:-1;946:7057:17;;;1614:43;;1523:141;;3422:110;946:7057;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;3586:26;;946:7057;3586:26;;946:7057;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3549:10;946:7057;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5399:10;;946:7057;;5388:10;946:7057;;;;;;;;;5379:58;946:7057;5379:58;;946:7057;5379:58;;;946:7057;5379:58;;;;;;;946:7057;5379:58;;;946:7057;;;;;;;5379:58;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;5379:58;;;;;;;;;946:7057;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;946:7057:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;-1:-1:-1;946:7057:17;;;;;;;;-1:-1:-1;;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;946:7057:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;946:7057:17;;-1:-1:-1;946:7057:17;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;946:7057:17;;;;5450:521;946:7057;;;;1963:42;5539:13;;:31;;;;5450:521;5535:430;;;5620:10;;;946:7057;;5609:10;946:7057;;5593:52;946:7057;5609:10;946:7057;;;5609:35;946:7057;:::i;:::-;5593:52;:::i;:::-;5586:59;:::o;5535:430::-;946:7057;;;5694:38;;5726:4;5694:38;;;946:7057;5694:38;;;;946:7057;5694:38;;;;;;;;;;;946:7057;5694:38;;;5535:430;5775:10;946:7057;5775:10;946:7057;5775:10;;946:7057;;5764:10;946:7057;;;;;;;5813:11;;5809:94;;5535:430;946:7057;;;5924:30;;;;;946:7057;5924:30;;5694:38;5924:30;;946:7057;5924:30;;;;;;;946:7057;5924:30;;;5917:37;;;:::o;5924:30::-;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;5917:37;:::o;5924:30::-;;;;;;946:7057;;;;;;;;;5809:94;5880:7;;;;;:::i;:::-;5809:94;;;5694:38;;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;;;;;;;;5694:38;;;;;;;5539:31;5556:14;2043:42;5556:14;;5539:31;;415:115:13;946:7057:17;483:10:13;946:7057:17;;497:10:13;483:24;946:7057:17;;415:115:13:o;946:7057:17:-;;;;;;;;;;;;;;;;;;;;;;;1219:160:9;946:7057:17;;;1328:43:9;;;;;;;946:7057:17;;;;1328:43:9;;;946:7057:17;;;;;;;;1219:160:9;;-1:-1:-1;;1328:43:9;946:7057:17;;;;1328:43:9;;;;;;;;;:::i;:::-;8507:421;;;;;;;;;-1:-1:-1;8507:421:9;;8942:15;;946:7057:17;;;;8960:26:9;:31;8942:68;8938:146;;1219:160;:::o;8938:146::-;1328:43;946:7057:17;;;;9033:40:9;;;;946:7057:17;9033:40:9;;;946:7057:17;9033:40:9;8942:68;9009:1;8994:16;;8942:68;;5977:1211:17;946:7057;;;;6102:35;;;6131:4;6102:35;;;946:7057;6102:35;;946:7057;6102:35;1963:42;6102:35;;;;;;;-1:-1:-1;6102:35:17;;;5977:1211;6081:56;;6164:27;6177:14;946:7057;6164:27;;:::i;:::-;6206:11;;;6202:25;;946:7057;;6259:36;;;6131:4;6102:35;6259:36;;946:7057;2043:42;6259:36;6102:35;6259:36;946:7057;6259:36;;;;;;;;;;-1:-1:-1;6259:36:17;;;5977:1211;6259:46;;946:7057;;6102:35;946:7057;6379:10;6375:196;;5977:1211;946:7057;;6177:14;946:7057;;;6102:35;5199:47:9;;946:7057:17;6102:35;-1:-1:-1;946:7057:17;5199:47:9;;;;946:7057:17;;5199:47:9;;946:7057:17;;;;;;;5199:47:9;;;;;:::i;:::-;9770:199;;;;;;;-1:-1:-1;9770:199:9;;9985:80;;;5977:1211:17;5261:45:9;;;5257:201;;5977:1211:17;946:7057;;;7071:16;946:7057;;;;;;;;;;;;;;;;;;;;6102:35;946:7057;;;;;-1:-1:-1;946:7057:17;;-1:-1:-1;6789:358:17;;;946:7057;;6789:358;;946:7057;6789:358;;;;946:7057;6984:2;6789:358;;;946:7057;;7027:15;946:7057;6789:358;;;946:7057;6789:358;;;946:7057;6789:358;;;946:7057;;;6740:417;;;;;946:7057;6740:417;;;6102:35;6740:417;;946:7057;;;;;;;6789:358;;;946:7057;;;;;;;;;;6789:358;;946:7057;;;;;;6789:358;;;946:7057;;;;;;6789:358;;;946:7057;;;;;;;6789:358;;;946:7057;;;;;;;6789:358;;;946:7057;;;;;;6789:358;946:7057;;;;;;;;;;;:::i;:::-;6740:417;;-1:-1:-1;946:7057:17;6740:417;;;;;;;;7168:13;5977:1211;:::o;6740:417::-;6102:35;6740:417;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;5977:1211;:::o;6740:417::-;;;;;5257:201:9;946:7057:17;;5349:43:9;6102:35:17;5349:43:9;;;946:7057:17;;5349:43:9;;946:7057:17;-1:-1:-1;946:7057:17;;;;;5349:43:9;;946:7057:17;;;;;;;;;;;;5434:12:9;946:7057:17;5349:43:9;946:7057:17;;;5349:43:9;:::i;:::-;5434:12;:::i;:::-;5257:201;;;;9985:80;9997:67;;-1:-1:-1;9997:15:9;;10015:26;;;:30;;9997:67;9985:80;;;;9997:67;10063:1;10048:16;9997:67;;6375:196:17;946:7057;;;;;;;;;;;;;;6486:17;1328:43:9;946:7057:17;6439:6;6459:13;946:7057;;6459:13;;;;;:::i;:::-;6486:17;;:::i;:::-;6542:12;946:7057;;;;6102:35;1328:43:9;;;946:7057:17;;;;;1328:43:9;;946:7057:17;;;;;;;;;1328:43:9;946:7057:17;;;;1328:43:9;946:7057:17;1328:43:9;6375:196:17;;;;946:7057;;;;;;;6102:35;;946:7057;;;;;;;;;;;;;;;;;;;6259:36;;;;6102:35;6259:36;;6102:35;6259:36;;;;;;6102:35;6259:36;;;:::i;:::-;;;946:7057;;;;;;;6259:36;;;;;;-1:-1:-1;6259:36:17;;6202:25;6219:8;;;;;-1:-1:-1;6219:8:17;:::o;6102:35::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;946:7057;;;;;6102:35;;;;;;;-1:-1:-1;6102:35:17;;8370:720:9;8507:421;-1:-1:-1;8507:421:9;;946:7057:17;;8507:421:9;;;;;;;;;-1:-1:-1;8507:421:9;;8942:15;;8960:26;;;:31;8942:68;8938:146;;8370:720;:::o;8938:146::-;946:7057:17;;;;9033:40:9;;;;;;;946:7057:17;9033:40:9;8942:68;9009:1;8994:16;;8942:68;;8370:720;8507:421;-1:-1:-1;8507:421:9;;1963:42:17;;8507:421:9;;;;;;;;;-1:-1:-1;8507:421:9;;8942:15;;8960:26;;;:31;8938:146;;8370:720;:::o

Swarm Source

ipfs://fcfe8b6d43d40039894f341674791c700bfdc6160d060da403e263b1a8c003a7

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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.