ETH Price: $3,536.24 (+4.40%)

Token

Staked Inv (sINV)
 

Overview

Max Total Supply

47,222.181382080767204426 sINV

Holders

76

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
*rosé.eth
Balance
153.940842259322953586 sINV

Value
$0.00
0x9c01b839c6091e519fd4749efa8b81e190c6d892
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
sINV

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion
File 1 of 5 : sInv.sol
// SPDX-License-Identifier: MIT License
pragma solidity ^0.8.21;

import "lib/solmate/src/tokens/ERC4626.sol";

interface IInvEscrow {
    function balance() external view returns (uint);
    function claimDBR() external;
    function claimable() external view returns (uint);
}

interface IMarket {
    function deposit(uint256 amount) external;
    function withdraw(uint256 amount) external;
    function dbr() external returns (address);
    function escrows(address user) external returns (address);
}

interface IERC20 {
    function transfer(address, uint) external returns (bool);
    function transferFrom(address, address, uint) external returns (bool);
    function balanceOf(address) external view returns (uint);
}

/**
 * @title sINV
 * @dev Auto-compounding ERC4626 wrapper for asset FiRM deposits utilizing xy=k auctions.
 * WARNING: While this vault is safe to be used as collateral in lending markets, it should not be allowed as a borrowable asset.
 * Any protocol in which sudden, large and atomic increases in the value of an asset may be a security risk should not integrate this vault.
 */
contract sINV is ERC4626{

    struct RevenueData {
        uint96 periodRevenue;
        uint96 lastPeriodRevenue;
        uint64 lastBuyPeriod;
    }

    struct KData {
        uint192 targetK;
        uint64 lastKUpdate;
    }
    
    uint256 public constant MIN_ASSETS = 10**16; // 1 cent
    uint256 public constant MIN_SHARES = 10**18;
    uint256 public constant MAX_ASSETS = 10**32; // 100 trillion asset
    uint256 public constant period = 7 days;
    uint256 public depositLimit;
    IMarket public immutable invMarket;
    IInvEscrow public immutable invEscrow;
    ERC20 public immutable DBR;
    RevenueData public revenueData;
    KData public kData;
    address public gov;
    address public guardian;
    address public pendingGov;
    uint256 public minBuffer;
    uint256 public prevK;

    function periodRevenue() external view returns(uint256){return revenueData.periodRevenue;}
    function lastPeriodRevenue() external view returns(uint256){return revenueData.lastPeriodRevenue;}
    function lastBuyPeriod() external view returns(uint256){return revenueData.lastBuyPeriod;}
    function targetK() external view returns(uint256){return kData.targetK;}
    function lastKUpdate() external view returns(uint256){return kData.lastKUpdate;}

    error OnlyGov();
    error OnlyPendingGov();
    error OnlyGuardian();
    error KTooLow(uint k, uint limit);
    error BelowMinShares();
    error AboveDepositLimit();
    error DepositLimitMustIncrease();
    error InsufficientAssets();
    error Invariant();
    error UnauthorizedTokenWithdrawal();

    /**
     * @dev Constructor for sINV contract.
     * WARNING: MIN_SHARES will always be unwithdrawable from the vault. Deployer should deposit enough to mint MIN_SHARES to avoid causing user grief.
     * @param _inv Address of the asset token.
     * @param _invMarket Address of the asset FiRM market.
     * @param _gov Address of the governance.
     * @param _K Initial value for the K variable used in calculations.
     */
    constructor(
        address _inv,
        address _invMarket,
        address _gov,
        address _guardian,
        uint256 _depositLimit,
        uint256 _K
    ) ERC4626(ERC20(_inv), "Staked Inv", "sINV") {
        if(_K == 0) revert KTooLow(_K, 1);
        IMarket(_invMarket).deposit(0); //creates an escrow on behalf of the sINV contract
        invEscrow = IInvEscrow(IMarket(_invMarket).escrows(address(this)));
        invMarket = IMarket(_invMarket);
        DBR = ERC20(IMarket(_invMarket).dbr());
        gov = _gov;
        guardian = _guardian;
        kData.targetK = uint192(_K);
        depositLimit = _depositLimit;
        prevK = _K;
        asset.approve(address(invMarket), type(uint).max);
    }

    modifier onlyGov() {
        if(msg.sender != gov) revert OnlyGov();
        _;
    }

    modifier onlyPendingGov() {
        if(msg.sender != pendingGov) revert OnlyPendingGov();
        _;
    }

    modifier onlyGuardian() {
        if(msg.sender != guardian) revert OnlyGuardian();
        _;
    }

    /**
     * @dev Hook that is called after tokens are deposited into the contract.
     */    
    function afterDeposit(uint256, uint256) internal override {
        if(totalSupply < MIN_SHARES) revert BelowMinShares();
        if(totalAssets() > depositLimit) revert AboveDepositLimit();
        uint256 invBal = asset.balanceOf(address(this));
        if(invBal > minBuffer){
            invMarket.deposit(invBal - minBuffer);
        }
    }

    /**
     * @dev Hook that is called before tokens are withdrawn from the contract.
     * @param assets The amount of assets to withdraw.
     * @param shares The amount of shares to withdraw
     */
    function beforeWithdraw(uint256 assets, uint256 shares) internal override {
        uint256 _totalAssets = totalAssets();
        if(_totalAssets < assets + MIN_ASSETS) revert InsufficientAssets();
        if(totalSupply < shares + MIN_SHARES) revert BelowMinShares();
        uint256 invBal = asset.balanceOf(address(this));
        if(assets > invBal) {
            uint256 withdrawAmount = assets - invBal + minBuffer;
            if(_totalAssets < withdrawAmount){
                invMarket.withdraw(assets - invBal);
            } else {
                invMarket.withdraw(withdrawAmount);
            }
        }
    }

    /**
     * @dev Calculates the total assets controlled by the contract.
     * Period revenue is distributed linearly over the following week.
     * @return The total assets in the contract.
     */
    function totalAssets() public view override returns (uint) {
        uint256 periodsSinceLastBuy = block.timestamp / period - revenueData.lastBuyPeriod;
        uint256 _lastPeriodRevenue = revenueData.lastPeriodRevenue;
        uint256 _periodRevenue = revenueData.periodRevenue;
        uint256 invBal = invEscrow.balance() + asset.balanceOf(address(this));
        if(periodsSinceLastBuy > 1){
            return invBal < MAX_ASSETS ? invBal : MAX_ASSETS;
        } else if(periodsSinceLastBuy == 1) {
            _lastPeriodRevenue = _periodRevenue;
            _periodRevenue = 0;
        }
        uint256 remainingLastRevenue = _lastPeriodRevenue * (period - block.timestamp % period) / period;
        uint256 lockedRevenue = remainingLastRevenue + _periodRevenue;
        uint256 actualAssets;
        if(invBal > lockedRevenue){
            actualAssets = invBal - lockedRevenue;
        }
        return actualAssets < MAX_ASSETS ? actualAssets : MAX_ASSETS;
    }

    function updatePeriodRevenue(uint96 newRevenue) internal {
        uint256 currentPeriod = block.timestamp / period;
        uint256 periodsSinceLastBuy = currentPeriod - revenueData.lastBuyPeriod;
        if(periodsSinceLastBuy > 1){
            revenueData.lastPeriodRevenue = 0;
            revenueData.periodRevenue = newRevenue;
            revenueData.lastBuyPeriod = uint64(currentPeriod);
        } else if(periodsSinceLastBuy == 1) {
            revenueData.lastPeriodRevenue = revenueData.periodRevenue;
            revenueData.periodRevenue = newRevenue;
            revenueData.lastBuyPeriod = uint64(currentPeriod);
        } else {
            revenueData.periodRevenue += newRevenue;
        }
    }

    /**
     * @dev Returns the current value of K, which is a weighted average between prevK and kData.targetK.
     * @return The current value of K.
     */
    function getK() public view returns (uint) {
        uint256 timeElapsed = block.timestamp - kData.lastKUpdate;
        if(timeElapsed > period) {
            return kData.targetK;
        }
        uint256 prevWeight = period - timeElapsed;
        return (prevK * prevWeight + kData.targetK * timeElapsed) / period;
    }

    /**
     * @dev Calculates the asset reserve based on the current DBR reserve.
     * @return The calculated asset reserve.
     */
    function getInvReserve() public view returns (uint) {
        return getK() / getDbrReserve();
    }

    /**
     * @dev Calculates the asset reserve for a given DBR reserve.
     * @param DBRReserve The DBR reserve value.
     * @return The calculated asset reserve.
     */
    function getInvReserve(uint256 DBRReserve) public view returns (uint) {
        return getK() / DBRReserve;
    }

    /**
     * @dev Returns the current DBR reserve as the sum of DBR balance and claimable DBR
     * @return The current DBR reserve.
     */
    function getDbrReserve() public view returns (uint) {
        return DBR.balanceOf(address(this)) + invEscrow.claimable();
    }

    /**
     * @dev Sets a new target K value.
     * @param _K The new target K value.
     */
    function setTargetK(uint256 _K) external onlyGov {
        if(_K < getDbrReserve()) revert KTooLow(_K, getDbrReserve());
        prevK = getK();
        kData.targetK = uint192(_K);
        kData.lastKUpdate = uint64(block.timestamp);
        emit SetTargetK(_K);
    }

    /**
     * @notice Set the min buffer
     * @dev Min buffer is the buffer of INV held by the sINV contract, which can be withdrawn much more cheaply than if they were staked
     * @param _minBuffer The new min buffer
     */
    function setMinBuffer(uint256 _minBuffer) external onlyGov {
        minBuffer = _minBuffer;
        emit SetMinBuffer(_minBuffer);
    }

    /**
     * @dev Allows users to buy DBR with asset.
     * WARNING: Never expose this directly to a UI as it's likely to cause a loss unless a transaction is executed immediately.
     * Instead use the sINVHelper function or custom smart contract code.
     * @param exactInvIn The exact amount of asset to spend.
     * @param exactDbrOut The exact amount of DBR to receive.
     * @param to The address that will receive the DBR.
     */
    function buyDBR(uint256 exactInvIn, uint256 exactDbrOut, address to) external {
        require(exactInvIn <= type(uint96).max, "EXCEED UINT96");
        uint256 DBRBalance = DBR.balanceOf(address(this));
        if(exactDbrOut > DBRBalance){
            invEscrow.claimDBR();
            DBRBalance = DBR.balanceOf(address(this));
        } else {
            DBRBalance += invEscrow.claimable(); 
        }
        uint256 k = getK();
        uint256 DBRReserve = DBRBalance - exactDbrOut;
        uint256 invReserve = k / DBRBalance + exactInvIn;
        if(invReserve * DBRReserve < k) revert Invariant();
        updatePeriodRevenue(uint96(exactInvIn));
        asset.transferFrom(msg.sender, address(this), exactInvIn);
        DBR.transfer(to, exactDbrOut);
        emit Buy(msg.sender, to, exactInvIn, exactDbrOut);
    }

    /**
     * @notice Sets a new depositLimit. Only callable by guardian.
     * @dev Deposit limit must always increase
     * @param _depositLimit The new deposit limit
     */
    function setDepositLimit(uint _depositLimit) external onlyGuardian {
        depositLimit = _depositLimit;
    }

    /**
     * @notice Sets the guardian that can increase the deposit limit. Only callable by governance.
     * @param _guardian The new guardian.
     */
    function setGuardian(address _guardian) external onlyGov {
        guardian = _guardian;
    }

    /**
     * @dev Sets a new pending governance address.
     * @param _gov The address of the new pending governance.
     */
    function setPendingGov(address _gov) external onlyGov {
        pendingGov = _gov;
    }

    /**
     * @dev Allows the pending governance to accept its role.
     */
    function acceptGov() external onlyPendingGov {
        gov = pendingGov;
        pendingGov = address(0);
    }

    /**
     * @dev Allows governance to sweep any ERC20 token from the contract.
     * @dev Excludes the ability to sweep DBR tokens.
     * @param token The address of the ERC20 token to sweep.
     * @param amount The amount of tokens to sweep.
     * @param to The recipient address of the swept tokens.
     */
    function sweep(address token, uint256 amount, address to) public onlyGov {
        if(address(DBR) == token ||
            address(asset) == token)
            revert UnauthorizedTokenWithdrawal();
        IERC20(token).transfer(to, amount);
    }
    
    /**
     * @notice Allows anyone to reapprove inv spending for invMarket
     */
    function reapprove() external {
        asset.approve(address(invMarket), type(uint).max);
    }
    

    event Buy(address indexed caller, address indexed to, uint256 exactInvIn, uint256 exactDbrOut);
    event SetTargetK(uint256 newTargetK);
    event SetMinBuffer(uint256 newMinBuffer);
}

