Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
15270727 | 930 days ago | 0.001 ETH | ||||
15270727 | 930 days ago | 0.001 ETH | ||||
15269122 | 930 days ago | 0.01137063 ETH | ||||
15269122 | 930 days ago | 0.01137063 ETH | ||||
15268470 | 930 days ago | 0.001 ETH | ||||
15268470 | 930 days ago | 0.001 ETH | ||||
15268460 | 930 days ago | 0.002 ETH | ||||
15268460 | 930 days ago | 0.002 ETH | ||||
15268440 | 930 days ago | 0.005 ETH | ||||
15268440 | 930 days ago | 0.005 ETH | ||||
15256156 | 932 days ago | 0.04 ETH | ||||
15256156 | 932 days ago | 0.04 ETH | ||||
15255927 | 932 days ago | 0.0001 ETH | ||||
15255927 | 932 days ago | 0.0001 ETH | ||||
15255921 | 932 days ago | 0.0001 ETH | ||||
15255921 | 932 days ago | 0.0001 ETH | ||||
15255910 | 932 days ago | 0.0001 ETH | ||||
15255910 | 932 days ago | 0.0001 ETH | ||||
15255748 | 932 days ago | 0.1 ETH | ||||
15255748 | 932 days ago | 0.1 ETH | ||||
15255644 | 932 days ago | 0.02 ETH | ||||
15255644 | 932 days ago | 0.02 ETH | ||||
15255546 | 932 days ago | 0.0022 ETH | ||||
15255546 | 932 days ago | 0.0022 ETH | ||||
15255510 | 932 days ago | 0.002 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
WstETHAdapter
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; // External references import { FixedMath } from "../../external/FixedMath.sol"; // Internal references import { BaseAdapter } from "../BaseAdapter.sol"; import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol"; interface WstETHLike { /// @notice https://github.com/lidofinance/lido-dao/blob/master/contracts/0.6.12/WstETH.sol /// @dev returns the current exchange rate of stETH to wstETH in wei (18 decimals) function stEthPerToken() external view returns (uint256); function unwrap(uint256 _wstETHAmount) external returns (uint256); function wrap(uint256 _stETHAmount) external returns (uint256); } interface StETHLike { /// @notice Send funds to the pool with optional _referral parameter /// @dev This function is alternative way to submit funds. Supports optional referral address. /// @return Amount of StETH shares generated function submit(address _referral) external payable returns (uint256); /// @return the amount of tokens owned by the `_account`. /// /// @dev Balances are dynamic and equal the `_account`'s share in the amount of the /// total Ether controlled by the protocol. See `sharesOf`. function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256); ///@return the amount of tokens owned by the `_account`. /// ///@dev Balances are dynamic and equal the `_account`'s share in the amount of the ///total Ether controlled by the protocol. See `sharesOf`. function balanceOf(address _account) external view returns (uint256); } interface CurveStableSwapLike { function get_dy( int128 i, int128 j, uint256 dx ) external view returns (uint256); function exchange( int128 i, int128 j, uint256 dx, uint256 min_dy ) external payable returns (uint256); } interface WETHLike { function deposit() external payable; function withdraw(uint256 wad) external; } interface StEthPriceFeedLike { function safe_price_value() external view returns (uint256); } /// @notice Adapter contract for wstETH contract WstETHAdapter is BaseAdapter { using FixedMath for uint256; using SafeTransferLib for ERC20; address public constant CETH = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5; address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public constant WSTETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; address public constant STETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; address public constant CURVESINGLESWAP = 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022; address public constant STETHPRICEFEED = 0xAb55Bf4DfBf469ebfe082b7872557D1F87692Fe6; // On 2022.02.28, a swap from 100k stETH ($250m+ worth) to ETH was quoted // by https://curve.fi/steth to incur 0.39% slippage, so we went with 0.5% // to capture practically all unwrap/wrap sizes through the Sense adapter." uint256 public constant SLIPPAGE_TOLERANCE = 0.005e18; /// @notice Cached scale value from the last call to `scale()` uint256 public override scaleStored; constructor( address _divider, address _target, address _underlying, uint128 _ifee, BaseAdapter.AdapterParams memory _adapterParams ) BaseAdapter(_divider, _target, _underlying, _ifee, _adapterParams) { // approve wstETH contract to pull stETH (used on wrapUnderlying()) ERC20(STETH).approve(WSTETH, type(uint256).max); // approve Curve stETH/ETH pool to pull stETH (used on unwrapTarget()) ERC20(STETH).approve(CURVESINGLESWAP, type(uint256).max); // set an inital cached scale value scaleStored = _wstEthToEthRate(); } /// @return exRate Eth per wstEtH (natively in 18 decimals) function scale() external virtual override returns (uint256 exRate) { exRate = _wstEthToEthRate(); if (exRate != scaleStored) { // update value only if different than the previous scaleStored = exRate; } } function getUnderlyingPrice() external pure override returns (uint256 price) { price = 1e18; } function unwrapTarget(uint256 amount) external override returns (uint256 eth) { ERC20(WSTETH).safeTransferFrom(msg.sender, address(this), amount); // pull wstETH uint256 stEth = WstETHLike(WSTETH).unwrap(amount); // unwrap wstETH into stETH // exchange stETH to ETH exchange on Curve // to calculate the minDy, we use Lido's safe_price_value() which should prevent from flash loan / sandwhich attacks // and we are also adding a slippage tolerance of 0.5% uint256 stEthEth = StEthPriceFeedLike(STETHPRICEFEED).safe_price_value(); // returns the cached stETH/ETH safe price eth = CurveStableSwapLike(CURVESINGLESWAP).exchange( int128(1), int128(0), stEth, stEthEth.fmul(stEth).fmul(FixedMath.WAD - SLIPPAGE_TOLERANCE) ); // deposit ETH into WETH contract (bool success, ) = WETH.call{ value: eth }(""); if (!success) revert Errors.TransferFailed(); ERC20(WETH).safeTransfer(msg.sender, eth); // transfer WETH back to sender (periphery) } function wrapUnderlying(uint256 amount) external override returns (uint256 wstETH) { ERC20(WETH).safeTransferFrom(msg.sender, address(this), amount); // pull WETH WETHLike(WETH).withdraw(amount); // unwrap WETH into ETH StETHLike(STETH).submit{ value: amount }(address(0)); // stake ETH (returns wstETH) uint256 stEth = StETHLike(STETH).balanceOf(address(this)); ERC20(WSTETH).safeTransfer(msg.sender, wstETH = WstETHLike(WSTETH).wrap(stEth)); // transfer wstETH to msg.sender } function _wstEthToEthRate() internal view returns (uint256 exRate) { // In order to account for the stETH/ETH CurveStableSwap rate, // we use `safe_price_value` from Lido's stETH price feed. // https://docs.lido.fi/contracts/steth-price-feed#steth-price-feed-specification uint256 stEthEth = StEthPriceFeedLike(STETHPRICEFEED).safe_price_value(); // returns the cached stETH/ETH safe price uint256 wstETHstETH = StETHLike(STETH).getPooledEthByShares(1 ether); // stETH tokens per one wstETH exRate = stEthEth.fmul(wstETHstETH); } fallback() external payable { if (msg.sender != WETH && msg.sender != CURVESINGLESWAP) revert Errors.SenderNotEligible(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; /// @title Fixed point arithmetic library /// @author Taken from https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol library FixedMath { uint256 internal constant WAD = 1e18; uint256 internal constant RAY = 1e27; function fmul( uint256 x, uint256 y, uint256 baseUnit ) internal pure returns (uint256) { return mulDivDown(x, y, baseUnit); // Equivalent to (x * y) / baseUnit rounded down. } function fmul(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function fmulUp( uint256 x, uint256 y, uint256 baseUnit ) internal pure returns (uint256) { return mulDivUp(x, y, baseUnit); // Equivalent to (x * y) / baseUnit rounded up. } function fmulUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function fdiv( uint256 x, uint256 y, uint256 baseUnit ) internal pure returns (uint256) { return mulDivDown(x, baseUnit, y); // Equivalent to (x * baseUnit) / y rounded down. } function fdiv(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function fdivUp( uint256 x, uint256 y, uint256 baseUnit ) internal pure returns (uint256) { return mulDivUp(x, baseUnit, y); // Equivalent to (x * baseUnit) / y rounded up. } function fdivUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; // External references import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import { IERC3156FlashLender } from "../external/flashloan/IERC3156FlashLender.sol"; import { IERC3156FlashBorrower } from "../external/flashloan/IERC3156FlashBorrower.sol"; // Internal references import { Divider } from "../Divider.sol"; import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol"; /// @title Assign value to Target tokens abstract contract BaseAdapter is IERC3156FlashLender { using SafeTransferLib for ERC20; /* ========== CONSTANTS ========== */ bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); /* ========== PUBLIC IMMUTABLES ========== */ /// @notice Sense core Divider address address public immutable divider; /// @notice Target token to divide address public immutable target; /// @notice Underlying for the Target address public immutable underlying; /// @notice Issuance fee uint128 public immutable ifee; /// @notice adapter params AdapterParams public adapterParams; /* ========== DATA STRUCTURES ========== */ struct AdapterParams { /// @notice Oracle address address oracle; /// @notice Token to stake at issuance address stake; /// @notice Amount to stake at issuance uint256 stakeSize; /// @notice Min maturity (seconds after block.timstamp) uint256 minm; /// @notice Max maturity (seconds after block.timstamp) uint256 maxm; /// @notice WAD number representing the percentage of the total /// principal that's set aside for Yield Tokens (e.g. 0.1e18 means that 10% of the principal is reserved). /// @notice If `0`, it means no principal is set aside for Yield Tokens uint64 tilt; /// @notice The number this function returns will be used to determine its access by checking for binary /// digits using the following scheme: <onRedeem(y/n)><collect(y/n)><combine(y/n)><issue(y/n)> /// (e.g. 0101 enables `collect` and `issue`, but not `combine`) uint48 level; /// @notice 0 for monthly, 1 for weekly uint16 mode; } /* ========== METADATA STORAGE ========== */ string public name; string public symbol; constructor( address _divider, address _target, address _underlying, uint128 _ifee, AdapterParams memory _adapterParams ) { divider = _divider; target = _target; underlying = _underlying; ifee = _ifee; adapterParams = _adapterParams; name = string(abi.encodePacked(ERC20(_target).name(), " Adapter")); symbol = string(abi.encodePacked(ERC20(_target).symbol(), "-adapter")); ERC20(_target).approve(divider, type(uint256).max); ERC20(_adapterParams.stake).approve(divider, type(uint256).max); } /// @notice Loan `amount` target to `receiver`, and takes it back after the callback. /// @param receiver The contract receiving target, needs to implement the /// `onFlashLoan(address user, address adapter, uint256 maturity, uint256 amount)` interface. /// @param amount The amount of target lent. /// @param data (encoded adapter address, maturity and YT amount the use has sent in) function flashLoan( IERC3156FlashBorrower receiver, address, /* fee */ uint256 amount, bytes calldata data ) external returns (bool) { if (Divider(divider).periphery() != msg.sender) revert Errors.OnlyPeriphery(); ERC20(target).safeTransfer(address(receiver), amount); bytes32 keccak = IERC3156FlashBorrower(receiver).onFlashLoan(msg.sender, target, amount, 0, data); if (keccak != CALLBACK_SUCCESS) revert Errors.FlashCallbackFailed(); ERC20(target).safeTransferFrom(address(receiver), address(this), amount); return true; } /* ========== REQUIRED VALUE GETTERS ========== */ /// @notice Calculate and return this adapter's Scale value for the current timestamp. To be overriden by child contracts /// @dev For some Targets, such as cTokens, this is simply the exchange rate, or `supply cToken / supply underlying` /// @dev For other Targets, such as AMM LP shares, specialized logic will be required /// @dev This function _must_ return a WAD number representing the current exchange rate /// between the Target and the Underlying. /// @return value WAD Scale value function scale() external virtual returns (uint256); /// @notice Cached scale value getter /// @dev For situations where you need scale from a view function function scaleStored() external view virtual returns (uint256); /// @notice Returns the current price of the underlying in ETH terms function getUnderlyingPrice() external view virtual returns (uint256); /* ========== REQUIRED UTILITIES ========== */ /// @notice Deposits underlying `amount`in return for target. Must be overriden by child contracts /// @param amount Underlying amount /// @return amount of target returned function wrapUnderlying(uint256 amount) external virtual returns (uint256); /// @notice Deposits target `amount`in return for underlying. Must be overriden by child contracts /// @param amount Target amount /// @return amount of underlying returned function unwrapTarget(uint256 amount) external virtual returns (uint256); function flashFee(address token, uint256) external view returns (uint256) { if (token != target) revert Errors.TokenNotSupported(); return 0; } function maxFlashLoan(address token) external view override returns (uint256) { return ERC20(token).balanceOf(address(this)); } /* ========== OPTIONAL HOOKS ========== */ /// @notice Notification whenever the Divider adds or removes Target function notify( address, /* usr */ uint256, /* amt */ bool /* join */ ) public virtual { return; } /// @notice Hook called whenever a user redeems PT function onRedeem( uint256, /* uBal */ uint256, /* mscale */ uint256, /* maxscale */ uint256 /* tBal */ ) public virtual { return; } /* ========== PUBLIC STORAGE ACCESSORS ========== */ function getMaturityBounds() external view virtual returns (uint256, uint256) { return (adapterParams.minm, adapterParams.maxm); } function getStakeAndTarget() external view returns ( address, address, uint256 ) { return (target, adapterParams.stake, adapterParams.stakeSize); } function mode() external view returns (uint256) { return adapterParams.mode; } function tilt() external view returns (uint256) { return adapterParams.tilt; } function level() external view returns (uint256) { return adapterParams.level; } }
pragma solidity ^0.8.0; import "./IERC3156FlashBorrower.sol"; interface IERC3156FlashLender { /// @dev The amount of currency available to be lent. /// @param token The loan currency. /// @return The amount of `token` that can be borrowed. function maxFlashLoan(address token) external view returns (uint256); /// @dev The fee to be charged for a given loan. /// @param token The loan currency. /// @param amount The amount of tokens lent. /// @return The amount of `token` to be charged for the loan, on top of the returned principal. function flashFee(address token, uint256 amount) external view returns (uint256); /// @dev Initiate a flash loan. /// @param receiver The receiver of the tokens in the loan, and the receiver of the callback. /// @param token The loan currency. /// @param amount The amount of tokens lent. /// @param data Arbitrary data structure, intended to contain user-defined parameters. function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); }
pragma solidity ^0.8.0; interface IERC3156FlashBorrower { /// @dev Receive a flash loan. /// @param initiator The initiator of the loan. /// @param token The loan currency. /// @param amount The amount of tokens lent. /// @param fee The additional amount of tokens to repay. /// @param data Arbitrary data structure, intended to contain user-defined parameters. /// @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; // External references import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol"; import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import { ReentrancyGuard } from "@rari-capital/solmate/src/utils/ReentrancyGuard.sol"; import { DateTime } from "./external/DateTime.sol"; import { FixedMath } from "./external/FixedMath.sol"; // Internal references import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol"; import { Levels } from "@sense-finance/v1-utils/src/libs/Levels.sol"; import { Trust } from "@sense-finance/v1-utils/src/Trust.sol"; import { YT } from "./tokens/YT.sol"; import { Token } from "./tokens/Token.sol"; import { BaseAdapter as Adapter } from "./adapters/BaseAdapter.sol"; /// @title Sense Divider: Divide Assets in Two /// @author fedealconada + jparklev /// @notice You can use this contract to issue, combine, and redeem Sense ERC20 Principal and Yield Tokens contract Divider is Trust, ReentrancyGuard, Pausable { using SafeTransferLib for ERC20; using FixedMath for uint256; using Levels for uint256; /* ========== PUBLIC CONSTANTS ========== */ /// @notice Buffer before and after the actual maturity in which only the sponsor can settle the Series uint256 public constant SPONSOR_WINDOW = 3 hours; /// @notice Buffer after the sponsor window in which anyone can settle the Series uint256 public constant SETTLEMENT_WINDOW = 3 hours; /// @notice 5% issuance fee cap uint256 public constant ISSUANCE_FEE_CAP = 0.05e18; /* ========== PUBLIC MUTABLE STORAGE ========== */ address public periphery; /// @notice Sense community multisig address public immutable cup; /// @notice Principal/Yield tokens deployer address public immutable tokenHandler; /// @notice Permissionless flag bool public permissionless; /// @notice Guarded launch flag bool public guarded = true; /// @notice Number of adapters (including turned off) uint248 public adapterCounter; /// @notice adapter ID -> adapter address mapping(uint256 => address) public adapterAddresses; /// @notice adapter data mapping(address => AdapterMeta) public adapterMeta; /// @notice adapter -> maturity -> Series mapping(address => mapping(uint256 => Series)) public series; /// @notice adapter -> maturity -> user -> lscale (last scale) mapping(address => mapping(uint256 => mapping(address => uint256))) public lscales; /* ========== DATA STRUCTURES ========== */ struct Series { // Principal ERC20 token address pt; // Timestamp of series initialization uint48 issuance; // Yield ERC20 token address yt; // % of underlying principal initially reserved for Yield uint96 tilt; // Actor who initialized the Series address sponsor; // Tracks fees due to the series' settler uint256 reward; // Scale at issuance uint256 iscale; // Scale at maturity uint256 mscale; // Max scale value from this series' lifetime uint256 maxscale; } struct AdapterMeta { // Adapter ID uint248 id; // Adapter enabled/disabled bool enabled; // Max amount of Target allowed to be issued uint256 guard; // Adapter level uint248 level; } constructor(address _cup, address _tokenHandler) Trust(msg.sender) { cup = _cup; tokenHandler = _tokenHandler; } /* ========== MUTATIVE FUNCTIONS ========== */ /// @notice Enable an adapter /// @dev when permissionless is disabled, only the Periphery can onboard adapters /// @dev after permissionless is enabled, anyone can onboard adapters /// @param adapter Adapter's address function addAdapter(address adapter) external whenNotPaused { if (!permissionless && msg.sender != periphery) revert Errors.OnlyPermissionless(); if (adapterMeta[adapter].id > 0 && !adapterMeta[adapter].enabled) revert Errors.InvalidAdapter(); _setAdapter(adapter, true); } /// @notice Initializes a new Series /// @dev Deploys two ERC20 contracts, one for PTs and the other one for YTs /// @dev Transfers some fixed amount of stake asset to this contract /// @param adapter Adapter to associate with the Series /// @param maturity Maturity date for the new Series, in units of unix time /// @param sponsor Sponsor of the Series that puts up a token stake and receives the issuance fees function initSeries( address adapter, uint256 maturity, address sponsor ) external nonReentrant whenNotPaused returns (address pt, address yt) { if (periphery != msg.sender) revert Errors.OnlyPeriphery(); if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter(); if (_exists(adapter, maturity)) revert Errors.DuplicateSeries(); if (!_isValid(adapter, maturity)) revert Errors.InvalidMaturity(); // Transfer stake asset stake from caller to adapter (address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget(); // Deploy Principal & Yield Tokens for this new Series (pt, yt) = TokenHandler(tokenHandler).deploy(adapter, adapterMeta[adapter].id, maturity); // Initialize the new Series struct uint256 scale = Adapter(adapter).scale(); series[adapter][maturity].pt = pt; series[adapter][maturity].issuance = uint48(block.timestamp); series[adapter][maturity].yt = yt; series[adapter][maturity].tilt = uint96(Adapter(adapter).tilt()); series[adapter][maturity].sponsor = sponsor; series[adapter][maturity].iscale = scale; series[adapter][maturity].maxscale = scale; ERC20(stake).safeTransferFrom(msg.sender, adapter, stakeSize); emit SeriesInitialized(adapter, maturity, pt, yt, sponsor, target); } /// @notice Settles a Series and transfers the settlement reward to the caller /// @dev The Series' sponsor has a grace period where only they can settle the Series /// @dev After that, the reward becomes MEV /// @param adapter Adapter to associate with the Series /// @param maturity Maturity date for the new Series function settleSeries(address adapter, uint256 maturity) external nonReentrant whenNotPaused { if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter(); if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist(); if (_settled(adapter, maturity)) revert Errors.AlreadySettled(); if (!_canBeSettled(adapter, maturity)) revert Errors.OutOfWindowBoundaries(); // The maturity scale value is all a Series needs for us to consider it "settled" uint256 mscale = Adapter(adapter).scale(); series[adapter][maturity].mscale = mscale; if (mscale > series[adapter][maturity].maxscale) { series[adapter][maturity].maxscale = mscale; } // Reward the caller for doing the work of settling the Series at around the correct time (address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget(); ERC20(target).safeTransferFrom(adapter, msg.sender, series[adapter][maturity].reward); ERC20(stake).safeTransferFrom(adapter, msg.sender, stakeSize); emit SeriesSettled(adapter, maturity, msg.sender); } /// @notice Mint Principal & Yield Tokens of a specific Series /// @param adapter Adapter address for the Series /// @param maturity Maturity date for the Series [unix time] /// @param tBal Balance of Target to deposit /// @dev The balance of PTs and YTs minted will be the same value in units of underlying (less fees) function issue( address adapter, uint256 maturity, uint256 tBal ) external nonReentrant whenNotPaused returns (uint256 uBal) { if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter(); if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist(); if (_settled(adapter, maturity)) revert Errors.IssueOnSettle(); uint256 level = adapterMeta[adapter].level; if (level.issueRestricted() && msg.sender != adapter) revert Errors.IssuanceRestricted(); ERC20 target = ERC20(Adapter(adapter).target()); // Take the issuance fee out of the deposited Target, and put it towards the settlement reward uint256 issuanceFee = Adapter(adapter).ifee(); if (issuanceFee > ISSUANCE_FEE_CAP) revert Errors.IssuanceFeeCapExceeded(); uint256 fee = tBal.fmul(issuanceFee); unchecked { // Safety: bounded by the Target's total token supply series[adapter][maturity].reward += fee; } uint256 tBalSubFee = tBal - fee; // Ensure the caller won't hit the issuance cap with this action unchecked { // Safety: bounded by the Target's total token supply if (guarded && target.balanceOf(adapter) + tBal > adapterMeta[address(adapter)].guard) revert Errors.GuardCapReached(); } // Update values on adapter Adapter(adapter).notify(msg.sender, tBalSubFee, true); uint256 scale = level.collectDisabled() ? series[adapter][maturity].iscale : Adapter(adapter).scale(); // Determine the amount of Underlying equal to the Target being sent in (the principal) uBal = tBalSubFee.fmul(scale); // If the caller has not collected on YT before, use the current scale, otherwise // use the harmonic mean of the last and the current scale value lscales[adapter][maturity][msg.sender] = lscales[adapter][maturity][msg.sender] == 0 ? scale : _reweightLScale( adapter, maturity, YT(series[adapter][maturity].yt).balanceOf(msg.sender), uBal, msg.sender, scale ); // Mint equal amounts of PT and YT Token(series[adapter][maturity].pt).mint(msg.sender, uBal); YT(series[adapter][maturity].yt).mint(msg.sender, uBal); target.safeTransferFrom(msg.sender, adapter, tBal); emit Issued(adapter, maturity, uBal, msg.sender); } /// @notice Reconstitute Target by burning PT and YT /// @dev Explicitly burns YTs before maturity, and implicitly does it at/after maturity through `_collect()` /// @param adapter Adapter address for the Series /// @param maturity Maturity date for the Series /// @param uBal Balance of PT and YT to burn function combine( address adapter, uint256 maturity, uint256 uBal ) external nonReentrant whenNotPaused returns (uint256 tBal) { if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter(); if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist(); uint256 level = adapterMeta[adapter].level; if (level.combineRestricted() && msg.sender != adapter) revert Errors.CombineRestricted(); // Burn the PT Token(series[adapter][maturity].pt).burn(msg.sender, uBal); // Collect whatever excess is due uint256 collected = _collect(msg.sender, adapter, maturity, uBal, uBal, address(0)); uint256 cscale = series[adapter][maturity].mscale; bool settled = _settled(adapter, maturity); if (!settled) { // If it's not settled, then YT won't be burned automatically in `_collect()` YT(series[adapter][maturity].yt).burn(msg.sender, uBal); // If collect has been restricted, use the initial scale, otherwise use the current scale cscale = level.collectDisabled() ? series[adapter][maturity].iscale : lscales[adapter][maturity][msg.sender]; } // Convert from units of Underlying to units of Target tBal = uBal.fdiv(cscale); ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, msg.sender, tBal); // Notify only when Series is not settled as when it is, the _collect() call above would trigger a _redeemYT which will call notify if (!settled) Adapter(adapter).notify(msg.sender, tBal, false); unchecked { // Safety: bounded by the Target's total token supply tBal += collected; } emit Combined(adapter, maturity, tBal, msg.sender); } /// @notice Burn PT of a Series once it's been settled /// @dev The balance of redeemable Target is a function of the change in Scale /// @param adapter Adapter address for the Series /// @param maturity Maturity date for the Series /// @param uBal Amount of PT to burn, which should be equivalent to the amount of Underlying owed to the caller function redeem( address adapter, uint256 maturity, uint256 uBal ) external nonReentrant whenNotPaused returns (uint256 tBal) { // If a Series is settled, we know that it must have existed as well, so that check is unnecessary if (!_settled(adapter, maturity)) revert Errors.NotSettled(); uint256 level = adapterMeta[adapter].level; if (level.redeemRestricted() && msg.sender == adapter) revert Errors.RedeemRestricted(); // Burn the caller's PT Token(series[adapter][maturity].pt).burn(msg.sender, uBal); // Principal Token holder's share of the principal = (1 - part of the principal that belongs to Yield) uint256 zShare = FixedMath.WAD - series[adapter][maturity].tilt; // If Principal Token are at a loss and Yield have some principal to help cover the shortfall, // take what we can from Yield Token's principal if (series[adapter][maturity].mscale.fdiv(series[adapter][maturity].maxscale) >= zShare) { tBal = (uBal * zShare) / series[adapter][maturity].mscale; } else { tBal = uBal.fdiv(series[adapter][maturity].maxscale); } if (!level.redeemHookDisabled()) { Adapter(adapter).onRedeem(uBal, series[adapter][maturity].mscale, series[adapter][maturity].maxscale, tBal); } ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, msg.sender, tBal); emit PTRedeemed(adapter, maturity, tBal); } function collect( address usr, address adapter, uint256 maturity, uint256 uBalTransfer, address to ) external nonReentrant onlyYT(adapter, maturity) whenNotPaused returns (uint256 collected) { uint256 uBal = YT(msg.sender).balanceOf(usr); return _collect(usr, adapter, maturity, uBal, uBalTransfer > 0 ? uBalTransfer : uBal, to); } /// @notice Collect YT excess before, at, or after maturity /// @dev If `to` is set, we copy the lscale value from usr to this address /// @param usr User who's collecting for their YTs /// @param adapter Adapter address for the Series /// @param maturity Maturity date for the Series /// @param uBal yield Token balance /// @param uBalTransfer original transfer value /// @param to address to set the lscale value from usr function _collect( address usr, address adapter, uint256 maturity, uint256 uBal, uint256 uBalTransfer, address to ) internal returns (uint256 collected) { if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist(); // If the adapter is disabled, its Yield Token can only collect // if associated Series has been settled, which implies that an admin // has backfilled it if (!adapterMeta[adapter].enabled && !_settled(adapter, maturity)) revert Errors.InvalidAdapter(); Series memory _series = series[adapter][maturity]; // Get the scale value from the last time this holder collected (default to maturity) uint256 lscale = lscales[adapter][maturity][usr]; uint256 level = adapterMeta[adapter].level; if (level.collectDisabled()) { // If this Series has been settled, we ensure everyone's YT will // collect yield accrued since issuance if (_settled(adapter, maturity)) { lscale = series[adapter][maturity].iscale; // If the Series is not settled, we ensure no collections can happen } else { return 0; } } // If the Series has been settled, this should be their last collect, so redeem the user's Yield Tokens for them if (_settled(adapter, maturity)) { _redeemYT(usr, adapter, maturity, uBal); } else { // If we're not settled and we're past maturity + the sponsor window, // anyone can settle this Series so revert until someone does if (block.timestamp > maturity + SPONSOR_WINDOW) { revert Errors.CollectNotSettled(); // Otherwise, this is a valid pre-settlement collect and we need to determine the scale value } else { uint256 cscale = Adapter(adapter).scale(); // If this is larger than the largest scale we've seen for this Series, use it if (cscale > _series.maxscale) { _series.maxscale = cscale; lscales[adapter][maturity][usr] = cscale; // If not, use the previously noted max scale value } else { lscales[adapter][maturity][usr] = _series.maxscale; } } } // Determine how much underlying has accrued since the last time this user collected, in units of Target. // (Or take the last time as issuance if they haven't yet) // // Reminder: `Underlying / Scale = Target` // So the following equation is saying, for some amount of Underlying `u`: // "Balance of Target that equaled `u` at the last collection _minus_ Target that equals `u` now" // // Because maxscale must be increasing, the Target balance needed to equal `u` decreases, and that "excess" // is what Yield holders are collecting uint256 tBalNow = uBal.fdivUp(_series.maxscale); // preventive round-up towards the protocol uint256 tBalPrev = uBal.fdiv(lscale); unchecked { collected = tBalPrev > tBalNow ? tBalPrev - tBalNow : 0; } ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, usr, collected); Adapter(adapter).notify(usr, collected, false); // Distribute reward tokens // If this collect is a part of a token transfer to another address, set the receiver's // last collection to a synthetic scale weighted based on the scale on their last collect, // the time elapsed, and the current scale if (to != address(0)) { uint256 ytBal = YT(_series.yt).balanceOf(to); // If receiver holds yields, we set lscale to a computed "synthetic" lscales value that, // for the updated yield balance, still assigns the correct amount of yield. lscales[adapter][maturity][to] = ytBal > 0 ? _reweightLScale(adapter, maturity, ytBal, uBalTransfer, to, _series.maxscale) : _series.maxscale; uint256 tBalTransfer = uBalTransfer.fdiv(_series.maxscale); Adapter(adapter).notify(usr, tBalTransfer, false); Adapter(adapter).notify(to, tBalTransfer, true); } series[adapter][maturity] = _series; emit Collected(adapter, maturity, collected); } /// @notice calculate the harmonic mean of the current scale and the last scale, /// weighted by amounts associated with each function _reweightLScale( address adapter, uint256 maturity, uint256 ytBal, uint256 uBal, address receiver, uint256 scale ) internal view returns (uint256) { // Target Decimals * 18 Decimals [from fdiv] / (Target Decimals * 18 Decimals [from fdiv] / 18 Decimals) // = 18 Decimals, which is the standard for scale values return (ytBal + uBal).fdiv((ytBal.fdiv(lscales[adapter][maturity][receiver]) + uBal.fdiv(scale))); } function _redeemYT( address usr, address adapter, uint256 maturity, uint256 uBal ) internal { // Burn the users's YTs YT(series[adapter][maturity].yt).burn(usr, uBal); // Default principal for a YT uint256 tBal = 0; // Principal Token holder's share of the principal = (1 - part of the principal that belongs to Yield Tokens) uint256 zShare = FixedMath.WAD - series[adapter][maturity].tilt; // If PTs are at a loss and YTs had their principal cut to help cover the shortfall, // calculate how much YTs have left if (series[adapter][maturity].mscale.fdiv(series[adapter][maturity].maxscale) >= zShare) { tBal = uBal.fdiv(series[adapter][maturity].maxscale) - (uBal * zShare) / series[adapter][maturity].mscale; ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, usr, tBal); } // Always notify the Adapter of the full Target balance that will no longer // have its rewards distributed Adapter(adapter).notify(usr, uBal.fdivUp(series[adapter][maturity].maxscale), false); emit YTRedeemed(adapter, maturity, tBal); } /* ========== ADMIN ========== */ /// @notice Enable or disable a adapter /// @param adapter Adapter's address /// @param isOn Flag setting this adapter to enabled or disabled function setAdapter(address adapter, bool isOn) public requiresTrust { _setAdapter(adapter, isOn); } /// @notice Set adapter's guard /// @param adapter Adapter address /// @param cap The max target that can be deposited on the Adapter function setGuard(address adapter, uint256 cap) external requiresTrust { adapterMeta[adapter].guard = cap; emit GuardChanged(adapter, cap); } /// @notice Set guarded mode /// @param _guarded bool function setGuarded(bool _guarded) external requiresTrust { guarded = _guarded; emit GuardedChanged(_guarded); } /// @notice Set periphery's contract /// @param _periphery Target address function setPeriphery(address _periphery) external requiresTrust { periphery = _periphery; emit PeripheryChanged(_periphery); } /// @notice Set paused flag /// @param _paused boolean function setPaused(bool _paused) external requiresTrust { _paused ? _pause() : _unpause(); } /// @notice Set permissioless mode /// @param _permissionless bool function setPermissionless(bool _permissionless) external requiresTrust { permissionless = _permissionless; emit PermissionlessChanged(_permissionless); } /// @notice Backfill a Series' Scale value at maturity if keepers failed to settle it /// @param adapter Adapter's address /// @param maturity Maturity date for the Series /// @param mscale Value to set as the Series' Scale value at maturity /// @param _usrs Values to set on lscales mapping /// @param _lscales Values to set on lscales mapping function backfillScale( address adapter, uint256 maturity, uint256 mscale, address[] calldata _usrs, uint256[] calldata _lscales ) external requiresTrust { if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist(); uint256 cutoff = maturity + SPONSOR_WINDOW + SETTLEMENT_WINDOW; // Admin can never backfill before maturity if (block.timestamp <= cutoff) revert Errors.OutOfWindowBoundaries(); // Set user's last scale values the Series (needed for the `collect` method) for (uint256 i = 0; i < _usrs.length; i++) { lscales[adapter][maturity][_usrs[i]] = _lscales[i]; } if (mscale > 0) { Series memory _series = series[adapter][maturity]; // Set the maturity scale for the Series (needed for `redeem` methods) series[adapter][maturity].mscale = mscale; if (mscale > _series.maxscale) { series[adapter][maturity].maxscale = mscale; } (address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget(); address stakeDst = adapterMeta[adapter].enabled ? cup : _series.sponsor; ERC20(target).safeTransferFrom(adapter, cup, _series.reward); series[adapter][maturity].reward = 0; ERC20(stake).safeTransferFrom(adapter, stakeDst, stakeSize); } emit Backfilled(adapter, maturity, mscale, _usrs, _lscales); } /* ========== INTERNAL VIEWS ========== */ function _exists(address adapter, uint256 maturity) internal view returns (bool) { return series[adapter][maturity].pt != address(0); } function _settled(address adapter, uint256 maturity) internal view returns (bool) { return series[adapter][maturity].mscale > 0; } function _canBeSettled(address adapter, uint256 maturity) internal view returns (bool) { uint256 cutoff = maturity + SPONSOR_WINDOW + SETTLEMENT_WINDOW; // If the sender is the sponsor for the Series if (msg.sender == series[adapter][maturity].sponsor) { return maturity - SPONSOR_WINDOW <= block.timestamp && cutoff >= block.timestamp; } else { return maturity + SPONSOR_WINDOW < block.timestamp && cutoff >= block.timestamp; } } function _isValid(address adapter, uint256 maturity) internal view returns (bool) { (uint256 minm, uint256 maxm) = Adapter(adapter).getMaturityBounds(); if (maturity < block.timestamp + minm || maturity > block.timestamp + maxm) return false; (, , uint256 day, uint256 hour, uint256 minute, uint256 second) = DateTime.timestampToDateTime(maturity); if (hour != 0 || minute != 0 || second != 0) return false; uint256 mode = Adapter(adapter).mode(); if (mode == 0) { return day == 1; } if (mode == 1) { return DateTime.getDayOfWeek(maturity) == 1; } return false; } /* ========== INTERNAL UTILS ========== */ function _setAdapter(address adapter, bool isOn) internal { AdapterMeta memory am = adapterMeta[adapter]; if (am.enabled == isOn) revert Errors.ExistingValue(); am.enabled = isOn; // If this adapter is being added for the first time if (isOn && am.id == 0) { am.id = ++adapterCounter; adapterAddresses[am.id] = adapter; } // Set level and target (can only be done once); am.level = uint248(Adapter(adapter).level()); adapterMeta[adapter] = am; emit AdapterChanged(adapter, am.id, isOn); } /* ========== PUBLIC GETTERS ========== */ /// @notice Returns address of Principal Token function pt(address adapter, uint256 maturity) public view returns (address) { return series[adapter][maturity].pt; } /// @notice Returns address of Yield Token function yt(address adapter, uint256 maturity) public view returns (address) { return series[adapter][maturity].yt; } function mscale(address adapter, uint256 maturity) public view returns (uint256) { return series[adapter][maturity].mscale; } /* ========== MODIFIERS ========== */ modifier onlyYT(address adapter, uint256 maturity) { if (series[adapter][maturity].yt != msg.sender) revert Errors.OnlyYT(); _; } /* ========== LOGS ========== */ /// @notice Admin event Backfilled( address indexed adapter, uint256 indexed maturity, uint256 mscale, address[] _usrs, uint256[] _lscales ); event GuardChanged(address indexed adapter, uint256 cap); event AdapterChanged(address indexed adapter, uint256 indexed id, bool indexed isOn); event PeripheryChanged(address indexed periphery); /// @notice Series lifecycle /// *---- beginning event SeriesInitialized( address adapter, uint256 indexed maturity, address pt, address yt, address indexed sponsor, address indexed target ); /// -***- middle event Issued(address indexed adapter, uint256 indexed maturity, uint256 balance, address indexed sender); event Combined(address indexed adapter, uint256 indexed maturity, uint256 balance, address indexed sender); event Collected(address indexed adapter, uint256 indexed maturity, uint256 collected); /// ----* end event SeriesSettled(address indexed adapter, uint256 indexed maturity, address indexed settler); event PTRedeemed(address indexed adapter, uint256 indexed maturity, uint256 redeemed); event YTRedeemed(address indexed adapter, uint256 indexed maturity, uint256 redeemed); /// *----* misc event GuardedChanged(bool indexed guarded); event PermissionlessChanged(bool indexed permissionless); } contract TokenHandler is Trust { /// @notice Program state address public divider; constructor() Trust(msg.sender) {} function init(address _divider) external requiresTrust { if (divider != address(0)) revert Errors.AlreadyInitialized(); divider = _divider; } function deploy( address adapter, uint248 id, uint256 maturity ) external returns (address pt, address yt) { if (msg.sender != divider) revert Errors.OnlyDivider(); ERC20 target = ERC20(Adapter(adapter).target()); uint8 decimals = target.decimals(); string memory symbol = target.symbol(); (string memory d, string memory m, string memory y) = DateTime.toDateString(maturity); string memory date = DateTime.format(maturity); string memory datestring = string(abi.encodePacked(d, "-", m, "-", y)); string memory adapterId = DateTime.uintToString(id); pt = address( new Token( string(abi.encodePacked(date, " ", symbol, " Sense Principal Token, A", adapterId)), string(abi.encodePacked("sP-", symbol, ":", datestring, ":", adapterId)), decimals, divider ) ); yt = address( new YT( adapter, maturity, string(abi.encodePacked(date, " ", symbol, " Sense Yield Token, A", adapterId)), string(abi.encodePacked("sY-", symbol, ":", datestring, ":", adapterId)), decimals, divider ) ); } }
pragma solidity 0.8.11; /// @author Taken from: https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary library DateTime { uint256 constant SECONDS_PER_DAY = 24 * 60 * 60; uint256 constant SECONDS_PER_HOUR = 60 * 60; uint256 constant SECONDS_PER_MINUTE = 60; int256 constant OFFSET19700101 = 2440588; function timestampToDate(uint256 timestamp) internal pure returns ( uint256 year, uint256 month, uint256 day ) { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); } function timestampToDateTime(uint256 timestamp) internal pure returns ( uint256 year, uint256 month, uint256 day, uint256 hour, uint256 minute, uint256 second ) { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint256 secs = timestamp % SECONDS_PER_DAY; hour = secs / SECONDS_PER_HOUR; secs = secs % SECONDS_PER_HOUR; minute = secs / SECONDS_PER_MINUTE; second = secs % SECONDS_PER_MINUTE; } function toDateString(uint256 _timestamp) internal pure returns ( string memory d, string memory m, string memory y ) { (uint256 year, uint256 month, uint256 day) = timestampToDate(_timestamp); d = uintToString(day); m = uintToString(month); y = uintToString(year); // append a 0 to numbers < 10 so we should, e.g, 01 instead of just 1 if (day < 10) d = string(abi.encodePacked("0", d)); if (month < 10) m = string(abi.encodePacked("0", m)); } function format(uint256 _timestamp) internal pure returns (string memory datestring) { string[12] memory months = [ "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" ]; (uint256 year, uint256 month, uint256 day) = timestampToDate(_timestamp); uint256 last = day % 10; string memory suffix = "th"; if (day < 11 || day > 20) { if (last == 1) suffix = "st"; if (last == 2) suffix = "nd"; if (last == 3) suffix = "rd"; } return string(abi.encodePacked(uintToString(day), suffix, " ", months[month - 1], " ", uintToString(year))); } function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) { uint256 _days = timestamp / SECONDS_PER_DAY; dayOfWeek = ((_days + 3) % 7) + 1; } /// Taken from https://stackoverflow.com/questions/47129173/how-to-convert-uint-to-string-in-solidity function uintToString(uint256 _i) internal pure returns (string memory _uintAsString) { if (_i == 0) return "0"; uint256 j = _i; uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint256 k = len; while (_i != 0) { k = k - 1; uint8 temp = (48 + uint8(_i - (_i / 10) * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; _i /= 10; } return string(bstr); } // ------------------------------------------------------------------------ // Calculate the number of days from 1970/01/01 to year/month/day using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and subtracting the offset 2440588 so that 1970/01/01 is day 0 // // days = day // - 32075 // + 1461 * (year + 4800 + (month - 14) / 12) / 4 // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 // - offset // ------------------------------------------------------------------------ function _daysFromDate( uint256 year, uint256 month, uint256 day ) internal pure returns (uint256 _days) { require(year >= 1970); int256 _year = int256(year); int256 _month = int256(month); int256 _day = int256(day); int256 __days = _day - 32075 + (1461 * (_year + 4800 + (_month - 14) / 12)) / 4 + (367 * (_month - 2 - ((_month - 14) / 12) * 12)) / 12 - (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) / 4 - OFFSET19700101; _days = uint256(__days); } // ------------------------------------------------------------------------ // Calculate year/month/day from the number of days since 1970/01/01 using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and adding the offset 2440588 so that 1970/01/01 is day 0 // // int L = days + 68569 + offset // int N = 4 * L / 146097 // L = L - (146097 * N + 3) / 4 // year = 4000 * (L + 1) / 1461001 // L = L - 1461 * year / 4 + 31 // month = 80 * L / 2447 // dd = L - 2447 * month / 80 // L = month / 11 // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ function _daysToDate(uint256 _days) internal pure returns ( uint256 year, uint256 month, uint256 day ) { int256 __days = int256(_days); int256 L = __days + 68569 + OFFSET19700101; int256 N = (4 * L) / 146097; L = L - (146097 * N + 3) / 4; int256 _year = (4000 * (L + 1)) / 1461001; L = L - (1461 * _year) / 4 + 31; int256 _month = (80 * L) / 2447; int256 _day = L - (2447 * _month) / 80; L = _month / 11; _month = _month + 2 - 12 * L; _year = 100 * (N - 49) + _year + L; year = uint256(_year); month = uint256(_month); day = uint256(_day); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; // Internal references import { Divider } from "../Divider.sol"; import { Token } from "./Token.sol"; /// @title Yield Token /// @notice Strips off excess before every transfer contract YT is Token { address public immutable adapter; address public immutable divider; uint256 public immutable maturity; constructor( address _adapter, uint256 _maturity, string memory _name, string memory _symbol, uint8 _decimals, address _divider ) Token(_name, _symbol, _decimals, _divider) { adapter = _adapter; maturity = _maturity; divider = _divider; } function collect() external returns (uint256 _collected) { return Divider(divider).collect(msg.sender, adapter, maturity, 0, address(0)); } function transfer(address to, uint256 value) public override returns (bool) { Divider(divider).collect(msg.sender, adapter, maturity, value, to); return super.transfer(to, value); } function transferFrom( address from, address to, uint256 value ) public override returns (bool) { if (value > 0) Divider(divider).collect(from, adapter, maturity, value, to); return super.transferFrom(from, to, value); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.11; // External references import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; // Internal references import { Trust } from "@sense-finance/v1-utils/src/Trust.sol"; /// @title Base Token contract Token is ERC20, Trust { constructor( string memory _name, string memory _symbol, uint8 _decimals, address _trusted ) ERC20(_name, _symbol, _decimals) Trust(_trusted) {} /// @param usr The address to send the minted tokens /// @param amount The amount to be minted function mint(address usr, uint256 amount) public requiresTrust { _mint(usr, amount); } /// @param usr The address from where to burn tokens from /// @param amount The amount to be burned function burn(address usr, uint256 amount) public requiresTrust { _burn(usr, amount); } }
// 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/Rari-Capital/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"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/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 { event Debug(bool one, bool two, uint256 retsize); /*/////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; 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; 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), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. 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; 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), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. 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; 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), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. 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: AGPL-3.0-only pragma solidity >=0.8.4; library Errors { // Auth error CombineRestricted(); error IssuanceRestricted(); error NotAuthorized(); error OnlyYT(); error OnlyDivider(); error OnlyPeriphery(); error OnlyPermissionless(); error RedeemRestricted(); error Untrusted(); // Adapters error TokenNotSupported(); error FlashCallbackFailed(); error SenderNotEligible(); error TargetMismatch(); error TargetNotSupported(); // Divider error AlreadySettled(); error CollectNotSettled(); error GuardCapReached(); error IssuanceFeeCapExceeded(); error IssueOnSettle(); error NotSettled(); // Input & validations error AlreadyInitialized(); error DuplicateSeries(); error ExistingValue(); error InvalidAdapter(); error InvalidMaturity(); error InvalidParam(); error NotImplemented(); error OutOfWindowBoundaries(); error SeriesDoesNotExist(); error SwapTooSmall(); error TargetParamsNotSet(); error PoolParamsNotSet(); error PTParamsNotSet(); // Periphery error FactoryNotSupported(); error FlashBorrowFailed(); error FlashUntrustedBorrower(); error FlashUntrustedLoanInitiator(); error UnexpectedSwapAmount(); error TooMuchLeftoverTarget(); // Fuse error AdapterNotSet(); error FailedBecomeAdmin(); error FailedAddTargetMarket(); error FailedToAddPTMarket(); error FailedAddLpMarket(); error OracleNotReady(); error PoolAlreadyDeployed(); error PoolNotDeployed(); error PoolNotSet(); error SeriesNotQueued(); error TargetExists(); error TargetNotInFuse(); // Tokens error MintFailed(); error RedeemFailed(); error TransferFailed(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.7.0; library Levels { uint256 private constant _INIT_BIT = 0x1; uint256 private constant _ISSUE_BIT = 0x2; uint256 private constant _COMBINE_BIT = 0x4; uint256 private constant _COLLECT_BIT = 0x8; uint256 private constant _REDEEM_BIT = 0x10; uint256 private constant _REDEEM_HOOK_BIT = 0x20; function initRestricted(uint256 level) internal pure returns (bool) { return level & _INIT_BIT != _INIT_BIT; } function issueRestricted(uint256 level) internal pure returns (bool) { return level & _ISSUE_BIT != _ISSUE_BIT; } function combineRestricted(uint256 level) internal pure returns (bool) { return level & _COMBINE_BIT != _COMBINE_BIT; } function collectDisabled(uint256 level) internal pure returns (bool) { return level & _COLLECT_BIT != _COLLECT_BIT; } function redeemRestricted(uint256 level) internal pure returns (bool) { return level & _REDEEM_BIT != _REDEEM_BIT; } function redeemHookDisabled(uint256 level) internal pure returns (bool) { return level & _REDEEM_HOOK_BIT != _REDEEM_HOOK_BIT; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.7.0; /// @notice Ultra minimal authorization logic for smart contracts. /// @author From https://github.com/Rari-Capital/solmate/blob/fab107565a51674f3a3b5bfdaacc67f6179b1a9b/src/auth/Trust.sol abstract contract Trust { event UserTrustUpdated(address indexed user, bool trusted); mapping(address => bool) public isTrusted; constructor(address initialUser) { isTrusted[initialUser] = true; emit UserTrustUpdated(initialUser, true); } function setIsTrusted(address user, bool trusted) public virtual requiresTrust { isTrusted[user] = trusted; emit UserTrustUpdated(user, trusted); } modifier requiresTrust() { require(isTrusted[msg.sender], "UNTRUSTED"); _; } }
{ "metadata": { "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_divider","type":"address"},{"internalType":"address","name":"_target","type":"address"},{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"uint128","name":"_ifee","type":"uint128"},{"components":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"stake","type":"address"},{"internalType":"uint256","name":"stakeSize","type":"uint256"},{"internalType":"uint256","name":"minm","type":"uint256"},{"internalType":"uint256","name":"maxm","type":"uint256"},{"internalType":"uint64","name":"tilt","type":"uint64"},{"internalType":"uint48","name":"level","type":"uint48"},{"internalType":"uint16","name":"mode","type":"uint16"}],"internalType":"struct BaseAdapter.AdapterParams","name":"_adapterParams","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FlashCallbackFailed","type":"error"},{"inputs":[],"name":"OnlyPeriphery","type":"error"},{"inputs":[],"name":"SenderNotEligible","type":"error"},{"inputs":[],"name":"TokenNotSupported","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"CALLBACK_SUCCESS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURVESINGLESWAP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLIPPAGE_TOLERANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETHPRICEFEED","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WSTETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adapterParams","outputs":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"stake","type":"address"},{"internalType":"uint256","name":"stakeSize","type":"uint256"},{"internalType":"uint256","name":"minm","type":"uint256"},{"internalType":"uint256","name":"maxm","type":"uint256"},{"internalType":"uint64","name":"tilt","type":"uint64"},{"internalType":"uint48","name":"level","type":"uint48"},{"internalType":"uint16","name":"mode","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"divider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getMaturityBounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakeAndTarget","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnderlyingPrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"ifee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"level","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mode","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"notify","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"onRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scale","outputs":[{"internalType":"uint256","name":"exRate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scaleStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"target","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tilt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unwrapTarget","outputs":[{"internalType":"uint256","name":"eth","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrapUnderlying","outputs":[{"internalType":"uint256","name":"wstETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101006040523480156200001257600080fd5b5060405162001f4e38038062001f4e83398101604081905262000035916200072a565b6001600160a01b03808616608090815281861660a081815283871660c09081526001600160801b03871660e09081528651600080549188166001600160a01b03199283161781556020890151600180549190991692169190911790965560408088015160025560608801516003559487015160049081559287015160058054938901519289015161ffff16600160701b0261ffff60701b1965ffffffffffff90941668010000000000000000026001600160701b03199095166001600160401b0390931692909217939093179190911617905582516306fdde0360e01b815292518994899489948994899491936306fdde0393808301939192908290030181865afa15801562000149573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200017391908101906200087a565b60405160200162000185919062000932565b60405160208183030381529060405260069080519060200190620001ab929190620005fb565b50836001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200021591908101906200087a565b60405160200162000227919062000960565b604051602081830303815290604052600790805190602001906200024d929190620005fb565b5060805160405163095ea7b360e01b81526001600160a01b03918216600482015260001960248201529085169063095ea7b3906044016020604051808303816000875af1158015620002a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c991906200098e565b50602081015160805160405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af115801562000323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200034991906200098e565b505060405163095ea7b360e01b8152737f39c581f595b53c5cb19bd0b3f8da6c935e2ca06004820152600019602482015273ae7ab96520de3a18e5e111b5eaab095312d7fe84945063095ea7b393506044019150620003a59050565b6020604051808303816000875af1158015620003c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003eb91906200098e565b5060405163095ea7b360e01b815273dc24316b9ae028f1497c275eb9192a3ea0f670226004820152600019602482015273ae7ab96520de3a18e5e111b5eaab095312d7fe849063095ea7b3906044016020604051808303816000875af11580156200045a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200048091906200098e565b506200048b6200049a565b6008555062000a099350505050565b60008073ab55bf4dfbf469ebfe082b7872557d1f87692fe66001600160a01b03166308c80d206040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620005169190620009b2565b604051630f451f7160e31b8152670de0b6b3a7640000600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe8490637a28fb8890602401602060405180830381865afa15801562000574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200059a9190620009b2565b9050620005b68183620005bd60201b62000f751790919060201c565b9250505090565b6000620005d48383670de0b6b3a7640000620005db565b9392505050565b828202811515841585830485141716620005f457600080fd5b0492915050565b8280546200060990620009cc565b90600052602060002090601f0160209004810192826200062d576000855562000678565b82601f106200064857805160ff191683800117855562000678565b8280016001018555821562000678579182015b82811115620006785782518255916020019190600101906200065b565b50620006869291506200068a565b5090565b5b808211156200068657600081556001016200068b565b80516001600160a01b0381168114620006b957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405161010081016001600160401b0381118282101715620006fa57620006fa620006be565b60405290565b805165ffffffffffff81168114620006b957600080fd5b805161ffff81168114620006b957600080fd5b60008060008060008587036101808112156200074557600080fd5b6200075087620006a1565b95506200076060208801620006a1565b94506200077060408801620006a1565b60608801519094506001600160801b03811681146200078e57600080fd5b9250610100607f198201811315620007a557600080fd5b620007af620006d4565b9150620007bf60808901620006a1565b8252620007cf60a08901620006a1565b602083015260c0880151604083015260e0880151606083015287015160808201526101208701516001600160401b03811681146200080c57600080fd5b60a082015262000820610140880162000700565b60c082015262000834610160880162000717565b60e0820152809150509295509295909350565b60005b83811015620008645781810151838201526020016200084a565b8381111562000874576000848401525b50505050565b6000602082840312156200088d57600080fd5b81516001600160401b0380821115620008a557600080fd5b818401915084601f830112620008ba57600080fd5b815181811115620008cf57620008cf620006be565b604051601f8201601f19908116603f01168101908382118183101715620008fa57620008fa620006be565b816040528281528760208487010111156200091457600080fd5b6200092783602083016020880162000847565b979650505050505050565b600082516200094681846020870162000847565b671020b230b83a32b960c11b920191825250600801919050565b600082516200097481846020870162000847565b6716b0b230b83a32b960c11b920191825250600801919050565b600060208284031215620009a157600080fd5b81518015158114620005d457600080fd5b600060208284031215620009c557600080fd5b5051919050565b600181811c90821680620009e157607f821691505b6020821081141562000a0357634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e0516114e162000a6d60003960006106280152600061053f01526000818161038d0152818161069301528181610d3001528181610d8001528181610e420152610efe0152600081816103f50152610c7c01526114e16000f3fe60806040526004361061018d5760003560e01c8063613255ab116100d7578063b484972a11610085578063b484972a146105f6578063b8c15a9f14610616578063c39a3b2914610662578063d4b8399214610681578063d9d98ce4146106b5578063d9fb643a146106d5578063e00bfe50146106fd578063f51e181a146107255761018d565b8063613255ab146104e557806364c56e3c146105055780636f307dc31461052d5780636fd5ae15146105615780638237e5381461058557806395d89b41146105b9578063ad5c4648146105ce5761018d565b8063295a52121161013f578063295a5212146103c3578063378efa37146103e3578063468f02d2146104175780634aae9fed146104325780634c2037861461045257806351c39ea11461046d5780635cffe9de1461048d57806361096820146104bd5761018d565b806306fdde03146101e5578063083118d51461021057806314282f58146102ca578063162ba733146102eb5780632063b5cc14610320578063226778491461034857806327b327d01461036c575b3373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148015906101c557503373dc24316b9ae028f1497c275eb9192a3ea0f6702214155b156101e3576040516304ae33a760e31b815260040160405180910390fd5b005b3480156101f157600080fd5b506101fa61073a565b60405161020791906111c4565b60405180910390f35b34801561021c57600080fd5b5060005460015460025460035460045460055461026e956001600160a01b0390811695169392919067ffffffffffffffff811690600160401b810465ffffffffffff1690600160701b900461ffff1688565b604080516001600160a01b03998a168152989097166020890152958701949094526060860192909252608085015267ffffffffffffffff1660a084015265ffffffffffff1660c083015261ffff1660e082015261010001610207565b3480156102d657600080fd5b506101e36102e5366004611219565b50505050565b3480156102f757600080fd5b5061031373dc24316b9ae028f1497c275eb9192a3ea0f6702281565b604051610207919061124b565b34801561032c57600080fd5b5061031373ab55bf4dfbf469ebfe082b7872557d1f87692fe681565b34801561035457600080fd5b5061035e60085481565b604051908152602001610207565b34801561037857600080fd5b50600154600254604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682529093166020840152820152606001610207565b3480156103cf57600080fd5b50600554600160701b900461ffff1661035e565b3480156103ef57600080fd5b506103137f000000000000000000000000000000000000000000000000000000000000000081565b34801561042357600080fd5b50670de0b6b3a764000061035e565b34801561043e57600080fd5b5061035e61044d36600461125f565b6107c8565b34801561045e57600080fd5b5061035e6611c37937e0800081565b34801561047957600080fd5b5061035e61048836600461125f565b6109eb565b34801561049957600080fd5b506104ad6104a8366004611290565b610c6e565b6040519015158152602001610207565b3480156104c957600080fd5b50610313734ddc2d193948926d02f9b1fe9e1daa0718270ed581565b3480156104f157600080fd5b5061035e61050036600461132f565b610e77565b34801561051157600080fd5b5060035460045460408051928352602083019190915201610207565b34801561053957600080fd5b506103137f000000000000000000000000000000000000000000000000000000000000000081565b34801561056d57600080fd5b50600554600160401b900465ffffffffffff1661035e565b34801561059157600080fd5b5061035e7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b3480156105c557600080fd5b506101fa610eed565b3480156105da57600080fd5b5061031373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561060257600080fd5b506101e361061136600461134c565b505050565b34801561062257600080fd5b5061064a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b039091168152602001610207565b34801561066e57600080fd5b5060055467ffffffffffffffff1661035e565b34801561068d57600080fd5b506103137f000000000000000000000000000000000000000000000000000000000000000081565b3480156106c157600080fd5b5061035e6106d0366004611393565b610efa565b3480156106e157600080fd5b50610313737f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b34801561070957600080fd5b5061031373ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b34801561073157600080fd5b5061035e610f57565b60068054610747906113bf565b80601f0160208091040260200160405190810160405280929190818152602001828054610773906113bf565b80156107c05780601f10610795576101008083540402835291602001916107c0565b820191906000526020600020905b8154815290600101906020018083116107a357829003601f168201915b505050505081565b60006107ea73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2333085610f91565b604051632e1a7d4d60e01b81526004810183905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b505060405163a1903eab60e01b815273ae7ab96520de3a18e5e111b5eaab095312d7fe84925063a1903eab915084906108899060009060040161124b565b60206040518083038185885af11580156108a7573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108cc91906113f4565b506040516370a0823160e01b815260009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319061090790309060040161124b565b602060405180830381865afa158015610924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094891906113f4565b604051630ea598cb60e41b8152600481018290529091506109e5903390737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09063ea598cb0906024016020604051808303816000875af11580156109a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c791906113f4565b9350737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09084611020565b50919050565b6000610a0d737f39c581f595b53c5cb19bd0b3f8da6c935e2ca0333085610f91565b604051636f074d1f60e11b815260048101839052600090737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09063de0e9a3e906024016020604051808303816000875af1158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8691906113f4565b9050600073ab55bf4dfbf469ebfe082b7872557d1f87692fe66001600160a01b03166308c80d206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0091906113f4565b905073dc24316b9ae028f1497c275eb9192a3ea0f67022633df021246001600085610b4d610b3d6611c37937e08000670de0b6b3a764000061140d565b610b47888a610f75565b90610f75565b6040516001600160e01b031960e087901b168152600f94850b60048201529290930b6024830152604482015260648101919091526084016020604051808303816000875af1158015610ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc791906113f4565b60405190935060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29085908381818185875af1925050503d8060008114610c20576040519150601f19603f3d011682016040523d82523d6000602084013e610c25565b606091505b5050905080610c47576040516312171d8360e31b815260040160405180910390fd5b610c6673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc23386611020565b505050919050565b6000336001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166377aace1a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc9190611432565b6001600160a01b031614610d235760405163fb02114960e01b815260040160405180910390fd5b610d576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168786611020565b6040516323e30c8b60e01b81526000906001600160a01b038816906323e30c8b90610db09033907f0000000000000000000000000000000000000000000000000000000000000000908a9087908b908b9060040161144f565b6020604051808303816000875af1158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df391906113f4565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98114610e355760405163081f7c8760e21b815260040160405180910390fd5b610e6a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016883088610f91565b5060019695505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610ea690309060040161124b565b602060405180830381865afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee791906113f4565b92915050565b60078054610747906113bf565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614610f4e57604051633dd1b30560e01b815260040160405180910390fd5b50600092915050565b6000610f61611098565b90506008548114610f725760088190555b90565b6000610f8a8383670de0b6b3a76400006111a5565b9392505050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806110195760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064015b60405180910390fd5b5050505050565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102e55760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401611010565b60008073ab55bf4dfbf469ebfe082b7872557d1f87692fe66001600160a01b03166308c80d206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111191906113f4565b604051630f451f7160e31b8152670de0b6b3a7640000600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe8490637a28fb8890602401602060405180830381865afa15801561116e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119291906113f4565b905061119e8282610f75565b9250505090565b8282028115158415858304851417166111bd57600080fd5b0492915050565b600060208083528351808285015260005b818110156111f1578581018301518582016040015282016111d5565b81811115611203576000604083870101525b50601f01601f1916929092016040019392505050565b6000806000806080858703121561122f57600080fd5b5050823594602084013594506040840135936060013592509050565b6001600160a01b0391909116815260200190565b60006020828403121561127157600080fd5b5035919050565b6001600160a01b038116811461128d57600080fd5b50565b6000806000806000608086880312156112a857600080fd5b85356112b381611278565b945060208601356112c381611278565b935060408601359250606086013567ffffffffffffffff808211156112e757600080fd5b818801915088601f8301126112fb57600080fd5b81358181111561130a57600080fd5b89602082850101111561131c57600080fd5b9699959850939650602001949392505050565b60006020828403121561134157600080fd5b8135610f8a81611278565b60008060006060848603121561136157600080fd5b833561136c81611278565b9250602084013591506040840135801515811461138857600080fd5b809150509250925092565b600080604083850312156113a657600080fd5b82356113b181611278565b946020939093013593505050565b600181811c908216806113d357607f821691505b602082108114156109e557634e487b7160e01b600052602260045260246000fd5b60006020828403121561140657600080fd5b5051919050565b60008282101561142d57634e487b7160e01b600052601160045260246000fd5b500390565b60006020828403121561144457600080fd5b8151610f8a81611278565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea26469706673582212207d19660262f27850b08e34252731852eb89b45ac85037fbcce7376f47cb30a5b64736f6c634300080b003300000000000000000000000086ba3e96be68563e41c2f5769f1af9faf758e6e00000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000001887118e49e0f4a78bd71b792a49de03504a764d000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820a80000000000000000000000000000000000000000000000000000000012cf4ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061018d5760003560e01c8063613255ab116100d7578063b484972a11610085578063b484972a146105f6578063b8c15a9f14610616578063c39a3b2914610662578063d4b8399214610681578063d9d98ce4146106b5578063d9fb643a146106d5578063e00bfe50146106fd578063f51e181a146107255761018d565b8063613255ab146104e557806364c56e3c146105055780636f307dc31461052d5780636fd5ae15146105615780638237e5381461058557806395d89b41146105b9578063ad5c4648146105ce5761018d565b8063295a52121161013f578063295a5212146103c3578063378efa37146103e3578063468f02d2146104175780634aae9fed146104325780634c2037861461045257806351c39ea11461046d5780635cffe9de1461048d57806361096820146104bd5761018d565b806306fdde03146101e5578063083118d51461021057806314282f58146102ca578063162ba733146102eb5780632063b5cc14610320578063226778491461034857806327b327d01461036c575b3373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2148015906101c557503373dc24316b9ae028f1497c275eb9192a3ea0f6702214155b156101e3576040516304ae33a760e31b815260040160405180910390fd5b005b3480156101f157600080fd5b506101fa61073a565b60405161020791906111c4565b60405180910390f35b34801561021c57600080fd5b5060005460015460025460035460045460055461026e956001600160a01b0390811695169392919067ffffffffffffffff811690600160401b810465ffffffffffff1690600160701b900461ffff1688565b604080516001600160a01b03998a168152989097166020890152958701949094526060860192909252608085015267ffffffffffffffff1660a084015265ffffffffffff1660c083015261ffff1660e082015261010001610207565b3480156102d657600080fd5b506101e36102e5366004611219565b50505050565b3480156102f757600080fd5b5061031373dc24316b9ae028f1497c275eb9192a3ea0f6702281565b604051610207919061124b565b34801561032c57600080fd5b5061031373ab55bf4dfbf469ebfe082b7872557d1f87692fe681565b34801561035457600080fd5b5061035e60085481565b604051908152602001610207565b34801561037857600080fd5b50600154600254604080516001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0811682529093166020840152820152606001610207565b3480156103cf57600080fd5b50600554600160701b900461ffff1661035e565b3480156103ef57600080fd5b506103137f00000000000000000000000086ba3e96be68563e41c2f5769f1af9faf758e6e081565b34801561042357600080fd5b50670de0b6b3a764000061035e565b34801561043e57600080fd5b5061035e61044d36600461125f565b6107c8565b34801561045e57600080fd5b5061035e6611c37937e0800081565b34801561047957600080fd5b5061035e61048836600461125f565b6109eb565b34801561049957600080fd5b506104ad6104a8366004611290565b610c6e565b6040519015158152602001610207565b3480156104c957600080fd5b50610313734ddc2d193948926d02f9b1fe9e1daa0718270ed581565b3480156104f157600080fd5b5061035e61050036600461132f565b610e77565b34801561051157600080fd5b5060035460045460408051928352602083019190915201610207565b34801561053957600080fd5b506103137f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561056d57600080fd5b50600554600160401b900465ffffffffffff1661035e565b34801561059157600080fd5b5061035e7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b3480156105c557600080fd5b506101fa610eed565b3480156105da57600080fd5b5061031373c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b34801561060257600080fd5b506101e361061136600461134c565b505050565b34801561062257600080fd5b5061064a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b039091168152602001610207565b34801561066e57600080fd5b5060055467ffffffffffffffff1661035e565b34801561068d57600080fd5b506103137f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b3480156106c157600080fd5b5061035e6106d0366004611393565b610efa565b3480156106e157600080fd5b50610313737f39c581f595b53c5cb19bd0b3f8da6c935e2ca081565b34801561070957600080fd5b5061031373ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b34801561073157600080fd5b5061035e610f57565b60068054610747906113bf565b80601f0160208091040260200160405190810160405280929190818152602001828054610773906113bf565b80156107c05780601f10610795576101008083540402835291602001916107c0565b820191906000526020600020905b8154815290600101906020018083116107a357829003601f168201915b505050505081565b60006107ea73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2333085610f91565b604051632e1a7d4d60e01b81526004810183905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b505060405163a1903eab60e01b815273ae7ab96520de3a18e5e111b5eaab095312d7fe84925063a1903eab915084906108899060009060040161124b565b60206040518083038185885af11580156108a7573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906108cc91906113f4565b506040516370a0823160e01b815260009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319061090790309060040161124b565b602060405180830381865afa158015610924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094891906113f4565b604051630ea598cb60e41b8152600481018290529091506109e5903390737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09063ea598cb0906024016020604051808303816000875af11580156109a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c791906113f4565b9350737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09084611020565b50919050565b6000610a0d737f39c581f595b53c5cb19bd0b3f8da6c935e2ca0333085610f91565b604051636f074d1f60e11b815260048101839052600090737f39c581f595b53c5cb19bd0b3f8da6c935e2ca09063de0e9a3e906024016020604051808303816000875af1158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8691906113f4565b9050600073ab55bf4dfbf469ebfe082b7872557d1f87692fe66001600160a01b03166308c80d206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610adc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0091906113f4565b905073dc24316b9ae028f1497c275eb9192a3ea0f67022633df021246001600085610b4d610b3d6611c37937e08000670de0b6b3a764000061140d565b610b47888a610f75565b90610f75565b6040516001600160e01b031960e087901b168152600f94850b60048201529290930b6024830152604482015260648101919091526084016020604051808303816000875af1158015610ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc791906113f4565b60405190935060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29085908381818185875af1925050503d8060008114610c20576040519150601f19603f3d011682016040523d82523d6000602084013e610c25565b606091505b5050905080610c47576040516312171d8360e31b815260040160405180910390fd5b610c6673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc23386611020565b505050919050565b6000336001600160a01b03167f00000000000000000000000086ba3e96be68563e41c2f5769f1af9faf758e6e06001600160a01b03166377aace1a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfc9190611432565b6001600160a01b031614610d235760405163fb02114960e01b815260040160405180910390fd5b610d576001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0168786611020565b6040516323e30c8b60e01b81526000906001600160a01b038816906323e30c8b90610db09033907f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0908a9087908b908b9060040161144f565b6020604051808303816000875af1158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df391906113f4565b90507f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd98114610e355760405163081f7c8760e21b815260040160405180910390fd5b610e6a6001600160a01b037f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca016883088610f91565b5060019695505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610ea690309060040161124b565b602060405180830381865afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee791906113f4565b92915050565b60078054610747906113bf565b60007f0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca06001600160a01b0316836001600160a01b031614610f4e57604051633dd1b30560e01b815260040160405180910390fd5b50600092915050565b6000610f61611098565b90506008548114610f725760088190555b90565b6000610f8a8383670de0b6b3a76400006111a5565b9392505050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806110195760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064015b60405180910390fd5b5050505050565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102e55760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401611010565b60008073ab55bf4dfbf469ebfe082b7872557d1f87692fe66001600160a01b03166308c80d206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111191906113f4565b604051630f451f7160e31b8152670de0b6b3a7640000600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe8490637a28fb8890602401602060405180830381865afa15801561116e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119291906113f4565b905061119e8282610f75565b9250505090565b8282028115158415858304851417166111bd57600080fd5b0492915050565b600060208083528351808285015260005b818110156111f1578581018301518582016040015282016111d5565b81811115611203576000604083870101525b50601f01601f1916929092016040019392505050565b6000806000806080858703121561122f57600080fd5b5050823594602084013594506040840135936060013592509050565b6001600160a01b0391909116815260200190565b60006020828403121561127157600080fd5b5035919050565b6001600160a01b038116811461128d57600080fd5b50565b6000806000806000608086880312156112a857600080fd5b85356112b381611278565b945060208601356112c381611278565b935060408601359250606086013567ffffffffffffffff808211156112e757600080fd5b818801915088601f8301126112fb57600080fd5b81358181111561130a57600080fd5b89602082850101111561131c57600080fd5b9699959850939650602001949392505050565b60006020828403121561134157600080fd5b8135610f8a81611278565b60008060006060848603121561136157600080fd5b833561136c81611278565b9250602084013591506040840135801515811461138857600080fd5b809150509250925092565b600080604083850312156113a657600080fd5b82356113b181611278565b946020939093013593505050565b600181811c908216806113d357607f821691505b602082108114156109e557634e487b7160e01b600052602260045260246000fd5b60006020828403121561140657600080fd5b5051919050565b60008282101561142d57634e487b7160e01b600052601160045260246000fd5b500390565b60006020828403121561144457600080fd5b8151610f8a81611278565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea26469706673582212207d19660262f27850b08e34252731852eb89b45ac85037fbcce7376f47cb30a5b64736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000086ba3e96be68563e41c2f5769f1af9faf758e6e00000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000001887118e49e0f4a78bd71b792a49de03504a764d000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002820a80000000000000000000000000000000000000000000000000000000012cf4ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _divider (address): 0x86bA3E96Be68563E41c2f5769F1AF9fAf758e6E0
Arg [1] : _target (address): 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
Arg [2] : _underlying (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [3] : _ifee (uint128): 0
Arg [4] : _adapterParams (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 00000000000000000000000086ba3e96be68563e41c2f5769f1af9faf758e6e0
Arg [1] : 0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0
Arg [2] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000001887118e49e0f4a78bd71b792a49de03504a764d
Arg [5] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 00000000000000000000000000000000000000000000000000000000002820a8
Arg [8] : 0000000000000000000000000000000000000000000000000000000012cf4ec0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [10] : 000000000000000000000000000000000000000000000000000000000000001f
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
2333:4428:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6666:10;2558:42;6666:18;;;;:51;;-1:-1:-1;6688:10:2;2809:42;6688:29;;6666:51;6662:90;;;6726:26;;-1:-1:-1;;;6726:26:2;;;;;;;;;;;6662:90;2333:4428;2441:18:1;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1222:34;;;;;;;;;;-1:-1:-1;1222:34:1;;;;;;;;;;;;;;-1:-1:-1;;;;;1222:34:1;;;;;;;;;;;;;-1:-1:-1;;;1222:34:1;;;;;-1:-1:-1;;;1222:34:1;;;;;;;;;;-1:-1:-1;;;;;1009:15:17;;;991:34;;1061:15;;;;1056:2;1041:18;;1034:43;1093:18;;;1086:34;;;;1151:2;1136:18;;1129:34;;;;1194:3;1179:19;;1172:35;1256:18;1244:31;971:3;1223:19;;1216:60;1325:14;1313:27;1307:3;1292:19;;1285:56;1390:6;1378:19;1372:3;1357:19;;1350:48;940:3;925:19;1222:34:1;616:788:17;6313:180:1;;;;;;;;;;-1:-1:-1;6313:180:1;;;;;:::i;:::-;;;;;;2767:84:2;;;;;;;;;;;;2809:42;2767:84;;;;;;;;;:::i;2857:83::-;;;;;;;;;;;;2898:42;2857:83;;3311:35;;;;;;;;;;;;;;;;;;;2153:25:17;;;2141:2;2126:18;3311:35:2;2007:177:17;6705:231:1;;;;;;;;;;-1:-1:-1;6884:19:1;;6905:23;;6705:231;;;-1:-1:-1;;;;;6876:6:1;2447:15:17;;2429:34;;6884:19:1;;;2494:2:17;2479:18;;2472:43;2531:18;;2524:34;2379:2;2364:18;6705:231:1;2189:375:17;6942:90:1;;;;;;;;;;-1:-1:-1;7007:18:1;;-1:-1:-1;;;7007:18:1;;;;6942:90;;926:32;;;;;;;;;;;;;;;4303:106:2;;;;;;;;;;-1:-1:-1;4398:4:2;4303:106;;5509:522;;;;;;;;;;-1:-1:-1;5509:522:2;;;;;:::i;:::-;;:::i;3184:53::-;;;;;;;;;;;;3229:8;3184:53;;4415:1088;;;;;;;;;;-1:-1:-1;4415:1088:2;;;;;:::i;:::-;;:::i;3518:613:1:-;;;;;;;;;;-1:-1:-1;3518:613:1;;;;;:::i;:::-;;:::i;:::-;;;4095:14:17;;4088:22;4070:41;;4058:2;4043:18;3518:613:1;3930:187:17;2448:73:2;;;;;;;;;;;;2479:42;2448:73;;5847:139:1;;;;;;;;;;-1:-1:-1;5847:139:1;;;;;:::i;:::-;;:::i;6557:142::-;;;;;;;;;;-1:-1:-1;6653:18:1;;6673;;6557:142;;;4571:25:17;;;4627:2;4612:18;;4605:34;;;;4544:18;6557:142:1;4397:248:17;1084:35:1;;;;;;;;;;;;;;;7134:92;;;;;;;;;;-1:-1:-1;7200:19:1;;-1:-1:-1;;;7200:19:1;;;;7134:92;;737:88;;;;;;;;;;;;780:45;737:88;;2466:20;;;;;;;;;;;;;:::i;2527:73:2:-;;;;;;;;;;;;2558:42;2527:73;;6113:139:1;;;;;;;;;;-1:-1:-1;6113:139:1;;;;;:::i;:::-;;;;;1155:29;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;5508:32:17;;;5490:51;;5478:2;5463:18;1155:29:1;5344:203:17;7038:90:1;;;;;;;;;;-1:-1:-1;7103:18:1;;;;7038:90;;1004:31;;;;;;;;;;;;;;;5678:163;;;;;;;;;;-1:-1:-1;5678:163:1;;;;;:::i;:::-;;:::i;2606:75:2:-;;;;;;;;;;;;2639:42;2606:75;;2687:74;;;;;;;;;;;;2719:42;2687:74;;4039:258;;;;;;;;;;;;;:::i;2441:18:1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5509:522:2:-;5576:14;5602:63;2558:42;5631:10;5651:4;5658:6;5602:28;:63::i;:::-;5688:31;;-1:-1:-1;;;5688:31:2;;;;;2153:25:17;;;2558:42:2;;5688:23;;2126:18:17;;5688:31:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5753:52:2;;-1:-1:-1;;;5753:52:2;;2719:42;;-1:-1:-1;5753:23:2;;-1:-1:-1;5785:6:2;;5753:52;;5802:1;;5753:52;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;5861:41:2;;-1:-1:-1;;;5861:41:2;;5845:13;;2719:42;;5861:26;;:41;;5896:4;;5861:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5960:30;;-1:-1:-1;;;5960:30:2;;;;;2153:25:17;;;5845:57:2;;-1:-1:-1;5912:79:2;;5939:10;;2639:42;;5960:23;;2126:18:17;;5960:30:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5951:39;-1:-1:-1;2639:42:2;;5951:39;5912:26;:79::i;:::-;5592:439;5509:522;;;:::o;4415:1088::-;4480:11;4503:65;2639:42;4534:10;4554:4;4561:6;4503:30;:65::i;:::-;4609:33;;-1:-1:-1;;;4609:33:2;;;;;2153:25:17;;;4593:13:2;;2639:42;;4609:25;;2126:18:17;;4609:33:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4593:49;;4920:16;2898:42;-1:-1:-1;;;;;4939:51:2;;:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4920:72;-1:-1:-1;2809:42:2;5052:45;5118:1;5141;5157:5;5176:61;5202:34;3229:8;270:4:4;5202:34:2;:::i;:::-;5176:20;:8;5190:5;5176:13;:20::i;:::-;:25;;:61::i;:::-;5052:195;;-1:-1:-1;;;;;;5052:195:2;;;;;;;6952:2:17;6941:22;;;5052:195:2;;;6923:41:17;7000:22;;;;6980:18;;;6973:50;7039:18;;;7032:34;7082:18;;;7075:34;;;;6895:19;;5052:195:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5319:27;;5046:201;;-1:-1:-1;5301:12:2;;2558:42;;5046:201;;5301:12;5319:27;5301:12;5319:27;5046:201;2558:42;5319:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5300:46;;;5361:7;5356:44;;5377:23;;-1:-1:-1;;;5377:23:2;;;;;;;;;;;5356:44;5411:41;2558:42;5436:10;5448:3;5411:24;:41::i;:::-;4493:1010;;;4415:1088;;;:::o;3518:613:1:-;3681:4;3733:10;-1:-1:-1;;;;;3701:42:1;3709:7;-1:-1:-1;;;;;3701:26:1;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3701:42:1;;3697:77;;3752:22;;-1:-1:-1;;;3752:22:1;;;;;;;;;;;3697:77;3784:53;-1:-1:-1;;;;;3790:6:1;3784:26;3819:8;3830:6;3784:26;:53::i;:::-;3864:80;;-1:-1:-1;;;3864:80:1;;3847:14;;-1:-1:-1;;;;;3864:43:1;;;;;:80;;3908:10;;3920:6;;3928;;3847:14;;3939:4;;;;3864:80;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3847:97;;780:45;3958:6;:26;3954:67;;3993:28;;-1:-1:-1;;;3993:28:1;;;;;;;;;;;3954:67;4031:72;-1:-1:-1;;;;;4037:6:1;4031:30;4070:8;4089:4;4096:6;4031:30;:72::i;:::-;-1:-1:-1;4120:4:1;;3518:613;-1:-1:-1;;;;;;3518:613:1:o;5847:139::-;5942:37;;-1:-1:-1;;;5942:37:1;;5916:7;;-1:-1:-1;;;;;5942:22:1;;;;;:37;;5973:4;;5942:37;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5935:44;5847:139;-1:-1:-1;;5847:139:1:o;2466:20::-;;;;;;;:::i;5678:163::-;5743:7;5775:6;-1:-1:-1;;;;;5766:15:1;:5;-1:-1:-1;;;;;5766:15:1;;5762:54;;5790:26;;-1:-1:-1;;;5790:26:1;;;;;;;;;;;5762:54;-1:-1:-1;5833:1:1;5678:163;;;;:::o;4039:258:2:-;4091:14;4126:18;:16;:18::i;:::-;4117:27;;4169:11;;4159:6;:21;4155:136;;4260:11;:20;;;4155:136;4039:258;:::o;545:158:4:-;604:7;630:21;641:1;644;270:4;630:10;:21::i;:::-;623:28;545:158;-1:-1:-1;;;545:158:4:o;1337:1573:13:-;1475:12;1602:4;1596:11;-1:-1:-1;;;1725:17:13;1718:93;1858:4;1854:1;1835:17;1831:25;1824:39;1942:2;1937;1918:17;1914:26;1907:38;2022:6;2017:2;1998:17;1994:26;1987:42;2826:2;2823:1;2818:3;2799:17;2796:1;2789:5;2782;2777:52;2345:16;2338:24;2332:2;2314:16;2311:24;2307:1;2303;2297:8;2294:15;2290:46;2287:76;2087:756;2076:767;;;2871:7;2863:40;;;;-1:-1:-1;;;2863:40:13;;8747:2:17;2863:40:13;;;8729:21:17;8786:2;8766:18;;;8759:30;-1:-1:-1;;;8805:18:17;;;8798:50;8865:18;;2863:40:13;;;;;;;;;1465:1445;1337:1573;;;;:::o;2916:1456::-;3028:12;3155:4;3149:11;-1:-1:-1;;;3278:17:13;3271:93;3411:2;3407:1;3388:17;3384:25;3377:37;3491:6;3486:2;3467:17;3463:26;3456:42;4293:2;4290:1;4286:2;4267:17;4264:1;4257:5;4250;4245:51;3814:16;3807:24;3801:2;3783:16;3780:24;3776:1;3772;3766:8;3763:15;3759:46;3756:76;3556:754;3545:765;;;4338:7;4330:35;;;;-1:-1:-1;;;4330:35:13;;9096:2:17;4330:35:13;;;9078:21:17;9135:2;9115:18;;;9108:30;-1:-1:-1;;;9154:18:17;;;9147:45;9209:18;;4330:35:13;8894:339:17;6037:581:2;6088:14;6342:16;2898:42;-1:-1:-1;;;;;6361:51:2;;:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6489:46;;-1:-1:-1;;;6489:46:2;;6527:7;6489:46;;;2153:25:17;6342:72:2;;-1:-1:-1;6467:19:2;;2719:42;;6489:37;;2126:18:17;;6489:46:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6467:68;-1:-1:-1;6585:26:2;:8;6467:68;6585:13;:26::i;:::-;6576:35;;6104:514;;6037:581;:::o;1859:535:4:-;2065:9;;;2196:19;;2189:27;2221:9;;2235;;;2232:16;;2218:31;2185:65;2175:121;;2280:1;2277;2270:12;2175:121;2359:19;;1859:535;-1:-1:-1;;1859:535:4:o;14:597:17:-;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;595:2:17;574:15;-1:-1:-1;;570:29:17;555:45;;;;602:2;551:54;;14:597;-1:-1:-1;;;14:597:17:o;1409:385::-;1495:6;1503;1511;1519;1572:3;1560:9;1551:7;1547:23;1543:33;1540:53;;;1589:1;1586;1579:12;1540:53;-1:-1:-1;;1612:23:17;;;1682:2;1667:18;;1654:32;;-1:-1:-1;1733:2:17;1718:18;;1705:32;;1784:2;1769:18;1756:32;;-1:-1:-1;1409:385:17;-1:-1:-1;1409:385:17:o;1799:203::-;-1:-1:-1;;;;;1963:32:17;;;;1945:51;;1933:2;1918:18;;1799:203::o;2569:180::-;2628:6;2681:2;2669:9;2660:7;2656:23;2652:32;2649:52;;;2697:1;2694;2687:12;2649:52;-1:-1:-1;2720:23:17;;2569:180;-1:-1:-1;2569:180:17:o;2754:154::-;-1:-1:-1;;;;;2852:31:17;;2842:42;;2832:70;;2898:1;2895;2888:12;2832:70;2754:154;:::o;2913:1012::-;3040:6;3048;3056;3064;3072;3125:3;3113:9;3104:7;3100:23;3096:33;3093:53;;;3142:1;3139;3132:12;3093:53;3181:9;3168:23;3200:54;3248:5;3200:54;:::i;:::-;3273:5;-1:-1:-1;3330:2:17;3315:18;;3302:32;3343:56;3302:32;3343:56;:::i;:::-;3418:7;-1:-1:-1;3472:2:17;3457:18;;3444:32;;-1:-1:-1;3527:2:17;3512:18;;3499:32;3550:18;3580:14;;;3577:34;;;3607:1;3604;3597:12;3577:34;3645:6;3634:9;3630:22;3620:32;;3690:7;3683:4;3679:2;3675:13;3671:27;3661:55;;3712:1;3709;3702:12;3661:55;3752:2;3739:16;3778:2;3770:6;3767:14;3764:34;;;3794:1;3791;3784:12;3764:34;3839:7;3834:2;3825:6;3821:2;3817:15;3813:24;3810:37;3807:57;;;3860:1;3857;3850:12;3807:57;2913:1012;;;;-1:-1:-1;2913:1012:17;;-1:-1:-1;3891:2:17;3883:11;;3913:6;2913:1012;-1:-1:-1;;;2913:1012:17:o;4122:270::-;4181:6;4234:2;4222:9;4213:7;4209:23;4205:32;4202:52;;;4250:1;4247;4240:12;4202:52;4289:9;4276:23;4308:54;4356:5;4308:54;:::i;4832:507::-;4906:6;4914;4922;4975:2;4963:9;4954:7;4950:23;4946:32;4943:52;;;4991:1;4988;4981:12;4943:52;5030:9;5017:23;5049:54;5097:5;5049:54;:::i;:::-;5122:5;-1:-1:-1;5174:2:17;5159:18;;5146:32;;-1:-1:-1;5230:2:17;5215:18;;5202:32;5272:15;;5265:23;5253:36;;5243:64;;5303:1;5300;5293:12;5243:64;5326:7;5316:17;;;4832:507;;;;;:::o;5552:338::-;5620:6;5628;5681:2;5669:9;5660:7;5656:23;5652:32;5649:52;;;5697:1;5694;5687:12;5649:52;5736:9;5723:23;5755:54;5803:5;5755:54;:::i;:::-;5828:5;5880:2;5865:18;;;;5852:32;;-1:-1:-1;;;5552:338:17:o;5895:380::-;5974:1;5970:12;;;;6017;;;6038:61;;6092:4;6084:6;6080:17;6070:27;;6038:61;6145:2;6137:6;6134:14;6114:18;6111:38;6108:161;;;6191:10;6186:3;6182:20;6179:1;6172:31;6226:4;6223:1;6216:15;6254:4;6251:1;6244:15;6280:184;6350:6;6403:2;6391:9;6382:7;6378:23;6374:32;6371:52;;;6419:1;6416;6409:12;6371:52;-1:-1:-1;6442:16:17;;6280:184;-1:-1:-1;6280:184:17:o;6469:222::-;6509:4;6537:1;6534;6531:8;6528:131;;;6581:10;6576:3;6572:20;6569:1;6562:31;6616:4;6613:1;6606:15;6644:4;6641:1;6634:15;6528:131;-1:-1:-1;6676:9:17;;6469:222::o;7330:274::-;7400:6;7453:2;7441:9;7432:7;7428:23;7424:32;7421:52;;;7469:1;7466;7459:12;7421:52;7501:9;7495:16;7520:54;7568:5;7520:54;:::i;7609:742::-;-1:-1:-1;;;;;7924:15:17;;;7906:34;;7976:15;;7971:2;7956:18;;7949:43;8023:2;8008:18;;8001:34;;;8066:2;8051:18;;8044:34;;;7886:3;8109;8094:19;;8087:32;;;8135:19;;8128:35;;;7849:4;8156:6;8206;8200:3;8185:19;;8172:49;8271:1;8265:3;8256:6;8245:9;8241:22;8237:32;8230:43;8341:3;8334:2;8330:7;8325:2;8317:6;8313:15;8309:29;8298:9;8294:45;8290:55;8282:63;;7609:742;;;;;;;;;:::o
Swarm Source
ipfs://7d19660262f27850b08e34252731852eb89b45ac85037fbcce7376f47cb30a5b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $3,182.28 | 2.683 | $8,538.11 |
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.