ETH Price: $4,676.35 (+3.89%)

Contract

0xf030Cd61A57D67254aB547CDb2701ac129a27a91

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Nominate New Own...33341712025-06-16 12:29:42112 days ago1750076982IN
0xf030Cd61...129a27a91
0 ETH0.000000060.0012003
Add Vault33340732025-06-16 12:28:04112 days ago1750076884IN
0xf030Cd61...129a27a91
0 ETH00.00000025
Set Keeper18514172025-05-30 8:37:08129 days ago1748594228IN
0xf030Cd61...129a27a91
0 ETH00.00000025
Set Keeper18514172025-05-30 8:37:08129 days ago1748594228IN
0xf030Cd61...129a27a91
0 ETH00.00000025
Add Vault18514172025-05-30 8:37:08129 days ago1748594228IN
0xf030Cd61...129a27a91
0 ETH00.00000025
Accept Oracle Ow...18509592025-05-30 8:29:30129 days ago1748593770IN
0xf030Cd61...129a27a91
0 ETH00.00000025

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OracleVaultController

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 20000 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.25

pragma solidity ^0.8.25;

import {Owned} from "src/utils/Owned.sol";
import {Pausable} from "src/utils/Pausable.sol";
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
import {ERC4626} from "solmate/tokens/ERC4626.sol";
import {IPushOracle, Price} from "src/interfaces/IPushOracle.sol";

/// @notice Price update struct
struct PriceUpdate {
    /// @notice The vault to update the price for
    address vault;
    /// @notice The asset to update the price for (the asset the vault is denominated in)
    address asset;
    /// @notice The share value in assets
    uint256 shareValueInAssets;
    /// @notice The asset value in shares
    uint256 assetValueInShares;
}

/// @notice Safety limits for price updates
struct Limit {
    /// @notice Maximum allowed price jump from one update to the next (1e18 = 100%)
    uint256 jump; // 1e18 = 100%
    /// @notice Maximum allowed drawdown from the HWM (1e18 = 100%)
    uint256 drawdown; // 1e18 = 100%
}

/**
 * @title   OracleVaultController
 * @author  RedVeil
 * @notice  Controller for updating the price of vaults using a PushOracle
 * @dev     Updates are made by permissioned keepers in regular intervals.
 * @dev     A large jump in price or drawdown will pause the vault to safeguard against faulty updates or exploits
 */