File 2 of 5 : ERC4626.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";

/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol)
abstract contract ERC4626 is ERC20 {
    using SafeTransferLib for ERC20;
    using FixedPointMathLib for uint256;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);

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

    /*//////////////////////////////////////////////////////////////
                               IMMUTABLES
    //////////////////////////////////////////////////////////////*/

    ERC20 public immutable asset;

    constructor(
        ERC20 _asset,
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol, _asset.decimals()) {
        asset = _asset;
    }

    /*//////////////////////////////////////////////////////////////
                        DEPOSIT/WITHDRAWAL LOGIC
    //////////////////////////////////////////////////////////////*/

    function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
        // Check for rounding error since we round down in previewDeposit.
        require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");

        // Need to transfer before minting or ERC777s could reenter.
        asset.safeTransferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

        emit Deposit(msg.sender, receiver, assets, shares);

        afterDeposit(assets, shares);
    }

    function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
        assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.

        // Need to transfer before minting or ERC777s could reenter.
        asset.safeTransferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

        emit Deposit(msg.sender, receiver, assets, shares);

        afterDeposit(assets, shares);
    }

    function withdraw(
        uint256 assets,
        address receiver,
        address owner
    ) public virtual returns (uint256 shares) {
        shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.

        if (msg.sender != owner) {
            uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.

            if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
        }

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);

        asset.safeTransfer(receiver, assets);
    }

    function redeem(
        uint256 shares,
        address receiver,
        address owner
    ) public virtual returns (uint256 assets) {
        if (msg.sender != owner) {
            uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.

            if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
        }

        // Check for rounding error since we round down in previewRedeem.
        require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);

        asset.safeTransfer(receiver, assets);
    }

    /*//////////////////////////////////////////////////////////////
                            ACCOUNTING LOGIC
    //////////////////////////////////////////////////////////////*/

    function totalAssets() public view virtual returns (uint256);

    function convertToShares(uint256 assets) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
    }

    function convertToAssets(uint256 shares) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
    }

    function previewDeposit(uint256 assets) public view virtual returns (uint256) {
        return convertToShares(assets);
    }

    function previewMint(uint256 shares) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
    }

    function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
    }

    function previewRedeem(uint256 shares) public view virtual returns (uint256) {
        return convertToAssets(shares);
    }

    /*//////////////////////////////////////////////////////////////
                     DEPOSIT/WITHDRAWAL LIMIT LOGIC
    //////////////////////////////////////////////////////////////*/

    function maxDeposit(address) public view virtual returns (uint256) {
        return type(uint256).max;
    }

    function maxMint(address) public view virtual returns (uint256) {
        return type(uint256).max;
    }

    function maxWithdraw(address owner) public view virtual returns (uint256) {
        return convertToAssets(balanceOf[owner]);
    }

    function maxRedeem(address owner) public view virtual returns (uint256) {
        return balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                          INTERNAL HOOKS LOGIC
    //////////////////////////////////////////////////////////////*/

    function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}

    function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}

