Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18810013 | 285 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ActionCallbackV3
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "../interfaces/IPActionCallbackV3.sol"; import "../core/libraries/Errors.sol"; import "./base/CallbackHelper.sol"; import "../core/libraries/TokenHelper.sol"; contract ActionCallbackV3 is IPLimitOrderType, IPActionCallbackV3, CallbackHelper, TokenHelper { using PMath for int256; using PMath for uint256; using PYIndexLib for PYIndex; using PYIndexLib for IPYieldToken; function swapCallback(int256 ptToAccount, int256 syToAccount, bytes calldata data) external override { ActionType swapType = _getActionType(data); if (swapType == ActionType.SwapExactSyForYt) { _callbackSwapExactSyForYt(ptToAccount, syToAccount, data); } else if (swapType == ActionType.SwapYtForSy) { _callbackSwapYtForSy(ptToAccount, syToAccount, data); } else if (swapType == ActionType.SwapExactYtForPt) { _callbackSwapExactYtForPt(ptToAccount, syToAccount, data); } else if (swapType == ActionType.SwapExactPtForYt) { _callbackSwapExactPtForYt(ptToAccount, syToAccount, data); } else { assert(false); } } function limitRouterCallback( uint256 actualMaking, uint256 actualTaking, uint256, /*totalFee*/ bytes memory data ) external returns ( bytes memory // encode as netTransferToLimit, netOutputFromLimit ) { (OrderType orderType, IPYieldToken YT, uint256 netRemaining, address receiver) = abi.decode( data, (OrderType, IPYieldToken, uint256, address) ); if (orderType == OrderType.SY_FOR_PT || orderType == OrderType.SY_FOR_YT) { PYIndex index = YT.newIndex(); uint256 totalSyToMintPy = index.assetToSyUp(actualTaking); uint256 additionalSyToMint = totalSyToMintPy - actualMaking; require(additionalSyToMint <= netRemaining, "Router: Max SY to pull exceeded"); _transferOut(YT.SY(), address(YT), additionalSyToMint); uint256 netPyToReceiver; if (orderType == OrderType.SY_FOR_PT) { netPyToReceiver = YT.mintPY(address(this), receiver); _safeApproveInf(YT.PT(), msg.sender); } else { netPyToReceiver = YT.mintPY(receiver, address(this)); _safeApproveInf(address(YT), msg.sender); } return abi.encode(additionalSyToMint, netPyToReceiver); } else { require(actualMaking <= netRemaining, "Router: Max PY to pull exceeded"); if (orderType == OrderType.PT_FOR_SY) { _transferOut(address(YT), address(YT), actualMaking); } else { _transferOut(YT.PT(), address(YT), actualMaking); } uint256 netSyRedeemed = IPYieldToken(YT).redeemPY(address(this)); require(actualTaking <= netSyRedeemed, "Router: Insufficient SY redeemed"); uint256 netSyToReceiver = netSyRedeemed - actualTaking; address SY = YT.SY(); _transferOut(SY, receiver, netSyToReceiver); _safeApproveInf(SY, msg.sender); return abi.encode(actualMaking, netSyToReceiver); } } function _callbackSwapExactSyForYt(int256 ptToAccount, int256, /*syToAccount*/ bytes calldata data) internal { (address receiver, IPYieldToken YT) = _decodeSwapExactSyForYt(data); uint256 ptOwed = ptToAccount.abs(); uint256 netPyOut = YT.mintPY(msg.sender, receiver); if (netPyOut < ptOwed) revert Errors.RouterInsufficientPtRepay(netPyOut, ptOwed); } function _callbackSwapYtForSy(int256 ptToAccount, int256 syToAccount, bytes calldata data) internal { (address receiver, IPYieldToken YT) = _decodeSwapYtForSy(data); PYIndex pyIndex = YT.newIndex(); uint256 syOwed = syToAccount.neg().Uint(); address[] memory receivers = new address[](2); uint256[] memory amountPYToRedeems = new uint256[](2); (receivers[0], amountPYToRedeems[0]) = (msg.sender, pyIndex.syToAssetUp(syOwed)); (receivers[1], amountPYToRedeems[1]) = (receiver, ptToAccount.Uint() - amountPYToRedeems[0]); YT.redeemPYMulti(receivers, amountPYToRedeems); } function _callbackSwapExactPtForYt(int256 ptToAccount, int256, /*syToAccount*/ bytes calldata data) internal { (address receiver, uint256 exactPtIn, uint256 minYtOut, IPYieldToken YT) = _decodeSwapExactPtForYt(data); uint256 netPtOwed = ptToAccount.abs(); uint256 netPyOut = YT.mintPY(msg.sender, receiver); if (netPyOut < minYtOut) revert Errors.RouterInsufficientYtOut(netPyOut, minYtOut); if (exactPtIn + netPyOut < netPtOwed) { revert Errors.RouterInsufficientPtRepay(exactPtIn + netPyOut, netPtOwed); } } function _callbackSwapExactYtForPt(int256 ptToAccount, int256 syToAccount, bytes calldata data) internal { (address receiver, uint256 netPtOut, IPPrincipalToken PT, IPYieldToken YT) = _decodeSwapExactYtForPt(data); uint256 netSyOwed = syToAccount.abs(); uint256 netPtRedeemSy = ptToAccount.Uint() - netPtOut; _transferOut(address(PT), address(YT), netPtRedeemSy); uint256 netSyToMarket = YT.redeemPY(msg.sender); if (netSyToMarket < netSyOwed) { revert Errors.RouterInsufficientSyRepay(netSyToMarket, netSyOwed); } _transferOut(address(PT), receiver, netPtOut); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; library Errors { // BulkSeller error BulkInsufficientSyForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInsufficientTokenForTrade(uint256 currentAmount, uint256 requiredAmount); error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error BulkInSufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error BulkInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error BulkNotMaintainer(); error BulkNotAdmin(); error BulkSellerAlreadyExisted(address token, address SY, address bulk); error BulkSellerInvalidToken(address token, address SY); error BulkBadRateTokenToSy(uint256 actualRate, uint256 currentRate, uint256 eps); error BulkBadRateSyToToken(uint256 actualRate, uint256 currentRate, uint256 eps); // APPROX error ApproxFail(); error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps); error ApproxBinarySearchInputInvalid( uint256 approxGuessMin, uint256 approxGuessMax, uint256 minGuessMin, uint256 maxGuessMax ); // MARKET + MARKET MATH CORE error MarketExpired(); error MarketZeroAmountsInput(); error MarketZeroAmountsOutput(); error MarketZeroLnImpliedRate(); error MarketInsufficientPtForTrade(int256 currentAmount, int256 requiredAmount); error MarketInsufficientPtReceived(uint256 actualBalance, uint256 requiredBalance); error MarketInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance); error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset); error MarketExchangeRateBelowOne(int256 exchangeRate); error MarketProportionMustNotEqualOne(); error MarketRateScalarBelowZero(int256 rateScalar); error MarketScalarRootBelowZero(int256 scalarRoot); error MarketProportionTooHigh(int256 proportion, int256 maxProportion); error OracleUninitialized(); error OracleTargetTooOld(uint32 target, uint32 oldest); error OracleZeroCardinality(); error MarketFactoryExpiredPt(); error MarketFactoryInvalidPt(); error MarketFactoryMarketExists(); error MarketFactoryLnFeeRateRootTooHigh(uint80 lnFeeRateRoot, uint256 maxLnFeeRateRoot); error MarketFactoryOverriddenFeeTooHigh(uint80 overriddenFee, uint256 marketLnFeeRateRoot); error MarketFactoryReserveFeePercentTooHigh(uint8 reserveFeePercent, uint8 maxReserveFeePercent); error MarketFactoryZeroTreasury(); error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor); error MFNotPendleMarket(address addr); // ROUTER error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut); error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut); error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut); error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut); error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut); error RouterInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); error RouterInsufficientSyRepay(uint256 actualSyRepay, uint256 requiredSyRepay); error RouterInsufficientPtRepay(uint256 actualPtRepay, uint256 requiredPtRepay); error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed); error RouterTimeRangeZero(); error RouterCallbackNotPendleMarket(address caller); error RouterInvalidAction(bytes4 selector); error RouterInvalidFacet(address facet); error RouterKyberSwapDataZero(); error SimulationResults(bool success, bytes res); // YIELD CONTRACT error YCExpired(); error YCNotExpired(); error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy); error YCNothingToRedeem(); error YCPostExpiryDataNotSet(); error YCNoFloatingSy(); // YieldFactory error YCFactoryInvalidExpiry(); error YCFactoryYieldContractExisted(); error YCFactoryZeroExpiryDivisor(); error YCFactoryZeroTreasury(); error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate); error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate); // SY error SYInvalidTokenIn(address token); error SYInvalidTokenOut(address token); error SYZeroDeposit(); error SYZeroRedeem(); error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut); error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut); // SY-specific error SYQiTokenMintFailed(uint256 errCode); error SYQiTokenRedeemFailed(uint256 errCode); error SYQiTokenRedeemRewardsFailed(uint256 rewardAccruedType0, uint256 rewardAccruedType1); error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax); error SYCurveInvalidPid(); error SYCurve3crvPoolNotFound(); error SYApeDepositAmountTooSmall(uint256 amountDeposited); error SYBalancerInvalidPid(); error SYInvalidRewardToken(address token); error SYStargateRedeemCapExceeded(uint256 amountLpDesired, uint256 amountLpRedeemable); error SYBalancerReentrancy(); error NotFromTrustedRemote(uint16 srcChainId, bytes path); // Liquidity Mining error VCInactivePool(address pool); error VCPoolAlreadyActive(address pool); error VCZeroVePendle(address user); error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight); error VCEpochNotFinalized(uint256 wTime); error VCPoolAlreadyAddAndRemoved(address pool); error VEInvalidNewExpiry(uint256 newExpiry); error VEExceededMaxLockTime(); error VEInsufficientLockTime(); error VENotAllowedReduceExpiry(); error VEZeroAmountLocked(); error VEPositionNotExpired(); error VEZeroPosition(); error VEZeroSlope(uint128 bias, uint128 slope); error VEReceiveOldSupply(uint256 msgTime); error GCNotPendleMarket(address caller); error GCNotVotingController(address caller); error InvalidWTime(uint256 wTime); error ExpiryInThePast(uint256 expiry); error ChainNotSupported(uint256 chainId); error FDTotalAmountFundedNotMatch(uint256 actualTotalAmount, uint256 expectedTotalAmount); error FDEpochLengthMismatch(); error FDInvalidPool(address pool); error FDPoolAlreadyExists(address pool); error FDInvalidNewFinishedEpoch(uint256 oldFinishedEpoch, uint256 newFinishedEpoch); error FDInvalidStartEpoch(uint256 startEpoch); error FDInvalidWTimeFund(uint256 lastFunded, uint256 wTime); error FDFutureFunding(uint256 lastFunded, uint256 currentWTime); error BDInvalidEpoch(uint256 epoch, uint256 startTime); // Cross-Chain error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path); error MsgNotFromReceiveEndpoint(address sender); error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee); error ApproxDstExecutionGasNotSet(); error InvalidRetryData(); // GENERIC MSG error ArrayLengthMismatch(); error ArrayEmpty(); error ArrayOutOfBounds(); error ZeroAddress(); error FailedToSendEther(); error InvalidMerkleProof(); error OnlyLayerZeroEndpoint(); error OnlyYT(); error OnlyYCFactory(); error OnlyWhitelisted(); // Swap Aggregator error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual); error UnsupportedSelector(uint256 aggregatorType, bytes4 selector); }
// SPDX-License-Identifier: GPL-3.0-or-later // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.8.0; /* solhint-disable private-vars-leading-underscore, reason-string */ library PMath { uint256 internal constant ONE = 1e18; // 18 decimal places int256 internal constant IONE = 1e18; // 18 decimal places function subMax0(uint256 a, uint256 b) internal pure returns (uint256) { unchecked { return (a >= b ? a - b : 0); } } function subNoNeg(int256 a, int256 b) internal pure returns (int256) { require(a >= b, "negative"); return a - b; // no unchecked since if b is very negative, a - b might overflow } function mulDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; unchecked { return product / ONE; } } function mulDown(int256 a, int256 b) internal pure returns (int256) { int256 product = a * b; unchecked { return product / IONE; } } function divDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 aInflated = a * ONE; unchecked { return aInflated / b; } } function divDown(int256 a, int256 b) internal pure returns (int256) { int256 aInflated = a * IONE; unchecked { return aInflated / b; } } function rawDivUp(uint256 a, uint256 b) internal pure returns (uint256) { return (a + b - 1) / b; } // @author Uniswap function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } function square(uint256 x) internal pure returns (uint256) { return x * x; } function squareDown(uint256 x) internal pure returns (uint256) { return mulDown(x, x); } function abs(int256 x) internal pure returns (uint256) { return uint256(x > 0 ? x : -x); } function neg(int256 x) internal pure returns (int256) { return x * (-1); } function neg(uint256 x) internal pure returns (int256) { return Int(x) * (-1); } function max(uint256 x, uint256 y) internal pure returns (uint256) { return (x > y ? x : y); } function max(int256 x, int256 y) internal pure returns (int256) { return (x > y ? x : y); } function min(uint256 x, uint256 y) internal pure returns (uint256) { return (x < y ? x : y); } function min(int256 x, int256 y) internal pure returns (int256) { return (x < y ? x : y); } /*/////////////////////////////////////////////////////////////// SIGNED CASTS //////////////////////////////////////////////////////////////*/ function Int(uint256 x) internal pure returns (int256) { require(x <= uint256(type(int256).max)); return int256(x); } function Int128(int256 x) internal pure returns (int128) { require(type(int128).min <= x && x <= type(int128).max); return int128(x); } function Int128(uint256 x) internal pure returns (int128) { return Int128(Int(x)); } /*/////////////////////////////////////////////////////////////// UNSIGNED CASTS //////////////////////////////////////////////////////////////*/ function Uint(int256 x) internal pure returns (uint256) { require(x >= 0); return uint256(x); } function Uint32(uint256 x) internal pure returns (uint32) { require(x <= type(uint32).max); return uint32(x); } function Uint64(uint256 x) internal pure returns (uint64) { require(x <= type(uint64).max); return uint64(x); } function Uint112(uint256 x) internal pure returns (uint112) { require(x <= type(uint112).max); return uint112(x); } function Uint96(uint256 x) internal pure returns (uint96) { require(x <= type(uint96).max); return uint96(x); } function Uint128(uint256 x) internal pure returns (uint128) { require(x <= type(uint128).max); return uint128(x); } function Uint192(uint256 x) internal pure returns (uint192) { require(x <= type(uint192).max); return uint192(x); } function isAApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return mulDown(b, ONE - eps) <= a && a <= mulDown(b, ONE + eps); } function isAGreaterApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return a >= b && a <= mulDown(b, ONE + eps); } function isASmallerApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) { return a <= b && a >= mulDown(b, ONE - eps); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../interfaces/IWETH.sol"; abstract contract TokenHelper { using SafeERC20 for IERC20; address internal constant NATIVE = address(0); uint256 internal constant LOWER_BOUND_APPROVAL = type(uint96).max / 2; // some tokens use 96 bits for approval function _transferIn(address token, address from, uint256 amount) internal { if (token == NATIVE) require(msg.value == amount, "eth mismatch"); else if (amount != 0) IERC20(token).safeTransferFrom(from, address(this), amount); } function _transferFrom(IERC20 token, address from, address to, uint256 amount) internal { if (amount != 0) token.safeTransferFrom(from, to, amount); } function _transferOut(address token, address to, uint256 amount) internal { if (amount == 0) return; if (token == NATIVE) { (bool success, ) = to.call{value: amount}(""); require(success, "eth send failed"); } else { IERC20(token).safeTransfer(to, amount); } } function _transferOut(address[] memory tokens, address to, uint256[] memory amounts) internal { uint256 numTokens = tokens.length; require(numTokens == amounts.length, "length mismatch"); for (uint256 i = 0; i < numTokens; ) { _transferOut(tokens[i], to, amounts[i]); unchecked { i++; } } } function _selfBalance(address token) internal view returns (uint256) { return (token == NATIVE) ? address(this).balance : IERC20(token).balanceOf(address(this)); } function _selfBalance(IERC20 token) internal view returns (uint256) { return token.balanceOf(address(this)); } /// @notice Approves the stipulated contract to spend the given allowance in the given token /// @dev PLS PAY ATTENTION to tokens that requires the approval to be set to 0 before changing it function _safeApprove(address token, address to, uint256 value) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "Safe Approve"); } function _safeApproveInf(address token, address to) internal { if (token == NATIVE) return; if (IERC20(token).allowance(address(this), to) < LOWER_BOUND_APPROVAL) { _safeApprove(token, to, 0); _safeApprove(token, to, type(uint256).max); } } function _wrap_unwrap_ETH(address tokenIn, address tokenOut, uint256 netTokenIn) internal { if (tokenIn == NATIVE) IWETH(tokenOut).deposit{value: netTokenIn}(); else IWETH(tokenIn).withdraw(netTokenIn); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "../../interfaces/IPYieldToken.sol"; import "../../interfaces/IPPrincipalToken.sol"; import "./SYUtils.sol"; import "../libraries/math/PMath.sol"; type PYIndex is uint256; library PYIndexLib { using PMath for uint256; using PMath for int256; function newIndex(IPYieldToken YT) internal returns (PYIndex) { return PYIndex.wrap(YT.pyIndexCurrent()); } function syToAsset(PYIndex index, uint256 syAmount) internal pure returns (uint256) { return SYUtils.syToAsset(PYIndex.unwrap(index), syAmount); } function assetToSy(PYIndex index, uint256 assetAmount) internal pure returns (uint256) { return SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount); } function assetToSyUp(PYIndex index, uint256 assetAmount) internal pure returns (uint256) { return SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount); } function syToAssetUp(PYIndex index, uint256 syAmount) internal pure returns (uint256) { uint256 _index = PYIndex.unwrap(index); return SYUtils.syToAssetUp(_index, syAmount); } function syToAsset(PYIndex index, int256 syAmount) internal pure returns (int256) { int256 sign = syAmount < 0 ? int256(-1) : int256(1); return sign * (SYUtils.syToAsset(PYIndex.unwrap(index), syAmount.abs())).Int(); } function assetToSy(PYIndex index, int256 assetAmount) internal pure returns (int256) { int256 sign = assetAmount < 0 ? int256(-1) : int256(1); return sign * (SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount.abs())).Int(); } function assetToSyUp(PYIndex index, int256 assetAmount) internal pure returns (int256) { int256 sign = assetAmount < 0 ? int256(-1) : int256(1); return sign * (SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount.abs())).Int(); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; library SYUtils { uint256 internal constant ONE = 1e18; function syToAsset(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) { return (syAmount * exchangeRate) / ONE; } function syToAssetUp(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) { return (syAmount * exchangeRate + ONE - 1) / ONE; } function assetToSy(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) { return (assetAmount * ONE) / exchangeRate; } function assetToSyUp(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) { return (assetAmount * ONE + exchangeRate - 1) / exchangeRate; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "./IPMarketSwapCallback.sol"; import "./IPLimitRouter.sol"; interface IPActionCallbackV3 is IPMarketSwapCallback, IPLimitRouterCallback {}
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; interface IPInterestManagerYT { event CollectInterestFee(uint256 amountInterestFee); function userInterest(address user) external view returns (uint128 lastPYIndex, uint128 accruedInterest); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "../core/StandardizedYield/PYIndex.sol"; interface IPLimitOrderType { enum OrderType { SY_FOR_PT, PT_FOR_SY, SY_FOR_YT, YT_FOR_SY } // Fixed-size order part with core information struct StaticOrder { uint256 salt; uint256 expiry; uint256 nonce; OrderType orderType; address token; address YT; address maker; address receiver; uint256 makingAmount; uint256 lnImpliedRate; uint256 failSafeRate; } struct FillResults { uint256 totalMaking; uint256 totalTaking; uint256 totalFee; uint256 totalNotionalVolume; uint256[] netMakings; uint256[] netTakings; uint256[] netFees; uint256[] notionalVolumes; } } struct Order { uint256 salt; uint256 expiry; uint256 nonce; IPLimitOrderType.OrderType orderType; address token; address YT; address maker; address receiver; uint256 makingAmount; uint256 lnImpliedRate; uint256 failSafeRate; bytes permit; } struct FillOrderParams { Order order; bytes signature; uint256 makingAmount; } interface IPLimitRouterCallback is IPLimitOrderType { function limitRouterCallback( uint256 actualMaking, uint256 actualTaking, uint256 totalFee, bytes memory data ) external returns (bytes memory); } interface IPLimitRouter is IPLimitOrderType { struct OrderStatus { uint128 filledAmount; uint128 remaining; } event OrderCanceled(address indexed maker, bytes32 indexed orderHash); event OrderFilled( bytes32 indexed orderHash, OrderType indexed orderType, address indexed YT, address token, uint256 netInputFromMaker, uint256 netOutputToMaker, uint256 feeAmount, uint256 notionalVolume ); // @dev actualMaking, actualTaking are in the SY form function fill( FillOrderParams[] memory params, address receiver, uint256 maxTaking, bytes calldata optData, bytes calldata callback ) external returns (uint256 actualMaking, uint256 actualTaking, uint256 totalFee, bytes memory callbackReturn); function feeRecipient() external view returns (address); function hashOrder(Order memory order) external view returns (bytes32); function cancelSingle(Order calldata order) external; function cancelBatch(Order[] calldata orders) external; function orderStatusesRaw( bytes32[] memory orderHashes ) external view returns (uint256[] memory remainingsRaw, uint256[] memory filledAmounts); function orderStatuses( bytes32[] memory orderHashes ) external view returns (uint256[] memory remainings, uint256[] memory filledAmounts); function DOMAIN_SEPARATOR() external view returns (bytes32); function simulate(address target, bytes calldata data) external payable; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; interface IPMarketSwapCallback { function swapCallback(int256 ptToAccount, int256 syToAccount, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface IPPrincipalToken is IERC20Metadata { function burnByYT(address user, uint256 amount) external; function mintByYT(address user, uint256 amount) external; function initialize(address _YT) external; function SY() external view returns (address); function YT() external view returns (address); function factory() external view returns (address); function expiry() external view returns (uint256); function isExpired() external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "./IRewardManager.sol"; import "./IPInterestManagerYT.sol"; interface IPYieldToken is IERC20Metadata, IRewardManager, IPInterestManagerYT { event NewInterestIndex(uint256 indexed newIndex); event Mint( address indexed caller, address indexed receiverPT, address indexed receiverYT, uint256 amountSyToMint, uint256 amountPYOut ); event Burn(address indexed caller, address indexed receiver, uint256 amountPYToRedeem, uint256 amountSyOut); event RedeemRewards(address indexed user, uint256[] amountRewardsOut); event RedeemInterest(address indexed user, uint256 interestOut); event CollectRewardFee(address indexed rewardToken, uint256 amountRewardFee); function mintPY(address receiverPT, address receiverYT) external returns (uint256 amountPYOut); function redeemPY(address receiver) external returns (uint256 amountSyOut); function redeemPYMulti( address[] calldata receivers, uint256[] calldata amountPYToRedeems ) external returns (uint256[] memory amountSyOuts); function redeemDueInterestAndRewards( address user, bool redeemInterest, bool redeemRewards ) external returns (uint256 interestOut, uint256[] memory rewardsOut); function rewardIndexesCurrent() external returns (uint256[] memory); function pyIndexCurrent() external returns (uint256); function pyIndexStored() external view returns (uint256); function getRewardTokens() external view returns (address[] memory); function SY() external view returns (address); function PT() external view returns (address); function factory() external view returns (address); function expiry() external view returns (uint256); function isExpired() external view returns (bool); function doCacheIndexSameBlock() external view returns (bool); function pyIndexLastUpdatedBlock() external view returns (uint128); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; interface IRewardManager { function userReward(address token, address user) external view returns (uint128 index, uint128 accrued); }
// SPDX-License-Identifier: GPL-3.0-or-later /* * MIT License * =========== * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface IStandardizedYield is IERC20Metadata { /// @dev Emitted when any base tokens is deposited to mint shares event Deposit( address indexed caller, address indexed receiver, address indexed tokenIn, uint256 amountDeposited, uint256 amountSyOut ); /// @dev Emitted when any shares are redeemed for base tokens event Redeem( address indexed caller, address indexed receiver, address indexed tokenOut, uint256 amountSyToRedeem, uint256 amountTokenOut ); /// @dev check `assetInfo()` for more information enum AssetType { TOKEN, LIQUIDITY } /// @dev Emitted when (`user`) claims their rewards event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts); /** * @notice mints an amount of shares by depositing a base token. * @param receiver shares recipient address * @param tokenIn address of the base tokens to mint shares * @param amountTokenToDeposit amount of base tokens to be transferred from (`msg.sender`) * @param minSharesOut reverts if amount of shares minted is lower than this * @return amountSharesOut amount of shares minted * @dev Emits a {Deposit} event * * Requirements: * - (`tokenIn`) must be a valid base token. */ function deposit( address receiver, address tokenIn, uint256 amountTokenToDeposit, uint256 minSharesOut ) external payable returns (uint256 amountSharesOut); /** * @notice redeems an amount of base tokens by burning some shares * @param receiver recipient address * @param amountSharesToRedeem amount of shares to be burned * @param tokenOut address of the base token to be redeemed * @param minTokenOut reverts if amount of base token redeemed is lower than this * @param burnFromInternalBalance if true, burns from balance of `address(this)`, otherwise burns from `msg.sender` * @return amountTokenOut amount of base tokens redeemed * @dev Emits a {Redeem} event * * Requirements: * - (`tokenOut`) must be a valid base token. */ function redeem( address receiver, uint256 amountSharesToRedeem, address tokenOut, uint256 minTokenOut, bool burnFromInternalBalance ) external returns (uint256 amountTokenOut); /** * @notice exchangeRate * syBalance / 1e18 must return the asset balance of the account * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of sy he can mint must be X * exchangeRate / 1e18 * @dev SYUtils's assetToSy & syToAsset should be used instead of raw multiplication & division */ function exchangeRate() external view returns (uint256 res); /** * @notice claims reward for (`user`) * @param user the user receiving their rewards * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens` * @dev * Emits a `ClaimRewards` event * See {getRewardTokens} for list of reward tokens */ function claimRewards(address user) external returns (uint256[] memory rewardAmounts); /** * @notice get the amount of unclaimed rewards for (`user`) * @param user the user to check for * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens` */ function accruedRewards(address user) external view returns (uint256[] memory rewardAmounts); function rewardIndexesCurrent() external returns (uint256[] memory indexes); function rewardIndexesStored() external view returns (uint256[] memory indexes); /** * @notice returns the list of reward token addresses */ function getRewardTokens() external view returns (address[] memory); /** * @notice returns the address of the underlying yield token */ function yieldToken() external view returns (address); /** * @notice returns all tokens that can mint this SY */ function getTokensIn() external view returns (address[] memory res); /** * @notice returns all tokens that can be redeemed by this SY */ function getTokensOut() external view returns (address[] memory res); function isValidTokenIn(address token) external view returns (bool); function isValidTokenOut(address token) external view returns (bool); function previewDeposit( address tokenIn, uint256 amountTokenToDeposit ) external view returns (uint256 amountSharesOut); function previewRedeem( address tokenOut, uint256 amountSharesToRedeem ) external view returns (uint256 amountTokenOut); /** * @notice This function contains information to interpret what the asset is * @return assetType the type of the asset (0 for ERC20 tokens, 1 for AMM liquidity tokens, 2 for bridged yield bearing tokens like wstETH, rETH on Arbi whose the underlying asset doesn't exist on the chain) * @return assetAddress the address of the asset * @return assetDecimals the decimals of the asset */ function assetInfo() external view returns (AssetType assetType, address assetAddress, uint8 assetDecimals); }
// SPDX-License-Identifier: GPL-3.0-or-later /* * MIT License * =========== * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; import "../../interfaces/IPYieldToken.sol"; import "../../interfaces/IPPrincipalToken.sol"; import "../../interfaces/IStandardizedYield.sol"; abstract contract CallbackHelper { enum ActionType { SwapExactSyForYt, SwapYtForSy, SwapExactYtForPt, SwapExactPtForYt } /// ------------------------------------------------------------ /// SwapExactSyForYt /// ------------------------------------------------------------ function _encodeSwapExactSyForYt(address receiver, IPYieldToken YT) internal pure returns (bytes memory res) { res = new bytes(96); uint256 actionType = uint256(ActionType.SwapExactSyForYt); assembly { mstore(add(res, 32), actionType) mstore(add(res, 64), receiver) mstore(add(res, 96), YT) } } function _decodeSwapExactSyForYt(bytes calldata data) internal pure returns (address receiver, IPYieldToken YT) { assembly { // first 32 bytes is ActionType receiver := calldataload(add(data.offset, 32)) YT := calldataload(add(data.offset, 64)) } } /// ------------------------------------------------------------ /// SwapYtForSy (common encode & decode) /// ------------------------------------------------------------ function _encodeSwapYtForSy(address receiver, IPYieldToken YT) internal pure returns (bytes memory res) { res = new bytes(96); uint256 actionType = uint256(ActionType.SwapYtForSy); assembly { mstore(add(res, 32), actionType) mstore(add(res, 64), receiver) mstore(add(res, 96), YT) } } function _decodeSwapYtForSy(bytes calldata data) internal pure returns (address receiver, IPYieldToken YT) { assembly { // first 32 bytes is ActionType receiver := calldataload(add(data.offset, 32)) YT := calldataload(add(data.offset, 64)) } } function _encodeSwapExactYtForPt( address receiver, uint256 netPtOut, IPPrincipalToken PT, IPYieldToken YT ) internal pure returns (bytes memory res) { res = new bytes(160); uint256 actionType = uint256(ActionType.SwapExactYtForPt); assembly { mstore(add(res, 32), actionType) mstore(add(res, 64), receiver) mstore(add(res, 96), netPtOut) mstore(add(res, 128), PT) mstore(add(res, 160), YT) } } function _decodeSwapExactYtForPt( bytes calldata data ) internal pure returns (address receiver, uint256 netPtOut, IPPrincipalToken PT, IPYieldToken YT) { assembly { // first 32 bytes is ActionType receiver := calldataload(add(data.offset, 32)) netPtOut := calldataload(add(data.offset, 64)) PT := calldataload(add(data.offset, 96)) YT := calldataload(add(data.offset, 128)) } } function _encodeSwapExactPtForYt( address receiver, uint256 exactPtIn, uint256 minYtOut, IPYieldToken YT ) internal pure returns (bytes memory res) { res = new bytes(160); uint256 actionType = uint256(ActionType.SwapExactPtForYt); assembly { mstore(add(res, 32), actionType) mstore(add(res, 64), receiver) mstore(add(res, 96), exactPtIn) mstore(add(res, 128), minYtOut) mstore(add(res, 160), YT) } } function _decodeSwapExactPtForYt( bytes calldata data ) internal pure returns (address receiver, uint256 exactPtIn, uint256 minYtOut, IPYieldToken YT) { assembly { // first 32 bytes is ActionType receiver := calldataload(add(data.offset, 32)) exactPtIn := calldataload(add(data.offset, 64)) minYtOut := calldataload(add(data.offset, 96)) YT := calldataload(add(data.offset, 128)) } } /// ------------------------------------------------------------ /// Misc functions /// ------------------------------------------------------------ function _getActionType(bytes calldata data) internal pure returns (ActionType actionType) { assembly { actionType := calldataload(data.offset) } } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "evmVersion": "paris", "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"actualPtRepay","type":"uint256"},{"internalType":"uint256","name":"requiredPtRepay","type":"uint256"}],"name":"RouterInsufficientPtRepay","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualSyRepay","type":"uint256"},{"internalType":"uint256","name":"requiredSyRepay","type":"uint256"}],"name":"RouterInsufficientSyRepay","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualYtOut","type":"uint256"},{"internalType":"uint256","name":"requiredYtOut","type":"uint256"}],"name":"RouterInsufficientYtOut","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualMaking","type":"uint256"},{"internalType":"uint256","name":"actualTaking","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"limitRouterCallback","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"ptToAccount","type":"int256"},{"internalType":"int256","name":"syToAccount","type":"int256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080806040523461001657611809908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063eb3a7d47146107e85763fa483e721461003257600080fd5b346101a35760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a35760243567ffffffffffffffff604435116101a3573660236044350112156101a3576044356004013567ffffffffffffffff81116101a35760443560248181019236920101116101a35780356100b5816109ab565b806101bc575050506100c860043561169d565b6040517fdb74aa1500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff604480358082013583166024850152602092849291839160009160640135165af19081156101b057600091610179575b5081811061014357005b604491604051917fc217d4a900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b90506020813d6020116101a8575b81610194602093836108d2565b810103126101a3575138610139565b600080fd5b3d9150610187565b6040513d6000823e3d90fd5b6101c5816109ab565b600181036104f35750506101de606460443501356115a1565b8160000382159281057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148317156104c457600081126101a357604051926102258461089a565b6002845260403660208601376040519261023e8461089a565b6002845260403660208601378083029283041417156104c457670de0b6b3a764000081018082116104c457670de0b6b3a763ffff8201116104c457670de0b6b3a763ffff670de0b6b3a764000091010461029782611639565b52336102a283611639565b526000600435126101a357906102c36102ba83611639565b51600435610a10565b6102cc83611675565b526102d681611675565b73ffffffffffffffffffffffffffffffffffffffff6044803501351690526040519182917fb0d889810000000000000000000000000000000000000000000000000000000083526044830160406004850152815180915260206064850192019060005b818110610495575050507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8382030160248401526020808351928381520192019060005b81811061047c57505050908060009203818373ffffffffffffffffffffffffffffffffffffffff60646044350135165af180156101b0576103bb575b005b3d806000833e6103cb81836108d2565b8101906020818303126101a35780519067ffffffffffffffff82116101a357019080601f830112156101a35781519167ffffffffffffffff831161044d576020808460051b9460405190610421838801836108d2565b815201938201019182116101a357602001915b81831061043d57005b8251815260209283019201610434565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b825184528594506020938401939092019160010161037d565b825173ffffffffffffffffffffffffffffffffffffffff16845286955060209384019390920191600101610339565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6104fc816109ab565b600281036106285750606081013591604082013591602081013591608090910135906105279061169d565b936000600435126101a357602060009161056961054687600435610a10565b9173ffffffffffffffffffffffffffffffffffffffff80911695169182866110d9565b6024604051809481937fbcb7ea5d0000000000000000000000000000000000000000000000000000000083523360048401525af19081156101b0576000916105f6575b508481106105bf57506103b993506110d9565b60449085604051917f21586e7800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b90506020813d602011610620575b81610611602093836108d2565b810103126101a35751386105ac565b3d9150610604565b6003919250610636816109ab565b036107b95760206106df61067373ffffffffffffffffffffffffffffffffffffffff93906020820135916040810135916080606083013592013590565b61068460049693959294963561169d565b6040517fdb74aa1500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff909716602488015295968792839160009183906044820190565b0393165af19384156101b057600094610785575b5080841061074e575081610707848361162c565b1061070e57005b60449261071a9161162c565b90604051917fc217d4a900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83604491604051917fa59b8c3100000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b9093506020813d6020116107b1575b816107a1602093836108d2565b810103126101a3575192386106f3565b3d9150610794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b346101a35760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a35760643567ffffffffffffffff81116101a357366023820112156101a35780600401359061084382610913565b61085060405191826108d2565b82815236602484840101116101a357600060208461089695602461088296018386013783010152602435600435610a1d565b60405191829160208352602083019061094d565b0390f35b6060810190811067ffffffffffffffff82111761044d57604052565b6080810190811067ffffffffffffffff82111761044d57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761044d57604052565b67ffffffffffffffff811161044d57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106109975750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610958565b600411156109b557565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b908160209103126101a3575173ffffffffffffffffffffffffffffffffffffffff811681036101a35790565b919082039182116104c457565b90825192608081602095810103126101a35783810151926004808510156101a3576040948584015173ffffffffffffffffffffffffffffffffffffffff93848216968783036101a357608060608801519701519586168096036101a357610a83846109ab565b831592838015611096575b15610e3657610a9c906115a1565b90670de0b6b3a764000090818102918183041490151715610e085781610ac19161162c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908111610e08578115610dda5790610afd929104610a10565b948511610d7e5786517fafd27bf5000000000000000000000000000000000000000000000000000000008152888185818a5afa908115610d735786888b959493610b4f93600091610d56575b506110d9565b610b5a6000926109ab565b15610c9e575085517fdb74aa150000000000000000000000000000000000000000000000000000000081523081840190815273ffffffffffffffffffffffffffffffffffffffff909416602085015291928290819060400103816000885af1908115610c9357908691600091610c64575b50938551928380927fd94073d40000000000000000000000000000000000000000000000000000000082525afa908115610c595790610c1491600091610c2c575b5033906112da565b825193840152818301528152610c298161089a565b90565b610c4c9150863d8811610c52575b610c4481836108d2565b8101906109e4565b38610c0c565b503d610c3a565b84513d6000823e3d90fd5b82819392503d8311610c8c575b610c7b81836108d2565b810103126101a35785905138610bcb565b503d610c71565b85513d6000823e3d90fd5b86517fdb74aa1500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9094169284019283523060208401529183908190604001038184885af1908115610d4b578091610d16575b50610d1191509233906112da565b610c14565b90508582813d8311610d44575b610d2d81836108d2565b81010312610d415750610d11905138610d03565b80fd5b503d610d23565b8551903d90823e3d90fd5b610d6d9150873d8911610c5257610c4481836108d2565b38610b49565b88513d6000823e3d90fd5b606483898951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601f60248201527f526f757465723a204d617820535920746f2070756c6c206578636565646564006044820152fd5b6012867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6011867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b509392915094851161103a5780610e4e6001926109ab565b03610fcc57610e5e8486806110d9565b8551917fbcb7ea5d00000000000000000000000000000000000000000000000000000000835230828401526000928881602481878b5af1908115610fc2578491610f91575b50808211610f36578891610eb691610a10565b958751928380927fafd27bf50000000000000000000000000000000000000000000000000000000082525afa918215610f2b57610c14939291869192610f0a575b508192610f03926110d9565b33906112da565b610f039250610f2590893d8b11610c5257610c4481836108d2565b91610ef7565b8651903d90823e3d90fd5b6064838a808b51927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f526f757465723a20496e73756666696369656e742053592072656465656d65646044820152fd5b90508881813d8311610fbb575b610fa881836108d2565b81010312610fb7575138610ea3565b8380fd5b503d610f9e565b88513d86823e3d90fd5b85517fd94073d400000000000000000000000000000000000000000000000000000000815287818381895afa90811561102f578661101392879260009161101857506110d9565b610e5e565b610d6d91508b3d8d11610c5257610c4481836108d2565b87513d6000823e3d90fd5b606482898951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601f60248201527f526f757465723a204d617820505920746f2070756c6c206578636565646564006044820152fd5b506110a0856109ab565b60028514610a8e565b3d156110d4573d906110ba82610913565b916110c860405193846108d2565b82523d6000602084013e565b606090565b82156112d55773ffffffffffffffffffffffffffffffffffffffff90811680611175575050600080809381935af161110f6110a9565b501561111757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6574682073656e64206661696c656400000000000000000000000000000000006044820152fd5b60409391935191602094858401947fa9059cbb0000000000000000000000000000000000000000000000000000000086521660248401526044830152604482526111be826108b6565b604051916040830183811067ffffffffffffffff82111761044d576040528483527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564838601525161122093600091829182855af161121a6110a9565b91611703565b8051908282159283156112bd575b505050156112395750565b608490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6112cd9350820181019101611685565b38828161122e565b505050565b9073ffffffffffffffffffffffffffffffffffffffff9081831692831561159b57604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff841660248201526020959193918690829060449082905afa8015610c5957600090611562575b6b7fffffffffffffffffffffff91501061137f575b5050505050565b825193600080878701927f095ea7b30000000000000000000000000000000000000000000000000000000094858552169283602489015260449782898201528881526113ca816108b6565b519082875af16113d86110a9565b81611532575b50156114d657916000929183809386519089820193845260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8882015287815261142b816108b6565b51925af16114376110a9565b816114a6575b501561144a578080611378565b606492917f5361666520417070726f766500000000000000000000000000000000000000009151927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b805180159250859083156114be575b5050503861143d565b6114ce9350820181019101611685565b3884816114b5565b6064867f5361666520417070726f76650000000000000000000000000000000000000000878751927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b8051801592508890831561154a575b505050386113de565b61155a9350820181019101611685565b388781611541565b508581813d8311611594575b61157881836108d2565b810103126101a3576b7fffffffffffffffffffffff9051611363565b503d61156e565b50505050565b602073ffffffffffffffffffffffffffffffffffffffff600460009360405194859384927f1d52edc4000000000000000000000000000000000000000000000000000000008452165af19081156101b0576000916115fd575090565b90506020813d602011611624575b81611618602093836108d2565b810103126101a3575190565b3d915061160b565b919082018092116104c457565b8051156116465760200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051600110156116465760400190565b908160209103126101a3575180151581036101a35790565b6000808213156116ab575090565b7f800000000000000000000000000000000000000000000000000000000000000082146116d6570390565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b9192901561177e5750815115611717575090565b3b156117205790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156117915750805190602001fd5b6117cf906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061094d565b0390fdfea26469706673582212201637a14b15f5c476006d57482e3658ef4dcd6210d23118268316c53f00d65aaa64736f6c63430008170033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063eb3a7d47146107e85763fa483e721461003257600080fd5b346101a35760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a35760243567ffffffffffffffff604435116101a3573660236044350112156101a3576044356004013567ffffffffffffffff81116101a35760443560248181019236920101116101a35780356100b5816109ab565b806101bc575050506100c860043561169d565b6040517fdb74aa1500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff604480358082013583166024850152602092849291839160009160640135165af19081156101b057600091610179575b5081811061014357005b604491604051917fc217d4a900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b90506020813d6020116101a8575b81610194602093836108d2565b810103126101a3575138610139565b600080fd5b3d9150610187565b6040513d6000823e3d90fd5b6101c5816109ab565b600181036104f35750506101de606460443501356115a1565b8160000382159281057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148317156104c457600081126101a357604051926102258461089a565b6002845260403660208601376040519261023e8461089a565b6002845260403660208601378083029283041417156104c457670de0b6b3a764000081018082116104c457670de0b6b3a763ffff8201116104c457670de0b6b3a763ffff670de0b6b3a764000091010461029782611639565b52336102a283611639565b526000600435126101a357906102c36102ba83611639565b51600435610a10565b6102cc83611675565b526102d681611675565b73ffffffffffffffffffffffffffffffffffffffff6044803501351690526040519182917fb0d889810000000000000000000000000000000000000000000000000000000083526044830160406004850152815180915260206064850192019060005b818110610495575050507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8382030160248401526020808351928381520192019060005b81811061047c57505050908060009203818373ffffffffffffffffffffffffffffffffffffffff60646044350135165af180156101b0576103bb575b005b3d806000833e6103cb81836108d2565b8101906020818303126101a35780519067ffffffffffffffff82116101a357019080601f830112156101a35781519167ffffffffffffffff831161044d576020808460051b9460405190610421838801836108d2565b815201938201019182116101a357602001915b81831061043d57005b8251815260209283019201610434565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b825184528594506020938401939092019160010161037d565b825173ffffffffffffffffffffffffffffffffffffffff16845286955060209384019390920191600101610339565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6104fc816109ab565b600281036106285750606081013591604082013591602081013591608090910135906105279061169d565b936000600435126101a357602060009161056961054687600435610a10565b9173ffffffffffffffffffffffffffffffffffffffff80911695169182866110d9565b6024604051809481937fbcb7ea5d0000000000000000000000000000000000000000000000000000000083523360048401525af19081156101b0576000916105f6575b508481106105bf57506103b993506110d9565b60449085604051917f21586e7800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b90506020813d602011610620575b81610611602093836108d2565b810103126101a35751386105ac565b3d9150610604565b6003919250610636816109ab565b036107b95760206106df61067373ffffffffffffffffffffffffffffffffffffffff93906020820135916040810135916080606083013592013590565b61068460049693959294963561169d565b6040517fdb74aa1500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff909716602488015295968792839160009183906044820190565b0393165af19384156101b057600094610785575b5080841061074e575081610707848361162c565b1061070e57005b60449261071a9161162c565b90604051917fc217d4a900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b83604491604051917fa59b8c3100000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b9093506020813d6020116107b1575b816107a1602093836108d2565b810103126101a3575192386106f3565b3d9150610794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b346101a35760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a35760643567ffffffffffffffff81116101a357366023820112156101a35780600401359061084382610913565b61085060405191826108d2565b82815236602484840101116101a357600060208461089695602461088296018386013783010152602435600435610a1d565b60405191829160208352602083019061094d565b0390f35b6060810190811067ffffffffffffffff82111761044d57604052565b6080810190811067ffffffffffffffff82111761044d57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761044d57604052565b67ffffffffffffffff811161044d57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106109975750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201610958565b600411156109b557565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b908160209103126101a3575173ffffffffffffffffffffffffffffffffffffffff811681036101a35790565b919082039182116104c457565b90825192608081602095810103126101a35783810151926004808510156101a3576040948584015173ffffffffffffffffffffffffffffffffffffffff93848216968783036101a357608060608801519701519586168096036101a357610a83846109ab565b831592838015611096575b15610e3657610a9c906115a1565b90670de0b6b3a764000090818102918183041490151715610e085781610ac19161162c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908111610e08578115610dda5790610afd929104610a10565b948511610d7e5786517fafd27bf5000000000000000000000000000000000000000000000000000000008152888185818a5afa908115610d735786888b959493610b4f93600091610d56575b506110d9565b610b5a6000926109ab565b15610c9e575085517fdb74aa150000000000000000000000000000000000000000000000000000000081523081840190815273ffffffffffffffffffffffffffffffffffffffff909416602085015291928290819060400103816000885af1908115610c9357908691600091610c64575b50938551928380927fd94073d40000000000000000000000000000000000000000000000000000000082525afa908115610c595790610c1491600091610c2c575b5033906112da565b825193840152818301528152610c298161089a565b90565b610c4c9150863d8811610c52575b610c4481836108d2565b8101906109e4565b38610c0c565b503d610c3a565b84513d6000823e3d90fd5b82819392503d8311610c8c575b610c7b81836108d2565b810103126101a35785905138610bcb565b503d610c71565b85513d6000823e3d90fd5b86517fdb74aa1500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9094169284019283523060208401529183908190604001038184885af1908115610d4b578091610d16575b50610d1191509233906112da565b610c14565b90508582813d8311610d44575b610d2d81836108d2565b81010312610d415750610d11905138610d03565b80fd5b503d610d23565b8551903d90823e3d90fd5b610d6d9150873d8911610c5257610c4481836108d2565b38610b49565b88513d6000823e3d90fd5b606483898951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601f60248201527f526f757465723a204d617820535920746f2070756c6c206578636565646564006044820152fd5b6012867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6011867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b509392915094851161103a5780610e4e6001926109ab565b03610fcc57610e5e8486806110d9565b8551917fbcb7ea5d00000000000000000000000000000000000000000000000000000000835230828401526000928881602481878b5af1908115610fc2578491610f91575b50808211610f36578891610eb691610a10565b958751928380927fafd27bf50000000000000000000000000000000000000000000000000000000082525afa918215610f2b57610c14939291869192610f0a575b508192610f03926110d9565b33906112da565b610f039250610f2590893d8b11610c5257610c4481836108d2565b91610ef7565b8651903d90823e3d90fd5b6064838a808b51927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f526f757465723a20496e73756666696369656e742053592072656465656d65646044820152fd5b90508881813d8311610fbb575b610fa881836108d2565b81010312610fb7575138610ea3565b8380fd5b503d610f9e565b88513d86823e3d90fd5b85517fd94073d400000000000000000000000000000000000000000000000000000000815287818381895afa90811561102f578661101392879260009161101857506110d9565b610e5e565b610d6d91508b3d8d11610c5257610c4481836108d2565b87513d6000823e3d90fd5b606482898951917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601f60248201527f526f757465723a204d617820505920746f2070756c6c206578636565646564006044820152fd5b506110a0856109ab565b60028514610a8e565b3d156110d4573d906110ba82610913565b916110c860405193846108d2565b82523d6000602084013e565b606090565b82156112d55773ffffffffffffffffffffffffffffffffffffffff90811680611175575050600080809381935af161110f6110a9565b501561111757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6574682073656e64206661696c656400000000000000000000000000000000006044820152fd5b60409391935191602094858401947fa9059cbb0000000000000000000000000000000000000000000000000000000086521660248401526044830152604482526111be826108b6565b604051916040830183811067ffffffffffffffff82111761044d576040528483527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564838601525161122093600091829182855af161121a6110a9565b91611703565b8051908282159283156112bd575b505050156112395750565b608490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6112cd9350820181019101611685565b38828161122e565b505050565b9073ffffffffffffffffffffffffffffffffffffffff9081831692831561159b57604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff841660248201526020959193918690829060449082905afa8015610c5957600090611562575b6b7fffffffffffffffffffffff91501061137f575b5050505050565b825193600080878701927f095ea7b30000000000000000000000000000000000000000000000000000000094858552169283602489015260449782898201528881526113ca816108b6565b519082875af16113d86110a9565b81611532575b50156114d657916000929183809386519089820193845260248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8882015287815261142b816108b6565b51925af16114376110a9565b816114a6575b501561144a578080611378565b606492917f5361666520417070726f766500000000000000000000000000000000000000009151927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b805180159250859083156114be575b5050503861143d565b6114ce9350820181019101611685565b3884816114b5565b6064867f5361666520417070726f76650000000000000000000000000000000000000000878751927f08c379a00000000000000000000000000000000000000000000000000000000084526004840152600c6024840152820152fd5b8051801592508890831561154a575b505050386113de565b61155a9350820181019101611685565b388781611541565b508581813d8311611594575b61157881836108d2565b810103126101a3576b7fffffffffffffffffffffff9051611363565b503d61156e565b50505050565b602073ffffffffffffffffffffffffffffffffffffffff600460009360405194859384927f1d52edc4000000000000000000000000000000000000000000000000000000008452165af19081156101b0576000916115fd575090565b90506020813d602011611624575b81611618602093836108d2565b810103126101a3575190565b3d915061160b565b919082018092116104c457565b8051156116465760200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051600110156116465760400190565b908160209103126101a3575180151581036101a35790565b6000808213156116ab575090565b7f800000000000000000000000000000000000000000000000000000000000000082146116d6570390565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b9192901561177e5750815115611717575090565b3b156117205790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156117915750805190602001fd5b6117cf906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260206004840152602483019061094d565b0390fdfea26469706673582212201637a14b15f5c476006d57482e3658ef4dcd6210d23118268316c53f00d65aaa64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.