账户
0xca...c9f9
0xcA...C9F9

0xcA...C9F9

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.24+commit.e11b9ed9
语言
Solidity
合同源代码
文件 1 的 5:BaseFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

import {IFactory} from "./interfaces/IFactory.sol";

/// @title BaseFactory
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A minimal factory for deploying various contracts.
abstract contract BaseFactory is IFactory {
    /// @notice Contracts deployed by the factory.
    mapping(address => DeploymentInfo) internal deploymentInfo;

    /// @notice An array of addresses of all the contracts deployed by the factory
    address[] public deployments;

    /// @inheritdoc IFactory
    function getDeploymentInfo(address contractAddress) external view returns (address deployer, uint96 deployedAt) {
        DeploymentInfo memory info = deploymentInfo[contractAddress];
        return (info.deployer, info.deployedAt);
    }

    /// @inheritdoc IFactory
    function isValidDeployment(address contractAddress) external view returns (bool) {
        return deploymentInfo[contractAddress].deployedAt != 0;
    }

    /// @inheritdoc IFactory
    function getDeploymentsListLength() external view returns (uint256) {
        return deployments.length;
    }

    /// @inheritdoc IFactory
    function getDeploymentsListSlice(uint256 start, uint256 end) external view returns (address[] memory list) {
        if (end == type(uint256).max) end = deployments.length;
        if (end < start || end > deployments.length) revert Factory_BadQuery();

        list = new address[](end - start);
        for (uint256 i; i < end - start; ++i) {
            list[i] = deployments[start + i];
        }
    }
}
合同源代码
文件 2 的 5:EulerKinkIRMFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

import {BaseFactory} from "../BaseFactory/BaseFactory.sol";
import {IRMLinearKink} from "evk/InterestRateModels/IRMLinearKink.sol";

/// @title EulerKinkIRMFactory
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A minimal factory for Kink IRMs.
contract EulerKinkIRMFactory is BaseFactory {
    // corresponds to 1000% APY
    uint256 internal constant MAX_ALLOWED_INTEREST_RATE = 75986279153383989049;

    /// @notice Error thrown when the computed interest rate exceeds the maximum allowed limit.
    error IRMFactory_ExcessiveInterestRate();

    /// @notice Deploys a new IRMLinearKink.
    /// @param baseRate Base interest rate applied when utilization is equal zero
    /// @param slope1 Slope of the function before the kink
    /// @param slope2 Slope of the function after the kink
    /// @param kink Utilization at which the slope of the interest rate function changes. In type(uint32).max scale
    /// @return The deployment address.
    function deploy(uint256 baseRate, uint256 slope1, uint256 slope2, uint32 kink) external returns (address) {
        IRMLinearKink irm = new IRMLinearKink(baseRate, slope1, slope2, kink);

        // verify if the IRM is functional
        irm.computeInterestRateView(address(0), type(uint32).max, 0);
        irm.computeInterestRateView(address(0), type(uint32).max - kink, kink);
        uint256 maxInterestRate = irm.computeInterestRateView(address(0), 0, type(uint32).max);

        if (maxInterestRate > MAX_ALLOWED_INTEREST_RATE) revert IRMFactory_ExcessiveInterestRate();

        deploymentInfo[address(irm)] = DeploymentInfo(msg.sender, uint96(block.timestamp));
        deployments.push(address(irm));
        emit ContractDeployed(address(irm), msg.sender, block.timestamp);
        return address(irm);
    }
}
合同源代码
文件 3 的 5:IFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.8.0;

/// @title IFactory
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice A minimal factory interface for deploying contracts.
interface IFactory {
    struct DeploymentInfo {
        /// @notice The sender of the deployment call.
        address deployer;
        /// @notice The timestamp when the contract was deployed.
        uint96 deployedAt;
    }

    /// @notice An instance of a contract was deployed.
    /// @param deployedContract The deployment address of the contract.
    /// @param deployer The sender of the deployment call.
    /// @param deployedAt The deployment timestamp of the contract.
    event ContractDeployed(address indexed deployedContract, address indexed deployer, uint256 deployedAt);

    /// @notice Error thrown when the query is incorrect.
    error Factory_BadQuery();

    /// @notice Contracts deployed by the factory.
    function getDeploymentInfo(address contractAddress) external view returns (address deployer, uint96 deployedAt);

    /// @notice Checks if the deployment at the given address is valid.
    /// @param contractAddress The address of the contract to check.
    /// @return True if the deployment is valid, false otherwise.
    function isValidDeployment(address contractAddress) external view returns (bool);

    /// @notice Returns the number of contracts deployed by the factory.
    /// @return The number of deployed contracts.
    function getDeploymentsListLength() external view returns (uint256);

    /// @notice Returns a slice of the list of deployments.
    /// @param start The starting index of the slice.
    /// @param end The ending index of the slice (exclusive).
    /// @return list An array of addresses of the deployed contracts in the specified range.
    function getDeploymentsListSlice(uint256 start, uint256 end) external view returns (address[] memory list);
}
合同源代码
文件 4 的 5:IIRM.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.8.0;

/// @title IIRM
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Interface of the interest rate model contracts used by EVault
interface IIRM {
    error E_IRMUpdateUnauthorized();

    /// @notice Perform potentially state mutating computation of the new interest rate
    /// @param vault Address of the vault to compute the new interest rate for
    /// @param cash Amount of assets held directly by the vault
    /// @param borrows Amount of assets lent out to borrowers by the vault
    /// @return Then new interest rate in second percent yield (SPY), scaled by 1e27
    function computeInterestRate(address vault, uint256 cash, uint256 borrows) external returns (uint256);