File 3 of 5 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 4 of 5 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 5 of 5 : FixedPointMathLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_inv","type":"address"},{"internalType":"address","name":"_invMarket","type":"address"},{"internalType":"address","name":"_gov","type":"address"},{"internalType":"address","name":"_guardian","type":"address"},{"internalType":"uint256","name":"_depositLimit","type":"uint256"},{"internalType":"uint256","name":"_K","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AboveDepositLimit","type":"error"},{"inputs":[],"name":"BelowMinShares","type":"error"},{"inputs":[],"name":"DepositLimitMustIncrease","type":"error"},{"inputs":[],"name":"InsufficientAssets","type":"error"},{"inputs":[],"name":"Invariant","type":"error"},{"inputs":[{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"KTooLow","type":"error"},{"inputs":[],"name":"OnlyGov","type":"error"},{"inputs":[],"name":"OnlyGuardian","type":"error"},{"inputs":[],"name":"OnlyPendingGov","type":"error"},{"inputs":[],"name":"UnauthorizedTokenWithdrawal","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"exactInvIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exactDbrOut","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMinBuffer","type":"uint256"}],"name":"SetMinBuffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTargetK","type":"uint256"}],"name":"SetTargetK","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DBR","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ASSETS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_ASSETS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_SHARES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"exactInvIn","type":"uint256"},{"internalType":"uint256","name":"exactDbrOut","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"buyDBR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDbrReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"DBRReserve","type":"uint256"}],"name":"getInvReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInvReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"invEscrow","outputs":[{"internalType":"contract IInvEscrow","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"invMarket","outputs":[{"internalType":"contract IMarket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kData","outputs":[{"internalType":"uint192","name":"targetK","type":"uint192"},{"internalType":"uint64","name":"lastKUpdate","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastKUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPeriodRevenue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingGov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodRevenue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"prevK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reapprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revenueData","outputs":[{"internalType":"uint96","name":"periodRevenue","type":"uint96"},{"internalType":"uint96","name":"lastPeriodRevenue","type":"uint96"},{"internalType":"uint64","name":"lastBuyPeriod","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositLimit","type":"uint256"}],"name":"setDepositLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minBuffer","type":"uint256"}],"name":"setMinBuffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gov","type":"address"}],"name":"setPendingGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_K","type":"uint256"}],"name":"setTargetK","outputs":[],"stateMutability":"nonpayable","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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