contract OracleVaultController is Owned {
    using FixedPointMathLib for uint256;

    IPushOracle public oracle;

    event KeeperUpdated(address previous, address current);

    error NotKeeperNorOwner();

    constructor(address _oracle, address _owner) Owned(_owner) {
        oracle = IPushOracle(_oracle);
    }

    /*//////////////////////////////////////////////////////////////
                            ORACLE LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev vault => HWM
    mapping(address => uint256) public highWaterMarks;

    event VaultAdded(address vault);

    /**
     * @notice Update the price and hwm of a vault. A large jump in price or drawdown will pause the vault if it is not already paused
     * @param priceUpdate The price update to update
     * @dev Vault prices shouldnt fluctuate too much since the oracle should be updated regularly. If they do this could be a error, exploit attempt or simply a price jump
     * in these cases we will still update the price (future updates will revert the change if it was a faulty update) BUT pause the vault for additionals deposits
     */
    function updatePrice(PriceUpdate calldata priceUpdate) external {
        _updatePrice(priceUpdate);
    }

    /**
     * @notice Update the prices of multiple vaults
     * @param priceUpdates The price updates to update
     */
    function updatePrices(PriceUpdate[] calldata priceUpdates) external {
        for (uint256 i; i < priceUpdates.length; i++) {
            _updatePrice(priceUpdates[i]);
        }
    }

    /// @notice Internal function to update the price of a vault
    function _updatePrice(
        PriceUpdate calldata priceUpdate
    ) internal onlyKeeperOrOwner(priceUpdate.vault) {
        // Caching
        uint256 lastPrice = oracle.getCurrentPrice(
            priceUpdate.vault,
            priceUpdate.asset
        );
        uint256 hwm = highWaterMarks[priceUpdate.vault];
        bool paused = Pausable(priceUpdate.vault).paused();
        Limit memory limit = limits[priceUpdate.vault];

        // Check for price jump or drawdown
        if (
            // Check for price jump down
            priceUpdate.shareValueInAssets <
            lastPrice.mulDivDown(1e18 - limit.jump, 1e18) ||
            // Check for price jump up
            priceUpdate.shareValueInAssets >
            lastPrice.mulDivDown(1e18 + limit.jump, 1e18) ||
            // Check for drawdown
            priceUpdate.shareValueInAssets <
            hwm.mulDivDown(1e18 - limit.drawdown, 1e18)
        ) {
            // Pause the vault if it is not already paused
            if (!paused) {
                Pausable(priceUpdate.vault).pause();
            }
        } else if (priceUpdate.shareValueInAssets > hwm) {
            // Update HWM if there wasnt a jump or drawdown
            highWaterMarks[priceUpdate.vault] = priceUpdate.shareValueInAssets;
        }

        // Update the price
        oracle.setPrice(
            priceUpdate.vault,
            priceUpdate.asset,
            priceUpdate.shareValueInAssets,
            priceUpdate.assetValueInShares
        );
    }

    /**
     * @notice Update the price and hwm of a vault over multiple blocks. A large jump in price or drawdown will pause the vault if it is not already paused
     * @param priceUpdate The price update to update
     * @param changePerBlock The change of price per block
     * @param increase Whether the price is increasing or decreasing
     * @dev Vault prices shouldnt fluctuate too much since the oracle should be updated regularly. If they do this could be a error, exploit attempt or simply a price jump
     * in these cases we will still update the price (future updates will revert the change if it was a faulty update) BUT pause the vault for additionals deposits
     */
    function updatePriceOverTime(
        PriceUpdate calldata priceUpdate,
        uint256 changePerBlock,
        bool increase
    ) external {
        _updatePriceOverTime(priceUpdate, changePerBlock, increase);
    }

    /**
     * @notice Update the prices of multiple vaults over multiple blocks
     * @param priceUpdates The price updates to update
     * @param changesPerBlock The changes of price per block
     * @param increases Whether the price is increasing or decreasing
     */
    function updatePricesOverTime(
        PriceUpdate[] calldata priceUpdates,
        uint256[] calldata changesPerBlock,
        bool[] calldata increases
    ) external {
        if (priceUpdates.length != changesPerBlock.length)
            revert("Invalid length");
        if (priceUpdates.length != increases.length) revert("Invalid length");

        for (uint256 i; i < priceUpdates.length; i++) {
            _updatePriceOverTime(
                priceUpdates[i],
                changesPerBlock[i],
                increases[i]
            );
        }
    }

    /// @notice Internal function to update the price of a vault over multiple blocks
    function _updatePriceOverTime(
        PriceUpdate calldata priceUpdate,
        uint256 changePerBlock,
        bool increase
    ) internal onlyKeeperOrOwner(priceUpdate.vault) {
        // Caching
        uint256 lastPrice = oracle.getCurrentPrice(
            priceUpdate.vault,
            priceUpdate.asset
        );
        uint256 hwm = highWaterMarks[priceUpdate.vault];
        bool paused = Pausable(priceUpdate.vault).paused();
        Limit memory limit = limits[priceUpdate.vault];

        // Check for price jump or drawdown
        if (
            // Check if the changePerBlock is too large
            changePerBlock > lastPrice.mulDivDown(1e18 + limit.jump, 1e18)
        ) {
            // Pause the vault if it is not already paused
            if (!paused) {
                Pausable(priceUpdate.vault).pause();
            }
        } else if (priceUpdate.shareValueInAssets > hwm) {
            // Update HWM if there wasnt a jump or drawdown
            highWaterMarks[priceUpdate.vault] = priceUpdate.shareValueInAssets;
        }

        // Update the price
        oracle.setPriceOverTime(
            priceUpdate.vault,
            priceUpdate.asset,
            priceUpdate.shareValueInAssets,
            priceUpdate.assetValueInShares,
            changePerBlock,
            increase
        );
    }

    /**
     * @notice Add a vault to the controller to be able to update its price
     * @param vault The vault to add
     * @dev Will always initialize the price to 1e18 (1:1) -- This is to prevent pausing the vault on the first update
     * @dev This function should be called before the vault has received any deposits
     */
    function addVault(address vault) external onlyOwner {
        highWaterMarks[vault] = 1e18;

        oracle.setPrice(vault, address(ERC4626(vault).asset()), 1e18, 1e18);

        emit VaultAdded(vault);
    }

    /*//////////////////////////////////////////////////////////////
                        KEEPER LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev vault => keeper => isKeeper
    mapping(address => mapping(address => bool)) public isKeeper;

    event KeeperUpdated(address vault, address keeper, bool isKeeper);

    /**
     * @notice Set the keeper for a vault
     * @param _vault The vault to set the keeper for
     * @param _keeper The keeper to set for the vault
     */
    function setKeeper(
        address _vault,
        address _keeper,
        bool _isKeeper
    ) external onlyOwner {
        emit KeeperUpdated(_vault, _keeper, _isKeeper);

        isKeeper[_vault][_keeper] = _isKeeper;
    }

    /**
     * @notice Modifier to check if the sender is the owner or the keeper for a vault
     * @param _vault The vault to check the keeper for
     */
    modifier onlyKeeperOrOwner(address _vault) {
        if (msg.sender != owner && !isKeeper[_vault][msg.sender])
            revert NotKeeperNorOwner();
        _;
    }

    /*//////////////////////////////////////////////////////////////
                        MANAGEMENT LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev vault => Limit
    mapping(address => Limit) public limits;

    event LimitUpdated(address vault, Limit previous, Limit current);

    /**
     * @notice Set the limit for a vault
     * @param _vault The vault to set the limit for
     * @param _limit The limit to set for the vault
     */
    function setLimit(address _vault, Limit memory _limit) external onlyOwner {
        _setLimit(_vault, _limit);
    }

    /**
     * @notice Set the limits for multiple vaults
     * @param _vaults The vaults to set the limits for
     * @param _limits The limits to set for the vaults
     */
    function setLimits(
        address[] memory _vaults,
        Limit[] memory _limits
    ) external onlyOwner {
        if (_vaults.length != _limits.length) revert("Invalid length");

        for (uint256 i; i < _vaults.length; i++) {
            _setLimit(_vaults[i], _limits[i]);
        }
    }

    /// @notice Internal function to set the limit for a vault
    function _setLimit(address _vault, Limit memory _limit) internal {
        if (_limit.jump > 1e18 || _limit.drawdown > 1e18)
            revert("Invalid limit");
        emit LimitUpdated(_vault, limits[_vault], _limit);

        limits[_vault] = _limit;
    }

    /*//////////////////////////////////////////////////////////////
                        OTHER LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Accept the ownership of the oracle
     * @dev Used after construction since we otherwise have recursive dependencies on the construction of this contract and the oracle
     */
    function acceptOracleOwnership() external onlyOwner {
        Owned(address(oracle)).acceptOwnership();
    }
}

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

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

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

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

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