    /// @notice Perform computation of the new interest rate without mutating state
    /// @param vault Address of the vault to compute the new interest rate for
    /// @param cash Amount of assets held directly by the vault
    /// @param borrows Amount of assets lent out to borrowers by the vault
    /// @return Then new interest rate in second percent yield (SPY), scaled by 1e27
    function computeInterestRateView(address vault, uint256 cash, uint256 borrows) external view returns (uint256);
}
合同源代码
文件 5 的 5:IRMLinearKink.sol
// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity ^0.8.0;

import "./IIRM.sol";

/// @title IRMLinearKink
/// @custom:security-contact security@euler.xyz
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Implementation of an interest rate model, where interest rate grows linearly with utilization, and spikes
/// after reaching kink
contract IRMLinearKink is IIRM {
    /// @notice Base interest rate applied when utilization is equal zero
    uint256 public immutable baseRate;
    /// @notice Slope of the function before the kink
    uint256 public immutable slope1;
    /// @notice Slope of the function after the kink
    uint256 public immutable slope2;
    /// @notice Utilization at which the slope of the interest rate function changes. In type(uint32).max scale.
    uint256 public immutable kink;

    constructor(uint256 baseRate_, uint256 slope1_, uint256 slope2_, uint32 kink_) {
        baseRate = baseRate_;
        slope1 = slope1_;
        slope2 = slope2_;
        kink = kink_;
    }

    /// @inheritdoc IIRM
    function computeInterestRate(address vault, uint256 cash, uint256 borrows)
        external
        view
        override
        returns (uint256)
    {
        if (msg.sender != vault) revert E_IRMUpdateUnauthorized();

        return computeInterestRateInternal(vault, cash, borrows);
    }

    /// @inheritdoc IIRM
    function computeInterestRateView(address vault, uint256 cash, uint256 borrows)
        external
        view
        override
        returns (uint256)
    {
        return computeInterestRateInternal(vault, cash, borrows);
    }

    function computeInterestRateInternal(address, uint256 cash, uint256 borrows) internal view returns (uint256) {
        uint256 totalAssets = cash + borrows;

        uint32 utilization = totalAssets == 0
            ? 0 // empty pool arbitrarily given utilization of 0
            : uint32(borrows * type(uint32).max / totalAssets);

        uint256 ir = baseRate;

        if (utilization <= kink) {
            ir += utilization * slope1;
        } else {
            ir += kink * slope1;

            uint256 utilizationOverKink;
            unchecked {
                utilizationOverKink = utilization - kink;
            }
            ir += slope2 * utilizationOverKink;
        }

        return ir;
    }
}
设置
{
  "compilationTarget": {
    "src/IRMFactory/EulerKinkIRMFactory.sol": "EulerKinkIRMFactory"
  },
  "evmVersion": "cancun",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "remappings": [
    ":@chainlink/=lib/euler-price-oracle/node_modules/@chainlink/",
    ":@eth-optimism/=lib/euler-price-oracle/node_modules/@eth-optimism/contracts/",
    ":@openzeppelin/contracts/utils/math/=lib/euler-price-oracle/lib/openzeppelin-contracts/contracts/utils/math/",
    ":@pyth/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    ":@redstone-finance/=lib/euler-price-oracle/node_modules/@redstone-finance/",
    ":@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/",
    ":ds-test/=lib/fee-flow/lib/forge-std/lib/ds-test/src/",
    ":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    ":ethereum-vault-connector/=lib/ethereum-vault-connector/src/",
    ":euler-price-oracle-test/=lib/euler-price-oracle/test/",
    ":euler-price-oracle/=lib/euler-price-oracle/src/",
    ":euler-vault-kit/=lib/euler-vault-kit/src/",
    ":evc/=lib/ethereum-vault-connector/src/",
    ":evk-test/=lib/euler-vault-kit/test/",
    ":evk/=lib/euler-vault-kit/src/",
    ":fee-flow/=lib/fee-flow/src/",
    ":forge-gas-snapshot/=lib/euler-vault-kit/lib/permit2/lib/forge-gas-snapshot/src/",
    ":forge-std/=lib/forge-std/src/",
    ":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    ":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    ":openzeppelin/=lib/ethereum-vault-connector/lib/openzeppelin-contracts/contracts/",
    ":permit2/=lib/euler-vault-kit/lib/permit2/",
    ":pyth-sdk-solidity/=lib/euler-price-oracle/lib/pyth-sdk-solidity/",
    ":redstone-oracles-monorepo/=lib/euler-price-oracle/lib/",
    ":reward-streams/=lib/reward-streams/src/",
    ":solady/=lib/euler-price-oracle/lib/solady/src/",
    ":solmate/=lib/fee-flow/lib/solmate/src/",
    ":v3-core/=lib/euler-price-oracle/lib/v3-core/contracts/",
    ":v3-periphery/=lib/euler-price-oracle/lib/v3-periphery/contracts/"
  ]
}
ABI
[{"inputs":[],"name":"Factory_BadQuery","type":"error"},{"inputs":[],"name":"IRMFactory_ExcessiveInterestRate","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployedContract","type":"address"},{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":false,"internalType":"uint256","name":"deployedAt","type":"uint256"}],"name":"ContractDeployed","type":"event"},{"inputs":[{"internalType":"uint256","name":"baseRate","type":"uint256"},{"internalType":"uint256","name":"slope1","type":"uint256"},{"internalType":"uint256","name":"slope2","type":"uint256"},{"internalType":"uint32","name":"kink","type":"uint32"}],"name":"deploy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"deployments","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"getDeploymentInfo","outputs":[{"internalType":"address","name":"deployer","type":"address"},{"internalType":"uint96","name":"deployedAt","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeploymentsListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getDeploymentsListSlice","outputs":[{"internalType":"address[]","name":"list","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"isValidDeployment","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]