61016060405234801562000011575f80fd5b506040516200322138038062003221833981016040819052620000349162000417565b856040518060400160405280600a81526020016929ba30b5b2b21024b73b60b11b8152506040518060400160405280600481526020016339a4a72b60e11b8152508181846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000b4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620000da919062000482565b5f620000e784826200054b565b506001620000f683826200054b565b5060ff81166080524660a0526200010c62000361565b60c0525050506001600160a01b0390921660e05250505f81900362000152576040516308b6d51360e31b8152600481018290526001602482015260440160405180910390fd5b60405163b6b55f2560e01b81525f60048201526001600160a01b0386169063b6b55f25906024015f604051808303815f87803b15801562000191575f80fd5b505af1158015620001a4573d5f803e3d5ffd5b50506040516323b9185960e11b81523060048201526001600160a01b038816925063477230b291506024016020604051808303815f875af1158015620001ec573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000212919062000613565b6001600160a01b039081166101205285166101008190526040805163c7ed69cd60e01b8152905163c7ed69cd9160048082019260209290919082900301815f875af115801562000264573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200028a919062000613565b6001600160a01b0390811661014052600980546001600160a01b031990811687841617909155600a8054909116858316179055600880546001600160c01b0319166001600160c01b0384161790556006839055600d82905560e0516101005160405163095ea7b360e01b815290831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af11580156200032e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200035491906200062f565b50505050505050620006ca565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f60405162000393919062000650565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b80516001600160a01b038116811462000412575f80fd5b919050565b5f805f805f8060c087890312156200042d575f80fd5b6200043887620003fb565b95506200044860208801620003fb565b94506200045860408801620003fb565b93506200046860608801620003fb565b92506080870151915060a087015190509295509295509295565b5f6020828403121562000493575f80fd5b815160ff81168114620004a4575f80fd5b9392505050565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680620004d457607f821691505b602082108103620004f357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000546575f81815260208120601f850160051c81016020861015620005215750805b601f850160051c820191505b8181101562000542578281556001016200052d565b5050505b505050565b81516001600160401b03811115620005675762000567620004ab565b6200057f81620005788454620004bf565b84620004f9565b602080601f831160018114620005b5575f84156200059d5750858301515b5f19600386901b1c1916600185901b17855562000542565b5f85815260208120601f198616915b82811015620005e557888601518255948401946001909101908401620005c4565b50858210156200060357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f6020828403121562000624575f80fd5b620004a482620003fb565b5f6020828403121562000640575f80fd5b81518015158114620004a4575f80fd5b5f8083546200065f81620004bf565b600182811680156200067a57600181146200069057620006be565b60ff1984168752821515830287019450620006be565b875f526020805f205f5b85811015620006b55781548a8201529084019082016200069a565b50505082870194505b50929695505050505050565b60805160a05160c05160e051610100516101205161014051612a64620007bd5f395f8181610607015281816110b7015281816112e8015281816113e4015281816116090152611cd301525f81816108b4015281816109eb0152818161102401528181611365015261146001525f818161049c01528181611c00015281816121840152818161243301526124c801525f81816105580152818161098001528181610e8e0152818161119801528181611570015281816117c50152818161190c01528181611c2f01528181611d0e01528181612105015261238b01525f610e0701525f610dd201525f6105170152612a645ff3fe608060405234801561000f575f80fd5b506004361061039e575f3560e01c80637bc6729b116101ea578063c6e6f59211610114578063dd62ed3e116100a9578063ee39e7a011610079578063ee39e7a0146108df578063ef78d4fd146108e7578063ef8b30f7146108f1578063efdf0bb014610904575f80fd5b8063dd62ed3e1461087d578063e1e59849146108a7578063eba872a7146108af578063ecf70858146108d6575f80fd5b8063d505accf116100e4578063d505accf14610827578063d818f23a1461083a578063d905777e14610842578063dc2c256f1461086a575f80fd5b8063c6e6f592146107d6578063cd153866146107e9578063ce96cb7714610801578063d0926e2614610814575f80fd5b8063a08b06db1161018a578063b460af941161015a578063b460af941461079d578063ba087652146107b0578063bdc8144b146107c3578063c63d75b61461057a575f80fd5b8063a08b06db1461075b578063a9059cbb14610764578063b23adea614610777578063b3d7f6b91461078a575f80fd5b80638a0dac4a116101c55780638a0dac4a146106cb57806394bf804d146106de57806394f5c9dc146106f157806395d89b4114610753575f80fd5b80637bc6729b1461069c5780637ecebe00146106a457806387a64c01146106c3575f80fd5b8063260a220b116102cb5780634cdad5061161026b57806370a082311161023b57806370a082311461063c5780637153a20d1461065b57806376b1d08f1461066e578063781f56de14610683575f80fd5b80634cdad506146105a1578063563e1709146105b45780636d124715146106025780636e553f6514610629575f80fd5b80633644e515116102a65780633644e5151461054b57806338d52e0f14610553578063402d267d1461057a578063452a93201461058e575f80fd5b8063260a220b146104f35780632b8dbaa714610501578063313ce56714610512575f80fd5b806312d43a51116103415780631d2fa930116103115780631d2fa930146104975780631fcd3080146104be57806323b872dd146104cd57806325240810146104e0575f80fd5b806312d43a5114610439578063140c67b21461046457806318160ddd1461047d5780631cd1cf6414610486575f80fd5b8063084219e81161037c578063084219e8146103e5578063095ea7b3146103fa5780630a28a4771461041d57806311e5ff3f14610430575f80fd5b806301e1d114146103a257806306fdde03146103bd57806307a2d13a146103d2575b5f80fd5b6103aa610917565b6040519081526020015b60405180910390f35b6103c5610b4c565b6040516103b4919061260a565b6103aa6103e0366004612655565b610bd7565b6103f86103f3366004612655565b610c03565b005b61040d610408366004612687565b610c6a565b60405190151581526020016103b4565b6103aa61042b366004612655565b610cd6565b6103aa600c5481565b60095461044c906001600160a01b031681565b6040516001600160a01b0390911681526020016103b4565b600754600160c01b900467ffffffffffffffff166103aa565b6103aa60025481565b6008546001600160c01b03166103aa565b61044c7f000000000000000000000000000000000000000000000000000000000000000081565b6103aa670de0b6b3a764000081565b61040d6104db3660046126af565b610cf5565b600b5461044c906001600160a01b031681565b6103aa662386f26fc1000081565b6007546001600160601b03166103aa565b6105397f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016103b4565b6103aa610dcf565b61044c7f000000000000000000000000000000000000000000000000000000000000000081565b6103aa6105883660046126e8565b505f1990565b600a5461044c906001600160a01b031681565b6103aa6105af366004612655565b610e29565b6008546105da906001600160c01b03811690600160c01b900467ffffffffffffffff1682565b604080516001600160c01b03909316835267ffffffffffffffff9091166020830152016103b4565b61044c7f000000000000000000000000000000000000000000000000000000000000000081565b6103aa610637366004612701565b610e33565b6103aa61064a3660046126e8565b60036020525f908152604090205481565b6103f8610669366004612655565b610f10565b6103aa6d04ee2d6d415b85acef810000000081565b600854600160c01b900467ffffffffffffffff166103aa565b6103f8610fcf565b6103aa6106b23660046126e8565b60056020525f908152604090205481565b6103aa611021565b6103f86106d93660046126e8565b611132565b6103aa6106ec366004612701565b61117f565b600754610723906001600160601b0380821691600160601b810490911690600160c01b900467ffffffffffffffff1683565b604080516001600160601b03948516815293909216602084015267ffffffffffffffff16908201526060016103b4565b6103c561121a565b6103aa600d5481565b61040d610772366004612687565b611227565b6103f861078536600461272b565b61128a565b6103aa610798366004612655565b6116c4565b6103aa6107ab36600461275d565b6116e2565b6103aa6107be36600461275d565b6117ec565b6103f86107d1366004612655565b611933565b6103aa6107e4366004612655565b611963565b600754600160601b90046001600160601b03166103aa565b6103aa61080f3660046126e8565b611982565b6103aa610822366004612655565b6119a3565b6103f861083536600461278d565b6119b7565b6103f8611be9565b6103aa6108503660046126e8565b6001600160a01b03165f9081526003602052604090205490565b6103f86108783660046127fa565b611c9c565b6103aa61088b36600461282a565b600460209081525f928352604080842090915290825290205481565b6103aa611dcc565b61044c7f000000000000000000000000000000000000000000000000000000000000000081565b6103aa60065481565b6103aa611de7565b6103aa62093a8081565b6103aa6108ff366004612655565b611e7d565b6103f86109123660046126e8565b611e87565b6007545f908190600160c01b900467ffffffffffffffff1661093c62093a804261287a565b610946919061288d565b6007546040516370a0823160e01b81523060048201529192506001600160601b03600160601b82048116929116905f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156109c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e991906128a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b69ef8a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a45573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6991906128a0565b610a7391906128b7565b90506001841115610ab2576d04ee2d6d415b85acef81000000008110610aa7576d04ee2d6d415b85acef8100000000610aa9565b805b94505050505090565b83600103610ac0579091505f905b5f62093a80610acf81426128ca565b610adc9062093a8061288d565b610ae690866128dd565b610af0919061287a565b90505f610afd84836128b7565b90505f81841115610b1557610b12828561288d565b90505b6d04ee2d6d415b85acef81000000008110610b3e576d04ee2d6d415b85acef8100000000610b40565b805b97505050505050505090565b5f8054610b58906128f4565b80601f0160208091040260200160405190810160405280929190818152602001828054610b84906128f4565b8015610bcf5780601f10610ba657610100808354040283529160200191610bcf565b820191905f5260205f20905b815481529060010190602001808311610bb257829003601f168201915b505050505081565b6002545f908015610bfa57610bf5610bed610917565b849083611ed4565b610bfc565b825b9392505050565b6009546001600160a01b03163314610c2e57604051639097750360e01b815260040160405180910390fd5b600c8190556040518181527fc4ac55c04bc11a90cd33d7e0088129e6985b44c5d85a9f0acdeae027bfeeb50b906020015b60405180910390a150565b335f8181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610cc49086815260200190565b60405180910390a35060015b92915050565b6002545f908015610bfa57610bf581610ced610917565b859190611eef565b6001600160a01b0383165f9081526004602090815260408083203384529091528120545f198114610d4e57610d2a838261288d565b6001600160a01b0386165f9081526004602090815260408083203384529091529020555b6001600160a01b0385165f9081526003602052604081208054859290610d7590849061288d565b90915550506001600160a01b038085165f81815260036020526040908190208054870190555190918716905f80516020612a0f83398151915290610dbc9087815260200190565b60405180910390a3506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610e0457610dff611f12565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b5f610cd082610bd7565b5f610e3d83611e7d565b9050805f03610e815760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f53484152455360a81b60448201526064015b60405180910390fd5b610eb66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086611faa565b610ec08282612042565b60408051848152602081018390526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610cd08382612099565b6009546001600160a01b03163314610f3b57604051639097750360e01b815260040160405180910390fd5b610f43611021565b811015610f755780610f53611021565b6040516308b6d51360e31b815260048101929092526024820152604401610e78565b610f7d611de7565b600d556001600160c01b038116600160c01b4267ffffffffffffffff1602176008556040518181527f1fcc9c54f3c93fdac0b3691c0d36d64d222420c5ca56c6f1f28b43ab09cb8b7b90602001610c5f565b600b546001600160a01b03163314610ffa576040516307b70d3960e11b815260040160405180910390fd5b600b8054600980546001600160a01b03199081166001600160a01b03841617909155169055565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af38d7576040518163ffffffff1660e01b8152600401602060405180830381865afa15801561107e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110a291906128a0565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611104573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112891906128a0565b610dff91906128b7565b6009546001600160a01b0316331461115d57604051639097750360e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b5f611189836116c4565b90506111c06001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611faa565b6111ca8284612042565b60408051828152602081018590526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610cd08184612099565b60018054610b58906128f4565b335f9081526003602052604081208054839190839061124790849061288d565b90915550506001600160a01b0383165f81815260036020526040908190208054850190555133905f80516020612a0f83398151915290610cc49086815260200190565b6001600160601b038311156112d15760405162461bcd60e51b815260206004820152600d60248201526c22ac21a2a2a2102aa4a72a1c9b60991b6044820152606401610e78565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611335573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135991906128a0565b90508083111561145e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c93f304e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156113bb575f80fd5b505af11580156113cd573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506370a082319150602401602060405180830381865afa158015611433573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061145791906128a0565b90506114eb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663af38d7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114de91906128a0565b6114e890826128b7565b90505b5f6114f4611de7565b90505f611501858461288d565b90505f8661150f858561287a565b61151991906128b7565b90508261152683836128dd565b101561154557604051633876c51d60e11b815260040160405180910390fd5b61154e87612210565b6040516323b872dd60e01b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af11580156115be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e2919061292c565b5060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018890527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af115801561164f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611673919061292c565b5060408051888152602081018890526001600160a01b0387169133917f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e91015b60405180910390a350505050505050565b6002545f908015610bfa57610bf56116da610917565b849083611eef565b5f6116ec84610cd6565b9050336001600160a01b03831614611759576001600160a01b0382165f9081526004602090815260408083203384529091529020545f19811461175757611733828261288d565b6001600160a01b0384165f9081526004602090815260408083203384529091529020555b505b6117638482612304565b61176d828261252e565b60408051858152602081018390526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4610bfc6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016848661258d565b5f336001600160a01b03831614611858576001600160a01b0382165f9081526004602090815260408083203384529091529020545f19811461185657611832858261288d565b6001600160a01b0384165f9081526004602090815260408083203384529091529020555b505b61186184610e29565b9050805f036118a05760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f41535345545360a81b6044820152606401610e78565b6118aa8185612304565b6118b4828561252e565b60408051828152602081018690526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4610bfc6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016848361258d565b600a546001600160a01b0316331461195e57604051636570ecab60e11b815260040160405180910390fd5b600655565b6002545f908015610bfa57610bf58161197a610917565b859190611ed4565b6001600160a01b0381165f90815260036020526040812054610cd090610bd7565b5f816119ad611de7565b610cd0919061287a565b42841015611a075760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610e78565b5f6001611a12610dcf565b6001600160a01b038a81165f8181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f1981840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611b1a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615801590611b505750876001600160a01b0316816001600160a01b0316145b611b8d5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606401610e78565b6001600160a01b039081165f9081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591016116b3565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f1960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303815f875af1158015611c75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c99919061292c565b50565b6009546001600160a01b03163314611cc757604051639097750360e01b815260040160405180910390fd5b826001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480611d385750826001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316145b15611d5657604051631b16270360e01b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b0382811660048301526024820184905284169063a9059cbb906044016020604051808303815f875af1158015611da2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc6919061292c565b50505050565b5f611dd5611021565b611ddd611de7565b610dff919061287a565b6008545f908190611e0990600160c01b900467ffffffffffffffff164261288d565b905062093a80811115611e275750506008546001600160c01b031690565b5f611e358262093a8061288d565b60085490915062093a8090611e549084906001600160c01b03166128dd565b82600d54611e6291906128dd565b611e6c91906128b7565b611e76919061287a565b9250505090565b5f610cd082611963565b6009546001600160a01b03163314611eb257604051639097750360e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f825f190484118302158202611ee8575f80fd5b5091020490565b5f825f190484118302158202611f03575f80fd5b50910281810615159190040190565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f604051611f42919061294b565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f51141617169150508061203b5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610e78565b5050505050565b8060025f82825461205391906128b7565b90915550506001600160a01b0382165f818152600360209081526040808320805486019055518481525f80516020612a0f83398151915291015b60405180910390a35050565b670de0b6b3a764000060025410156120c45760405163b6af011960e01b815260040160405180910390fd5b6006546120cf610917565b11156120ee576040516301d8a97b60e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612152573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217691906128a0565b9050600c5481111561220b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b6b55f25600c54836121bf919061288d565b6040518263ffffffff1660e01b81526004016121dd91815260200190565b5f604051808303815f87803b1580156121f4575f80fd5b505af1158015612206573d5f803e3d5ffd5b505050505b505050565b5f61221e62093a804261287a565b6007549091505f9061224190600160c01b900467ffffffffffffffff168361288d565b905060018111156122705767ffffffffffffffff8216600160c01b026001600160601b03841617600755505050565b806001036122be576007805467ffffffffffffffff8416600160c01b02600160601b6001600160601b03928316026bffffffffffffffffffffffff60601b1691861691909117179055505050565b600780548491905f906122db9084906001600160601b03166129e7565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550505050565b5f61230d610917565b9050612320662386f26fc10000846128b7565b811015612340576040516396d8043360e01b815260040160405180910390fd5b612352670de0b6b3a7640000836128b7565b60025410156123745760405163b6af011960e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156123d8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123fc91906128a0565b905080841115611dc657600c545f90612415838761288d565b61241f91906128b7565b9050808310156124b2576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016632e1a7d4d612462848861288d565b6040518263ffffffff1660e01b815260040161248091815260200190565b5f604051808303815f87803b158015612497575f80fd5b505af11580156124a9573d5f803e3d5ffd5b5050505061203b565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015612511575f80fd5b505af1158015612523573d5f803e3d5ffd5b505050505050505050565b6001600160a01b0382165f908152600360205260408120805483929061255590849061288d565b90915550506002805482900390556040518181525f906001600160a01b038416905f80516020612a0f8339815191529060200161208d565b5f60405163a9059cbb60e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080611dc65760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610e78565b5f6020808352835180828501525f5b8181101561263557858101830151858201604001528201612619565b505f604082860101526040601f19601f8301168501019250505092915050565b5f60208284031215612665575f80fd5b5035919050565b80356001600160a01b0381168114612682575f80fd5b919050565b5f8060408385031215612698575f80fd5b6126a18361266c565b946020939093013593505050565b5f805f606084860312156126c1575f80fd5b6126ca8461266c565b92506126d86020850161266c565b9150604084013590509250925092565b5f602082840312156126f8575f80fd5b610bfc8261266c565b5f8060408385031215612712575f80fd5b823591506127226020840161266c565b90509250929050565b5f805f6060848603121561273d575f80fd5b83359250602084013591506127546040850161266c565b90509250925092565b5f805f6060848603121561276f575f80fd5b8335925061277f6020850161266c565b91506127546040850161266c565b5f805f805f805f60e0888a0312156127a3575f80fd5b6127ac8861266c565b96506127ba6020890161266c565b95506040880135945060608801359350608088013560ff811681146127dd575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121561280c575f80fd5b6128158461266c565b9250602084013591506127546040850161266c565b5f806040838503121561283b575f80fd5b6128448361266c565b91506127226020840161266c565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261288857612888612852565b500490565b81810381811115610cd057610cd0612866565b5f602082840312156128b0575f80fd5b5051919050565b80820180821115610cd057610cd0612866565b5f826128d8576128d8612852565b500690565b8082028115828204841417610cd057610cd0612866565b600181811c9082168061290857607f821691505b60208210810361292657634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561293c575f80fd5b81518015158114610bfc575f80fd5b5f80835481600182811c91508083168061296657607f831692505b6020808410820361298557634e487b7160e01b86526022600452602486fd5b81801561299957600181146129ae576129d9565b60ff19861689528415158502890196506129d9565b5f8a8152602090205f5b868110156129d15781548b8201529085019083016129b8565b505084890196505b509498975050505050505050565b6001600160601b03818116838216019080821115612a0757612a07612866565b509291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122044b93e02b1a4f6715ea137e1c03f04dd8442eecbaffecd723f158b5d012f7a5464736f6c6343000815003300000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb68000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b000000000000000000000000926df14a23be491164dcf93f4c468a50ef659d5b0000000000000000000000004b6c63e6a94ef26e2df60b89372db2d8e211f1b700000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000008e58532b0a48be0067ccbc8dd80000000000

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061039e575f3560e01c80637bc6729b116101ea578063c6e6f59211610114578063dd62ed3e116100a9578063ee39e7a011610079578063ee39e7a0146108df578063ef78d4fd146108e7578063ef8b30f7146108f1578063efdf0bb014610904575f80fd5b8063dd62ed3e1461087d578063e1e59849146108a7578063eba872a7146108af578063ecf70858146108d6575f80fd5b8063d505accf116100e4578063d505accf14610827578063d818f23a1461083a578063d905777e14610842578063dc2c256f1461086a575f80fd5b8063c6e6f592146107d6578063cd153866146107e9578063ce96cb7714610801578063d0926e2614610814575f80fd5b8063a08b06db1161018a578063b460af941161015a578063b460af941461079d578063ba087652146107b0578063bdc8144b146107c3578063c63d75b61461057a575f80fd5b8063a08b06db1461075b578063a9059cbb14610764578063b23adea614610777578063b3d7f6b91461078a575f80fd5b80638a0dac4a116101c55780638a0dac4a146106cb57806394bf804d146106de57806394f5c9dc146106f157806395d89b4114610753575f80fd5b80637bc6729b1461069c5780637ecebe00146106a457806387a64c01146106c3575f80fd5b8063260a220b116102cb5780634cdad5061161026b57806370a082311161023b57806370a082311461063c5780637153a20d1461065b57806376b1d08f1461066e578063781f56de14610683575f80fd5b80634cdad506146105a1578063563e1709146105b45780636d124715146106025780636e553f6514610629575f80fd5b80633644e515116102a65780633644e5151461054b57806338d52e0f14610553578063402d267d1461057a578063452a93201461058e575f80fd5b8063260a220b146104f35780632b8dbaa714610501578063313ce56714610512575f80fd5b806312d43a51116103415780631d2fa930116103115780631d2fa930146104975780631fcd3080146104be57806323b872dd146104cd57806325240810146104e0575f80fd5b806312d43a5114610439578063140c67b21461046457806318160ddd1461047d5780631cd1cf6414610486575f80fd5b8063084219e81161037c578063084219e8146103e5578063095ea7b3146103fa5780630a28a4771461041d57806311e5ff3f14610430575f80fd5b806301e1d114146103a257806306fdde03146103bd57806307a2d13a146103d2575b5f80fd5b6103aa610917565b6040519081526020015b60405180910390f35b6103c5610b4c565b6040516103b4919061260a565b6103aa6103e0366004612655565b610bd7565b6103f86103f3366004612655565b610c03565b005b61040d610408366004612687565b610c6a565b60405190151581526020016103b4565b6103aa61042b366004612655565b610cd6565b6103aa600c5481565b60095461044c906001600160a01b031681565b6040516001600160a01b0390911681526020016103b4565b600754600160c01b900467ffffffffffffffff166103aa565b6103aa60025481565b6008546001600160c01b03166103aa565b61044c7f000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b81565b6103aa670de0b6b3a764000081565b61040d6104db3660046126af565b610cf5565b600b5461044c906001600160a01b031681565b6103aa662386f26fc1000081565b6007546001600160601b03166103aa565b6105397f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff90911681526020016103b4565b6103aa610dcf565b61044c7f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6881565b6103aa6105883660046126e8565b505f1990565b600a5461044c906001600160a01b031681565b6103aa6105af366004612655565b610e29565b6008546105da906001600160c01b03811690600160c01b900467ffffffffffffffff1682565b604080516001600160c01b03909316835267ffffffffffffffff9091166020830152016103b4565b61044c7f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d71081565b6103aa610637366004612701565b610e33565b6103aa61064a3660046126e8565b60036020525f908152604090205481565b6103f8610669366004612655565b610f10565b6103aa6d04ee2d6d415b85acef810000000081565b600854600160c01b900467ffffffffffffffff166103aa565b6103f8610fcf565b6103aa6106b23660046126e8565b60056020525f908152604090205481565b6103aa611021565b6103f86106d93660046126e8565b611132565b6103aa6106ec366004612701565b61117f565b600754610723906001600160601b0380821691600160601b810490911690600160c01b900467ffffffffffffffff1683565b604080516001600160601b03948516815293909216602084015267ffffffffffffffff16908201526060016103b4565b6103c561121a565b6103aa600d5481565b61040d610772366004612687565b611227565b6103f861078536600461272b565b61128a565b6103aa610798366004612655565b6116c4565b6103aa6107ab36600461275d565b6116e2565b6103aa6107be36600461275d565b6117ec565b6103f86107d1366004612655565b611933565b6103aa6107e4366004612655565b611963565b600754600160601b90046001600160601b03166103aa565b6103aa61080f3660046126e8565b611982565b6103aa610822366004612655565b6119a3565b6103f861083536600461278d565b6119b7565b6103f8611be9565b6103aa6108503660046126e8565b6001600160a01b03165f9081526003602052604090205490565b6103f86108783660046127fa565b611c9c565b6103aa61088b36600461282a565b600460209081525f928352604080842090915290825290205481565b6103aa611dcc565b61044c7f0000000000000000000000005d2062751a100b384215af7dbacd49398d12094381565b6103aa60065481565b6103aa611de7565b6103aa62093a8081565b6103aa6108ff366004612655565b611e7d565b6103f86109123660046126e8565b611e87565b6007545f908190600160c01b900467ffffffffffffffff1661093c62093a804261287a565b610946919061288d565b6007546040516370a0823160e01b81523060048201529192506001600160601b03600160601b82048116929116905f906001600160a01b037f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6816906370a0823190602401602060405180830381865afa1580156109c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e991906128a0565b7f0000000000000000000000005d2062751a100b384215af7dbacd49398d1209436001600160a01b031663b69ef8a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a45573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6991906128a0565b610a7391906128b7565b90506001841115610ab2576d04ee2d6d415b85acef81000000008110610aa7576d04ee2d6d415b85acef8100000000610aa9565b805b94505050505090565b83600103610ac0579091505f905b5f62093a80610acf81426128ca565b610adc9062093a8061288d565b610ae690866128dd565b610af0919061287a565b90505f610afd84836128b7565b90505f81841115610b1557610b12828561288d565b90505b6d04ee2d6d415b85acef81000000008110610b3e576d04ee2d6d415b85acef8100000000610b40565b805b97505050505050505090565b5f8054610b58906128f4565b80601f0160208091040260200160405190810160405280929190818152602001828054610b84906128f4565b8015610bcf5780601f10610ba657610100808354040283529160200191610bcf565b820191905f5260205f20905b815481529060010190602001808311610bb257829003601f168201915b505050505081565b6002545f908015610bfa57610bf5610bed610917565b849083611ed4565b610bfc565b825b9392505050565b6009546001600160a01b03163314610c2e57604051639097750360e01b815260040160405180910390fd5b600c8190556040518181527fc4ac55c04bc11a90cd33d7e0088129e6985b44c5d85a9f0acdeae027bfeeb50b906020015b60405180910390a150565b335f8181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610cc49086815260200190565b60405180910390a35060015b92915050565b6002545f908015610bfa57610bf581610ced610917565b859190611eef565b6001600160a01b0383165f9081526004602090815260408083203384529091528120545f198114610d4e57610d2a838261288d565b6001600160a01b0386165f9081526004602090815260408083203384529091529020555b6001600160a01b0385165f9081526003602052604081208054859290610d7590849061288d565b90915550506001600160a01b038085165f81815260036020526040908190208054870190555190918716905f80516020612a0f83398151915290610dbc9087815260200190565b60405180910390a3506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000014614610e0457610dff611f12565b905090565b507f8d815ddb6b5e2f83ce08f3938845dbfb205a99747e087b60b1a20afe981d2d4b90565b5f610cd082610bd7565b5f610e3d83611e7d565b9050805f03610e815760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f53484152455360a81b60448201526064015b60405180910390fd5b610eb66001600160a01b037f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6816333086611faa565b610ec08282612042565b60408051848152602081018390526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610cd08382612099565b6009546001600160a01b03163314610f3b57604051639097750360e01b815260040160405180910390fd5b610f43611021565b811015610f755780610f53611021565b6040516308b6d51360e31b815260048101929092526024820152604401610e78565b610f7d611de7565b600d556001600160c01b038116600160c01b4267ffffffffffffffff1602176008556040518181527f1fcc9c54f3c93fdac0b3691c0d36d64d222420c5ca56c6f1f28b43ab09cb8b7b90602001610c5f565b600b546001600160a01b03163314610ffa576040516307b70d3960e11b815260040160405180910390fd5b600b8054600980546001600160a01b03199081166001600160a01b03841617909155169055565b5f7f0000000000000000000000005d2062751a100b384215af7dbacd49398d1209436001600160a01b031663af38d7576040518163ffffffff1660e01b8152600401602060405180830381865afa15801561107e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110a291906128a0565b6040516370a0823160e01b81523060048201527f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d7106001600160a01b0316906370a0823190602401602060405180830381865afa158015611104573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112891906128a0565b610dff91906128b7565b6009546001600160a01b0316331461115d57604051639097750360e01b815260040160405180910390fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b5f611189836116c4565b90506111c06001600160a01b037f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6816333084611faa565b6111ca8284612042565b60408051828152602081018590526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610cd08184612099565b60018054610b58906128f4565b335f9081526003602052604081208054839190839061124790849061288d565b90915550506001600160a01b0383165f81815260036020526040908190208054850190555133905f80516020612a0f83398151915290610cc49086815260200190565b6001600160601b038311156112d15760405162461bcd60e51b815260206004820152600d60248201526c22ac21a2a2a2102aa4a72a1c9b60991b6044820152606401610e78565b6040516370a0823160e01b81523060048201525f907f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d7106001600160a01b0316906370a0823190602401602060405180830381865afa158015611335573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135991906128a0565b90508083111561145e577f0000000000000000000000005d2062751a100b384215af7dbacd49398d1209436001600160a01b031663c93f304e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156113bb575f80fd5b505af11580156113cd573d5f803e3d5ffd5b50506040516370a0823160e01b81523060048201527f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d7106001600160a01b031692506370a082319150602401602060405180830381865afa158015611433573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061145791906128a0565b90506114eb565b7f0000000000000000000000005d2062751a100b384215af7dbacd49398d1209436001600160a01b031663af38d7576040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114de91906128a0565b6114e890826128b7565b90505b5f6114f4611de7565b90505f611501858461288d565b90505f8661150f858561287a565b61151991906128b7565b90508261152683836128dd565b101561154557604051633876c51d60e11b815260040160405180910390fd5b61154e87612210565b6040516323b872dd60e01b8152336004820152306024820152604481018890527f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb686001600160a01b0316906323b872dd906064016020604051808303815f875af11580156115be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e2919061292c565b5060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018890527f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d710169063a9059cbb906044016020604051808303815f875af115801561164f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611673919061292c565b5060408051888152602081018890526001600160a01b0387169133917f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e91015b60405180910390a350505050505050565b6002545f908015610bfa57610bf56116da610917565b849083611eef565b5f6116ec84610cd6565b9050336001600160a01b03831614611759576001600160a01b0382165f9081526004602090815260408083203384529091529020545f19811461175757611733828261288d565b6001600160a01b0384165f9081526004602090815260408083203384529091529020555b505b6117638482612304565b61176d828261252e565b60408051858152602081018390526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4610bfc6001600160a01b037f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6816848661258d565b5f336001600160a01b03831614611858576001600160a01b0382165f9081526004602090815260408083203384529091529020545f19811461185657611832858261288d565b6001600160a01b0384165f9081526004602090815260408083203384529091529020555b505b61186184610e29565b9050805f036118a05760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f41535345545360a81b6044820152606401610e78565b6118aa8185612304565b6118b4828561252e565b60408051828152602081018690526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a4610bfc6001600160a01b037f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb6816848361258d565b600a546001600160a01b0316331461195e57604051636570ecab60e11b815260040160405180910390fd5b600655565b6002545f908015610bfa57610bf58161197a610917565b859190611ed4565b6001600160a01b0381165f90815260036020526040812054610cd090610bd7565b5f816119ad611de7565b610cd0919061287a565b42841015611a075760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610e78565b5f6001611a12610dcf565b6001600160a01b038a81165f8181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f1981840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611b1a573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811615801590611b505750876001600160a01b0316816001600160a01b0316145b611b8d5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606401610e78565b6001600160a01b039081165f9081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591016116b3565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b811660048301525f1960248301527f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb68169063095ea7b3906044016020604051808303815f875af1158015611c75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c99919061292c565b50565b6009546001600160a01b03163314611cc757604051639097750360e01b815260040160405180910390fd5b826001600160a01b03167f000000000000000000000000ad038eb671c44b853887a7e32528fab35dc5d7106001600160a01b03161480611d385750826001600160a01b03167f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb686001600160a01b0316145b15611d5657604051631b16270360e01b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b0382811660048301526024820184905284169063a9059cbb906044016020604051808303815f875af1158015611da2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc6919061292c565b50505050565b5f611dd5611021565b611ddd611de7565b610dff919061287a565b6008545f908190611e0990600160c01b900467ffffffffffffffff164261288d565b905062093a80811115611e275750506008546001600160c01b031690565b5f611e358262093a8061288d565b60085490915062093a8090611e549084906001600160c01b03166128dd565b82600d54611e6291906128dd565b611e6c91906128b7565b611e76919061287a565b9250505090565b5f610cd082611963565b6009546001600160a01b03163314611eb257604051639097750360e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f825f190484118302158202611ee8575f80fd5b5091020490565b5f825f190484118302158202611f03575f80fd5b50910281810615159190040190565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f604051611f42919061294b565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f6040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260205f6064835f8a5af13d15601f3d1160015f51141617169150508061203b5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610e78565b5050505050565b8060025f82825461205391906128b7565b90915550506001600160a01b0382165f818152600360209081526040808320805486019055518481525f80516020612a0f83398151915291015b60405180910390a35050565b670de0b6b3a764000060025410156120c45760405163b6af011960e01b815260040160405180910390fd5b6006546120cf610917565b11156120ee576040516301d8a97b60e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb686001600160a01b0316906370a0823190602401602060405180830381865afa158015612152573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217691906128a0565b9050600c5481111561220b577f000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b6001600160a01b031663b6b55f25600c54836121bf919061288d565b6040518263ffffffff1660e01b81526004016121dd91815260200190565b5f604051808303815f87803b1580156121f4575f80fd5b505af1158015612206573d5f803e3d5ffd5b505050505b505050565b5f61221e62093a804261287a565b6007549091505f9061224190600160c01b900467ffffffffffffffff168361288d565b905060018111156122705767ffffffffffffffff8216600160c01b026001600160601b03841617600755505050565b806001036122be576007805467ffffffffffffffff8416600160c01b02600160601b6001600160601b03928316026bffffffffffffffffffffffff60601b1691861691909117179055505050565b600780548491905f906122db9084906001600160601b03166129e7565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550505050565b5f61230d610917565b9050612320662386f26fc10000846128b7565b811015612340576040516396d8043360e01b815260040160405180910390fd5b612352670de0b6b3a7640000836128b7565b60025410156123745760405163b6af011960e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f907f00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb686001600160a01b0316906370a0823190602401602060405180830381865afa1580156123d8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123fc91906128a0565b905080841115611dc657600c545f90612415838761288d565b61241f91906128b7565b9050808310156124b2576001600160a01b037f000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b16632e1a7d4d612462848861288d565b6040518263ffffffff1660e01b815260040161248091815260200190565b5f604051808303815f87803b158015612497575f80fd5b505af11580156124a9573d5f803e3d5ffd5b5050505061203b565b604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b6001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015612511575f80fd5b505af1158015612523573d5f803e3d5ffd5b505050505050505050565b6001600160a01b0382165f908152600360205260408120805483929061255590849061288d565b90915550506002805482900390556040518181525f906001600160a01b038416905f80516020612a0f8339815191529060200161208d565b5f60405163a9059cbb60e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f511416171691505080611dc65760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610e78565b5f6020808352835180828501525f5b8181101561263557858101830151858201604001528201612619565b505f604082860101526040601f19601f8301168501019250505092915050565b5f60208284031215612665575f80fd5b5035919050565b80356001600160a01b0381168114612682575f80fd5b919050565b5f8060408385031215612698575f80fd5b6126a18361266c565b946020939093013593505050565b5f805f606084860312156126c1575f80fd5b6126ca8461266c565b92506126d86020850161266c565b9150604084013590509250925092565b5f602082840312156126f8575f80fd5b610bfc8261266c565b5f8060408385031215612712575f80fd5b823591506127226020840161266c565b90509250929050565b5f805f6060848603121561273d575f80fd5b83359250602084013591506127546040850161266c565b90509250925092565b5f805f6060848603121561276f575f80fd5b8335925061277f6020850161266c565b91506127546040850161266c565b5f805f805f805f60e0888a0312156127a3575f80fd5b6127ac8861266c565b96506127ba6020890161266c565b95506040880135945060608801359350608088013560ff811681146127dd575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121561280c575f80fd5b6128158461266c565b9250602084013591506127546040850161266c565b5f806040838503121561283b575f80fd5b6128448361266c565b91506127226020840161266c565b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f8261288857612888612852565b500490565b81810381811115610cd057610cd0612866565b5f602082840312156128b0575f80fd5b5051919050565b80820180821115610cd057610cd0612866565b5f826128d8576128d8612852565b500690565b8082028115828204841417610cd057610cd0612866565b600181811c9082168061290857607f821691505b60208210810361292657634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561293c575f80fd5b81518015158114610bfc575f80fd5b5f80835481600182811c91508083168061296657607f831692505b6020808410820361298557634e487b7160e01b86526022600452602486fd5b81801561299957600181146129ae576129d9565b60ff19861689528415158502890196506129d9565b5f8a8152602090205f5b868110156129d15781548b8201529085019083016129b8565b505084890196505b509498975050505050505050565b6001600160601b03818116838216019080821115612a0757612a07612866565b509291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122044b93e02b1a4f6715ea137e1c03f04dd8442eecbaffecd723f158b5d012f7a5464736f6c63430008150033

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