/// @title IPriceOracle
/// @custom:security-contact [email protected]
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Common PriceOracle interface.
interface IPriceOracle {
    /// @notice Get the name of the oracle.
    /// @return The name of the oracle.
    function name() external view returns (string memory);

    /// @notice One-sided price: How much quote token you would get for inAmount of base token, assuming no price spread.
    /// @param inAmount The amount of `base` to convert.
    /// @param base The token that is being priced.
    /// @param quote The token that is the unit of account.
    /// @return outAmount The amount of `quote` that is equivalent to `inAmount` of `base`.
    function getQuote(
        uint256 inAmount,
        address base,
        address quote
    ) external view returns (uint256 outAmount);

    /// @notice Two-sided price: How much quote token you would get/spend for selling/buying inAmount of base token.
    /// @param inAmount The amount of `base` to convert.
    /// @param base The token that is being priced.
    /// @param quote The token that is the unit of account.
    /// @return bidOutAmount The amount of `quote` you would get for selling `inAmount` of `base`.
    /// @return askOutAmount The amount of `quote` you would spend for buying `inAmount` of `base`.
    function getQuotes(
        uint256 inAmount,
        address base,
        address quote
    ) external view returns (uint256 bidOutAmount, uint256 askOutAmount);
}

// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.25

pragma solidity ^0.8.25;

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

struct Price {
    uint256 price;
    uint256 targetPrice;
    uint256 changePerBlock;
    uint256 lastUpdatedBlock;
    bool increase;
}

interface IPushOracle is IPriceOracle {
    function setPrice(
        address base,
        address quote,
        uint256 bqPrice,
        uint256 qbPrice
    ) external;

    function setPrices(
        address[] memory bases,
        address[] memory quotes,
        uint256[] memory bqPrices,
        uint256[] memory qbPrices
    ) external;

    function prices(
        address base,
        address quote
    ) external view returns (Price memory);

    function setPriceOverTime(
        address base,
        address quote,
        uint256 bqTargetPrice,
        uint256 qbTargetPrice,
        uint256 changePerBlock,
        bool increase
    ) external;

    function setPricesOverTime(
        address[] memory bases,
        address[] memory quotes,
        uint256[] memory bqTargetPrices,
        uint256[] memory qbTargetPrices,
        uint256[] memory changePerBlocks,
        bool[] memory increases
    ) external;

    function getCurrentPrice(
        address base,
        address quote
    ) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.25

pragma solidity ^0.8.25;

// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);

    constructor(address _owner) {
        require(_owner != address(0), "Owned/owner-zero");
        owner = _owner;

        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external virtual onlyOwner {
        nominatedOwner = _owner;

        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external virtual {
        require(
            msg.sender == nominatedOwner,
            "Owned/not-nominated"
        );

        emit OwnerChanged(owner, nominatedOwner);

        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner() {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(
            msg.sender == owner,
            "Owned/not-owner"
        );
    }
}

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

/// @notice Gas optimized Pausable for smart contracts.
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Pausable.sol)
abstract contract Pausable {
    bool public paused;

    event Paused(address account);
    event Unpaused(address account);

    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    modifier whenPaused() {
        _requirePaused();
        _;
    }

    function _requireNotPaused() internal view virtual {
        if (paused) {
            revert("Pausable/paused");
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused) {
            revert("Pausable/not-paused");
        }
    }

    function _pause() internal virtual whenNotPaused {
        paused = true;
        emit Paused(msg.sender);
    }

    function _unpause() internal virtual whenPaused {
        paused = false;
        emit Unpaused(msg.sender);
    }

    function pause() external virtual whenNotPaused {
        _pause();
    }

    function unpause() external virtual whenPaused {
        _unpause();
    }
}

Settings
{
  "evmVersion": "shanghai",
  "libraries": {},
  "metadata": {
    "appendCBOR": true,
    "bytecodeHash": "ipfs",
    "useLiteralContent": false
  },
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "solmate/=lib/solmate/src/",
    "safe-smart-account/=lib/safe-smart-account/contracts/",
    "weiroll/=lib/weiroll/contracts/",
    "solady/=lib/solady/src/",
    "bitlib/=lib/solidity-bytes-utils/contracts/",
    "ERC-7540/=lib/ERC-7540-Reference/src/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@pyth/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    "@redstone/evm-connector/=lib/euler-price-oracle/lib/redstone-oracles-monorepo/packages/evm-connector/contracts/",
    "@solady/=lib/euler-price-oracle/lib/solady/src/",
    "@uniswap/v3-core/=lib/euler-price-oracle/lib/v3-core/",
    "@uniswap/v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/",
    "ERC-7540-Reference/=lib/ERC-7540-Reference/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "euler-price-oracle/=lib/euler-price-oracle/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "openzeppelin/=lib/euler-price-oracle/lib/openzeppelin-contracts/contracts/",
    "pyth-sdk-solidity/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    "redstone-oracles-monorepo/=lib/euler-price-oracle/lib/",
    "solidity-bytes-utils/=lib/solidity-bytes-utils/contracts/",
    "v3-core/=lib/v3-core/",
    "v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotKeeperNorOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previous","type":"address"},{"indexed":false,"internalType":"address","name":"current","type":"address"}],"name":"KeeperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"keeper","type":"address"},{"indexed":false,"internalType":"bool","name":"isKeeper","type":"bool"}],"name":"KeeperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"uint256","name":"jump","type":"uint256"},{"internalType":"uint256","name":"drawdown","type":"uint256"}],"indexed":false,"internalType":"struct Limit","name":"previous","type":"tuple"},{"components":[{"internalType":"uint256","name":"jump","type":"uint256"},{"internalType":"uint256","name":"drawdown","type":"uint256"}],"indexed":false,"internalType":"struct Limit","name":"current","type":"tuple"}],"name":"LimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"VaultAdded","type":"event"},{"inputs":[],"name":"acceptOracleOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"addVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"highWaterMarks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isKeeper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"limits","outputs":[{"internalType":"uint256","name":"jump","type":"uint256"},{"internalType":"uint256","name":"drawdown","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IPushOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"bool","name":"_isKeeper","type":"bool"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"components":[{"internalType":"uint256","name":"jump","type":"uint256"},{"internalType":"uint256","name":"drawdown","type":"uint256"}],"internalType":"struct Limit","name":"_limit","type":"tuple"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_vaults","type":"address[]"},{"components":[{"internalType":"uint256","name":"jump","type":"uint256"},{"internalType":"uint256","name":"drawdown","type":"uint256"}],"internalType":"struct Limit[]","name":"_limits","type":"tuple[]"}],"name":"setLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"shareValueInAssets","type":"uint256"},{"internalType":"uint256","name":"assetValueInShares","type":"uint256"}],"internalType":"struct PriceUpdate","name":"priceUpdate","type":"tuple"}],"name":"updatePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"shareValueInAssets","type":"uint256"},{"internalType":"uint256","name":"assetValueInShares","type":"uint256"}],"internalType":"struct PriceUpdate","name":"priceUpdate","type":"tuple"},{"internalType":"uint256","name":"changePerBlock","type":"uint256"},{"internalType":"bool","name":"increase","type":"bool"}],"name":"updatePriceOverTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"shareValueInAssets","type":"uint256"},{"internalType":"uint256","name":"assetValueInShares","type":"uint256"}],"internalType":"struct PriceUpdate[]","name":"priceUpdates","type":"tuple[]"}],"name":"updatePrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"shareValueInAssets","type":"uint256"},{"internalType":"uint256","name":"assetValueInShares","type":"uint256"}],"internalType":"struct PriceUpdate[]","name":"priceUpdates","type":"tuple[]"},{"internalType":"uint256[]","name":"changesPerBlock","type":"uint256[]"},{"internalType":"bool[]","name":"increases","type":"bool[]"}],"name":"updatePricesOverTime","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561000f575f5ffd5b50604051611c2a380380611c2a83398101604081905261002e91610114565b806001600160a01b03811661007c5760405162461bcd60e51b815260206004820152601060248201526f4f776e65642f6f776e65722d7a65726f60801b604482015260640160405180910390fd5b5f80546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a15050600280546001600160a01b0319166001600160a01b0392909216919091179055610145565b80516001600160a01b038116811461010f575f5ffd5b919050565b5f5f60408385031215610125575f5ffd5b61012e836100f9565b915061013c602084016100f9565b90509250929050565b611ad8806101525f395ff3fe608060405234801561000f575f5ffd5b5060043610610115575f3560e01c806379ba5097116100ad578063a64d48361161007d578063fb116cd811610063578063fb116cd8146102d6578063fd5835d0146102e9578063fe47ec9a146102f1575f5ffd5b8063a64d483614610296578063aa165f32146102c3575f5ffd5b806379ba5097146102125780637dc0d1d01461021a5780638da5cb5b1461023a57806397f2b7f214610259575f5ffd5b8063256b5a02116100e8578063256b5a02146101945780634261da37146101a757806353a47bb7146101ba578063720d033f146101ff575f5ffd5b806304efb1fb146101195780631032a4131461012e5780631627540c1461014157806320d7bec114610154575b5f5ffd5b61012c610127366004611643565b610304565b005b61012c61013c36600461172b565b6103d0565b61012c61014f366004611769565b6103db565b61017a610162366004611769565b60056020525f90815260409020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61012c6101a2366004611769565b61045d565b61012c6101b536600461178b565b6105f3565b6001546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018b565b61012c61020d366004611807565b610609565b61012c61063b565b6002546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b5f546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b610286610267366004611846565b600460209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161018b565b6102b56102a4366004611769565b60036020525f908152604090205481565b60405190815260200161018b565b61012c6102d136600461187d565b61075e565b61012c6102e43660046118d8565b61076a565b61012c6108b7565b61012c6102ff366004611977565b61093d565b61030c610a01565b805182511461037c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e67746800000000000000000000000000000000000060448201526064015b60405180910390fd5b5f5b82518110156103cb576103c383828151811061039c5761039c6119b4565b60200260200101518383815181106103b6576103b66119b4565b6020026020010151610a83565b60010161037e565b505050565b6103cb838383610bb8565b6103e3610a01565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b610465610a01565b73ffffffffffffffffffffffffffffffffffffffff8082165f81815260036020908152604091829020670de0b6b3a7640000905560025482517f38d52e0f000000000000000000000000000000000000000000000000000000008152925194169363a405d31293869390926338d52e0f926004808401938290030181865afa1580156104f3573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061051791906119e1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152670de0b6b3a76400006044820181905260648201526084015f604051808303815f87803b158015610596575f5ffd5b505af11580156105a8573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f7b7ef7a864d96a85497a1ed846adb39940dd6ccef678ff6ac8d55505e09b8cc492506020019050610452565b6105fb610a01565b6106058282610a83565b5050565b5f5b818110156103cb57610633838383818110610628576106286119b4565b905060800201611000565b60010161060b565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f776e65642f6e6f742d6e6f6d696e61746564000000000000000000000000006044820152606401610373565b5f546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180545f80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b61076781611000565b50565b8483146107d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152606401610373565b84811461083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152606401610373565b5f5b858110156108ae576108a687878381811061085b5761085b6119b4565b905060800201868684818110610873576108736119b4565b9050602002013585858581811061088c5761088c6119b4565b90506020020160208101906108a191906119fc565b610bb8565b60010161083e565b50505050505050565b6108bf610a01565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610925575f5ffd5b505af1158015610937573d5f5f3e3d5ffd5b50505050565b610945610a01565b6040805173ffffffffffffffffffffffffffffffffffffffff8581168252841660208201528215158183015290517f86665cd5d3d01ca9aad62eea6871fe4a5a65c2359ab24777315c7cf712f1e2a99181900360600190a173ffffffffffffffffffffffffffffffffffffffff9283165f9081526004602090815260408083209490951682529290925291902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610a81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4f776e65642f6e6f742d6f776e657200000000000000000000000000000000006044820152606401610373565b565b8051670de0b6b3a76400001080610aa55750670de0b6b3a76400008160200151115b15610b0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206c696d6974000000000000000000000000000000000000006044820152606401610373565b73ffffffffffffffffffffffffffffffffffffffff82165f8181526005602090815260409182902082519384528054848301526001015483830152835160608401528301516080830152517fc4b9b0c18c54d55c96918e7cb235095f193a9fae0a7c81a0c19c0397ec9779329181900360a00190a173ffffffffffffffffffffffffffffffffffffffff9091165f90815260056020908152604090912082518155910151600190910155565b610bc56020840184611769565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610c1c575073ffffffffffffffffffffffffffffffffffffffff81165f90815260046020908152604080832033845290915290205460ff16155b15610c53576040517fc6764d6d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002545f9073ffffffffffffffffffffffffffffffffffffffff1663db16a555610c806020880188611769565b610c906040890160208a01611769565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610cfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d229190611a17565b90505f600381610d356020890189611769565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040015f90812054925090610d6d90880188611769565b73ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dd99190611a2e565b90505f600581610dec60208b018b611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208082019290925260409081015f2081518083019092528054808352600190910154928201929092529150610e5690610e4690670de0b6b3a7640000611a76565b8590670de0b6b3a7640000611488565b871115610ecf5781610eca57610e6f6020890189611769565b73ffffffffffffffffffffffffffffffffffffffff16638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610eb3575f5ffd5b505af1158015610ec5573d5f5f3e3d5ffd5b505050505b610f17565b8288604001351115610f1757604088013560035f610ef060208c018c611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f20555b60025473ffffffffffffffffffffffffffffffffffffffff1663d073aec1610f4260208b018b611769565b610f5260408c0160208d01611769565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301528b0135604482015260608b01356064820152608481018a905288151560a482015260c4015f604051808303815f87803b158015610fe0575f5ffd5b505af1158015610ff2573d5f5f3e3d5ffd5b505050505050505050505050565b61100d6020820182611769565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611064575073ffffffffffffffffffffffffffffffffffffffff81165f90815260046020908152604080832033845290915290205460ff16155b1561109b576040517fc6764d6d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002545f9073ffffffffffffffffffffffffffffffffffffffff1663db16a5556110c86020860186611769565b6110d86040870160208801611769565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015611146573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061116a9190611a17565b90505f60038161117d6020870187611769565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040015f908120549250906111b590860186611769565b73ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112219190611a2e565b90505f6005816112346020890189611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208082019290925260409081015f208151808301909252805480835260019091015492820192909252915061128e90610e4690670de0b6b3a7640000611a8f565b866040013510806112b9575080516112b290610e4690670de0b6b3a7640000611a76565b8660400135115b806112f157506112ea8160200151670de0b6b3a76400006112da9190611a8f565b8490670de0b6b3a7640000611488565b8660400135105b156113685781611363576113086020870187611769565b73ffffffffffffffffffffffffffffffffffffffff16638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561134c575f5ffd5b505af115801561135e573d5f5f3e3d5ffd5b505050505b6113b0565b82866040013511156113b057604086013560035f61138960208a018a611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f20555b60025473ffffffffffffffffffffffffffffffffffffffff1663a405d3126113db6020890189611769565b6113eb60408a0160208b01611769565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301528901356044820152606089013560648201526084015f604051808303815f87803b15801561146a575f5ffd5b505af115801561147c573d5f5f3e3d5ffd5b50505050505050505050565b5f827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841183021582026114bb575f5ffd5b5091020490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611536576115366114c2565b604052919050565b5f67ffffffffffffffff821115611557576115576114c2565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610767575f5ffd5b5f60408284031215611592575f5ffd5b6040805190810167ffffffffffffffff811182821017156115b5576115b56114c2565b604052823581526020928301359281019290925250919050565b5f82601f8301126115de575f5ffd5b81356115f16115ec8261153e565b6114ef565b8082825260208201915060208360061b860101925085831115611612575f5ffd5b602085015b83811015611639576116298782611582565b8352602090920191604001611617565b5095945050505050565b5f5f60408385031215611654575f5ffd5b823567ffffffffffffffff81111561166a575f5ffd5b8301601f8101851361167a575f5ffd5b80356116886115ec8261153e565b8082825260208201915060208360051b8501019250878311156116a9575f5ffd5b6020840193505b828410156116d45783356116c381611561565b8252602093840193909101906116b0565b9450505050602083013567ffffffffffffffff8111156116f2575f5ffd5b6116fe858286016115cf565b9150509250929050565b5f60808284031215611718575f5ffd5b50919050565b8015158114610767575f5ffd5b5f5f5f60c0848603121561173d575f5ffd5b6117478585611708565b92506080840135915060a084013561175e8161171e565b809150509250925092565b5f60208284031215611779575f5ffd5b813561178481611561565b9392505050565b5f5f6060838503121561179c575f5ffd5b82356117a781611561565b91506117b68460208501611582565b90509250929050565b5f5f83601f8401126117cf575f5ffd5b50813567ffffffffffffffff8111156117e6575f5ffd5b6020830191508360208260071b8501011115611800575f5ffd5b9250929050565b5f5f60208385031215611818575f5ffd5b823567ffffffffffffffff81111561182e575f5ffd5b61183a858286016117bf565b90969095509350505050565b5f5f60408385031215611857575f5ffd5b823561186281611561565b9150602083013561187281611561565b809150509250929050565b5f6080828403121561188d575f5ffd5b6117848383611708565b5f5f83601f8401126118a7575f5ffd5b50813567ffffffffffffffff8111156118be575f5ffd5b6020830191508360208260051b8501011115611800575f5ffd5b5f5f5f5f5f5f606087890312156118ed575f5ffd5b863567ffffffffffffffff811115611903575f5ffd5b61190f89828a016117bf565b909750955050602087013567ffffffffffffffff81111561192e575f5ffd5b61193a89828a01611897565b909550935050604087013567ffffffffffffffff811115611959575f5ffd5b61196589828a01611897565b979a9699509497509295939492505050565b5f5f5f60608486031215611989575f5ffd5b833561199481611561565b925060208401356119a481611561565b9150604084013561175e8161171e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156119f1575f5ffd5b815161178481611561565b5f60208284031215611a0c575f5ffd5b81356117848161171e565b5f60208284031215611a27575f5ffd5b5051919050565b5f60208284031215611a3e575f5ffd5b81516117848161171e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611a8957611a89611a49565b92915050565b81810381811115611a8957611a89611a4956fea2646970667358221220db68e1a93f8437761fe63c5e07908089b074b42e793e75b333259423d92221ee64736f6c634300081c0033000000000000000000000000b2a4e3b4843adea2abdcc02aa9db8261fd9323ad000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c8