00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb68000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b000000000000000000000000926df14a23be491164dcf93f4c468a50ef659d5b0000000000000000000000004b6c63e6a94ef26e2df60b89372db2d8e211f1b700000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000008e58532b0a48be0067ccbc8dd80000000000

-----Decoded View---------------
Arg [0] : _inv (address): 0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68
Arg [1] : _invMarket (address): 0xb516247596Ca36bf32876199FBdCaD6B3322330B
Arg [2] : _gov (address): 0x926dF14a23BE491164dCF93f4c468A50ef659D5B
Arg [3] : _guardian (address): 0x4b6c63E6a94ef26E2dF60b89372db2d8e211F1B7
Arg [4] : _depositLimit (uint256): 10000000000000000000000
Arg [5] : _K (uint256): 12400000000000000000000000000000000000000000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000041d5d79431a913c4ae7d69a668ecdfe5ff9dfb68
Arg [1] : 000000000000000000000000b516247596ca36bf32876199fbdcad6b3322330b
Arg [2] : 000000000000000000000000926df14a23be491164dcf93f4c468a50ef659d5b
Arg [3] : 0000000000000000000000004b6c63e6a94ef26e2df60b89372db2d8e211f1b7
Arg [4] : 00000000000000000000000000000000000000000000021e19e0c9bab2400000
Arg [5] : 00000000000000000000000000008e58532b0a48be0067ccbc8dd80000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.