Deployed Bytecode

0x608060405234801561000f575f5ffd5b5060043610610115575f3560e01c806379ba5097116100ad578063a64d48361161007d578063fb116cd811610063578063fb116cd8146102d6578063fd5835d0146102e9578063fe47ec9a146102f1575f5ffd5b8063a64d483614610296578063aa165f32146102c3575f5ffd5b806379ba5097146102125780637dc0d1d01461021a5780638da5cb5b1461023a57806397f2b7f214610259575f5ffd5b8063256b5a02116100e8578063256b5a02146101945780634261da37146101a757806353a47bb7146101ba578063720d033f146101ff575f5ffd5b806304efb1fb146101195780631032a4131461012e5780631627540c1461014157806320d7bec114610154575b5f5ffd5b61012c610127366004611643565b610304565b005b61012c61013c36600461172b565b6103d0565b61012c61014f366004611769565b6103db565b61017a610162366004611769565b60056020525f90815260409020805460019091015482565b604080519283526020830191909152015b60405180910390f35b61012c6101a2366004611769565b61045d565b61012c6101b536600461178b565b6105f3565b6001546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018b565b61012c61020d366004611807565b610609565b61012c61063b565b6002546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b5f546101da9073ffffffffffffffffffffffffffffffffffffffff1681565b610286610267366004611846565b600460209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161018b565b6102b56102a4366004611769565b60036020525f908152604090205481565b60405190815260200161018b565b61012c6102d136600461187d565b61075e565b61012c6102e43660046118d8565b61076a565b61012c6108b7565b61012c6102ff366004611977565b61093d565b61030c610a01565b805182511461037c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e67746800000000000000000000000000000000000060448201526064015b60405180910390fd5b5f5b82518110156103cb576103c383828151811061039c5761039c6119b4565b60200260200101518383815181106103b6576103b66119b4565b6020026020010151610a83565b60010161037e565b505050565b6103cb838383610bb8565b6103e3610a01565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b610465610a01565b73ffffffffffffffffffffffffffffffffffffffff8082165f81815260036020908152604091829020670de0b6b3a7640000905560025482517f38d52e0f000000000000000000000000000000000000000000000000000000008152925194169363a405d31293869390926338d52e0f926004808401938290030181865afa1580156104f3573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061051791906119e1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152670de0b6b3a76400006044820181905260648201526084015f604051808303815f87803b158015610596575f5ffd5b505af11580156105a8573d5f5f3e3d5ffd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f7b7ef7a864d96a85497a1ed846adb39940dd6ccef678ff6ac8d55505e09b8cc492506020019050610452565b6105fb610a01565b6106058282610a83565b5050565b5f5b818110156103cb57610633838383818110610628576106286119b4565b905060800201611000565b60010161060b565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f776e65642f6e6f742d6e6f6d696e61746564000000000000000000000000006044820152606401610373565b5f546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180545f80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b61076781611000565b50565b8483146107d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152606401610373565b84811461083c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c6964206c656e6774680000000000000000000000000000000000006044820152606401610373565b5f5b858110156108ae576108a687878381811061085b5761085b6119b4565b905060800201868684818110610873576108736119b4565b9050602002013585858581811061088c5761088c6119b4565b90506020020160208101906108a191906119fc565b610bb8565b60010161083e565b50505050505050565b6108bf610a01565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610925575f5ffd5b505af1158015610937573d5f5f3e3d5ffd5b50505050565b610945610a01565b6040805173ffffffffffffffffffffffffffffffffffffffff8581168252841660208201528215158183015290517f86665cd5d3d01ca9aad62eea6871fe4a5a65c2359ab24777315c7cf712f1e2a99181900360600190a173ffffffffffffffffffffffffffffffffffffffff9283165f9081526004602090815260408083209490951682529290925291902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610a81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4f776e65642f6e6f742d6f776e657200000000000000000000000000000000006044820152606401610373565b565b8051670de0b6b3a76400001080610aa55750670de0b6b3a76400008160200151115b15610b0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206c696d6974000000000000000000000000000000000000006044820152606401610373565b73ffffffffffffffffffffffffffffffffffffffff82165f8181526005602090815260409182902082519384528054848301526001015483830152835160608401528301516080830152517fc4b9b0c18c54d55c96918e7cb235095f193a9fae0a7c81a0c19c0397ec9779329181900360a00190a173ffffffffffffffffffffffffffffffffffffffff9091165f90815260056020908152604090912082518155910151600190910155565b610bc56020840184611769565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590610c1c575073ffffffffffffffffffffffffffffffffffffffff81165f90815260046020908152604080832033845290915290205460ff16155b15610c53576040517fc6764d6d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002545f9073ffffffffffffffffffffffffffffffffffffffff1663db16a555610c806020880188611769565b610c906040890160208a01611769565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610cfe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d229190611a17565b90505f600381610d356020890189611769565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040015f90812054925090610d6d90880188611769565b73ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610db5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dd99190611a2e565b90505f600581610dec60208b018b611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208082019290925260409081015f2081518083019092528054808352600190910154928201929092529150610e5690610e4690670de0b6b3a7640000611a76565b8590670de0b6b3a7640000611488565b871115610ecf5781610eca57610e6f6020890189611769565b73ffffffffffffffffffffffffffffffffffffffff16638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610eb3575f5ffd5b505af1158015610ec5573d5f5f3e3d5ffd5b505050505b610f17565b8288604001351115610f1757604088013560035f610ef060208c018c611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f20555b60025473ffffffffffffffffffffffffffffffffffffffff1663d073aec1610f4260208b018b611769565b610f5260408c0160208d01611769565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301528b0135604482015260608b01356064820152608481018a905288151560a482015260c4015f604051808303815f87803b158015610fe0575f5ffd5b505af1158015610ff2573d5f5f3e3d5ffd5b505050505050505050505050565b61100d6020820182611769565b5f5473ffffffffffffffffffffffffffffffffffffffff163314801590611064575073ffffffffffffffffffffffffffffffffffffffff81165f90815260046020908152604080832033845290915290205460ff16155b1561109b576040517fc6764d6d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002545f9073ffffffffffffffffffffffffffffffffffffffff1663db16a5556110c86020860186611769565b6110d86040870160208801611769565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015611146573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061116a9190611a17565b90505f60038161117d6020870187611769565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040015f908120549250906111b590860186611769565b73ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112219190611a2e565b90505f6005816112346020890189611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208082019290925260409081015f208151808301909252805480835260019091015492820192909252915061128e90610e4690670de0b6b3a7640000611a8f565b866040013510806112b9575080516112b290610e4690670de0b6b3a7640000611a76565b8660400135115b806112f157506112ea8160200151670de0b6b3a76400006112da9190611a8f565b8490670de0b6b3a7640000611488565b8660400135105b156113685781611363576113086020870187611769565b73ffffffffffffffffffffffffffffffffffffffff16638456cb596040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561134c575f5ffd5b505af115801561135e573d5f5f3e3d5ffd5b505050505b6113b0565b82866040013511156113b057604086013560035f61138960208a018a611769565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f20555b60025473ffffffffffffffffffffffffffffffffffffffff1663a405d3126113db6020890189611769565b6113eb60408a0160208b01611769565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301528901356044820152606089013560648201526084015f604051808303815f87803b15801561146a575f5ffd5b505af115801561147c573d5f5f3e3d5ffd5b50505050505050505050565b5f827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841183021582026114bb575f5ffd5b5091020490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611536576115366114c2565b604052919050565b5f67ffffffffffffffff821115611557576115576114c2565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610767575f5ffd5b5f60408284031215611592575f5ffd5b6040805190810167ffffffffffffffff811182821017156115b5576115b56114c2565b604052823581526020928301359281019290925250919050565b5f82601f8301126115de575f5ffd5b81356115f16115ec8261153e565b6114ef565b8082825260208201915060208360061b860101925085831115611612575f5ffd5b602085015b83811015611639576116298782611582565b8352602090920191604001611617565b5095945050505050565b5f5f60408385031215611654575f5ffd5b823567ffffffffffffffff81111561166a575f5ffd5b8301601f8101851361167a575f5ffd5b80356116886115ec8261153e565b8082825260208201915060208360051b8501019250878311156116a9575f5ffd5b6020840193505b828410156116d45783356116c381611561565b8252602093840193909101906116b0565b9450505050602083013567ffffffffffffffff8111156116f2575f5ffd5b6116fe858286016115cf565b9150509250929050565b5f60808284031215611718575f5ffd5b50919050565b8015158114610767575f5ffd5b5f5f5f60c0848603121561173d575f5ffd5b6117478585611708565b92506080840135915060a084013561175e8161171e565b809150509250925092565b5f60208284031215611779575f5ffd5b813561178481611561565b9392505050565b5f5f6060838503121561179c575f5ffd5b82356117a781611561565b91506117b68460208501611582565b90509250929050565b5f5f83601f8401126117cf575f5ffd5b50813567ffffffffffffffff8111156117e6575f5ffd5b6020830191508360208260071b8501011115611800575f5ffd5b9250929050565b5f5f60208385031215611818575f5ffd5b823567ffffffffffffffff81111561182e575f5ffd5b61183a858286016117bf565b90969095509350505050565b5f5f60408385031215611857575f5ffd5b823561186281611561565b9150602083013561187281611561565b809150509250929050565b5f6080828403121561188d575f5ffd5b6117848383611708565b5f5f83601f8401126118a7575f5ffd5b50813567ffffffffffffffff8111156118be575f5ffd5b6020830191508360208260051b8501011115611800575f5ffd5b5f5f5f5f5f5f606087890312156118ed575f5ffd5b863567ffffffffffffffff811115611903575f5ffd5b61190f89828a016117bf565b909750955050602087013567ffffffffffffffff81111561192e575f5ffd5b61193a89828a01611897565b909550935050604087013567ffffffffffffffff811115611959575f5ffd5b61196589828a01611897565b979a9699509497509295939492505050565b5f5f5f60608486031215611989575f5ffd5b833561199481611561565b925060208401356119a481611561565b9150604084013561175e8161171e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156119f1575f5ffd5b815161178481611561565b5f60208284031215611a0c575f5ffd5b81356117848161171e565b5f60208284031215611a27575f5ffd5b5051919050565b5f60208284031215611a3e575f5ffd5b81516117848161171e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611a8957611a89611a49565b92915050565b81810381811115611a8957611a89611a4956fea2646970667358221220db68e1a93f8437761fe63c5e07908089b074b42e793e75b333259423d92221ee64736f6c634300081c0033

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

000000000000000000000000b2a4e3b4843adea2abdcc02aa9db8261fd9323ad000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c8

-----Decoded View---------------
Arg [0] : _oracle (address): 0xb2a4E3B4843ADea2abdCc02aa9db8261Fd9323AD
Arg [1] : _owner (address): 0x919D5a6F2CBc0731380C26B4AC4f6183dD3A40C8

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b2a4e3b4843adea2abdcc02aa9db8261fd9323ad
Arg [1] : 000000000000000000000000919d5a6f2cbc0731380c26b4ac4f6183dd3a40c8


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
0xf030Cd61A57D67254aB547CDb2701ac129a27a91
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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