Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
Multichain Info
No addresses found
Loading...
Loading
Contract Name:
ActionCallbackV3
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 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: 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; 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 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) } } }
// 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; 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 "../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 OrderFilledV2( bytes32 indexed orderHash, OrderType indexed orderType, address indexed YT, address token, uint256 netInputFromMaker, uint256 netOutputToMaker, uint256 feeAmount, uint256 notionalVolume, address maker, address taker ); // @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; /* --- Deprecated events --- */ // deprecate on 7/1/2024, prior to official launch event OrderFilled( bytes32 indexed orderHash, OrderType indexed orderType, address indexed YT, address token, uint256 netInputFromMaker, uint256 netOutputToMaker, uint256 feeAmount, uint256 notionalVolume ); }
// 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; 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 /* * 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: 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/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. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ 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: 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 "./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; interface IRewardManager { function userReward(address token, address user) external view returns (uint128 index, uint128 accrued); }
// 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: 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.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) (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 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 // 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); } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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
6080806040523461001657611271908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063eb3a7d47146106435763fa483e721461003257600080fd5b346101455760603660031901126101455760243567ffffffffffffffff6044351161014557366023604435011215610145576044356004013567ffffffffffffffff81116101455760443560248181019236920101116101455780356100978161078d565b8061015e575050506100aa6004356111d7565b60405163db74aa1560e01b81523360048201526001600160a01b03604480358082013583166024850152602092849291839160009160640135165af19081156101525760009161011c575b508181106100ff57005b6044916040519163c217d4a960e01b835260048301526024820152fd5b90506020813d821161014a575b816101366020938361070f565b810103126101455751386100f5565b600080fd5b3d9150610129565b6040513d6000823e3d90fd5b6101678161078d565b6001810361040d57505061018060646044350135610cf0565b9080806000030560001914811517156103f75760008181031261014557604051916101aa836106d7565b600283526040366020850137604051916101c3836106d7565b6002835260403660208501378015600082900383810204831417156103f75760008190038202670de0b6b3a76400008101106103f75760008190038202670de0b6b3a76400008101670de0b6b3a763ffff909101116103f757670de0b6b3a764000091670de0b6b3a763ffff9160000302010461023f82611208565b523361024a83611208565b52600060043512610145579061026b61026283611208565b516004356107cc565b6102748361122b565b5261027e8161122b565b60018060a01b0360448035013516905260405191829163b0d8898160e01b83526044830160406004850152815180915260206064850192019060005b8181106103d5575050506003198382030160248401526020808351928381520192019060005b8181106103bc575060009392839003915082905083604435606401356001600160a01b03165af1801561015257610314575b005b3d806000833e610324818361070f565b8101906020818303126101455780519067ffffffffffffffff821161014557019080601f830112156101455781519167ffffffffffffffff83116103a6576020808460051b946040519061037a8388018361070f565b8152019382010191821161014557602001915b81831061039657005b825181526020928301920161038d565b634e487b7160e01b600052604160045260246000fd5b82518452859450602093840193909201916001016102e0565b82516001600160a01b03168452869550602093840193909201916001016102ba565b634e487b7160e01b600052601160045260246000fd5b6104168161078d565b60028103610502575060608101359160408201359160208101359160809091013590610441906111d7565b93600435600081126101455760009161047661045f876020946107cc565b6001600160a01b0392831695909216918286610d93565b60246040518094819363bcb7ea5d60e01b83523360048401525af1908115610152576000916104d1575b508481106104b357506103129350610d93565b604490856040519163042b0dcf60e31b835260048301526024820152fd5b90506020813d82116104fa575b816104eb6020938361070f565b810103126101455751386104a0565b3d91506104de565b60039192506105108161078d565b0361062d57602061057e61053a600093906020820135916040810135916080606083013592013590565b61054b6004969395929496356111d7565b60405163db74aa1560e01b81523360048201526001600160a01b0390971660248801529596879283919082906044820190565b03926001600160a01b03165af1938415610152576000946105fa575b508084106105dc5750816105ae8483610d56565b106105b557005b6044926105c191610d56565b906040519163c217d4a960e01b835260048301526024820152fd5b836044916040519163a59b8c3160e01b835260048301526024820152fd5b9093506020813d8211610625575b816106156020938361070f565b810103126101455751923861059a565b3d9150610608565b634e487b7160e01b600052600160045260246000fd5b346101455760803660031901126101455760643567ffffffffffffffff811161014557366023820112156101455780600401359061068082610731565b61068d604051918261070f565b82815236602484840101116101455760006020846106d39560246106bf960183860137830101526024356004356107d9565b60405191829160208352602083019061074d565b0390f35b6060810190811067ffffffffffffffff8211176103a657604052565b6080810190811067ffffffffffffffff8211176103a657604052565b90601f8019910116810190811067ffffffffffffffff8211176103a657604052565b67ffffffffffffffff81116103a657601f01601f191660200190565b919082519283825260005b848110610779575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610758565b6004111561079757565b634e487b7160e01b600052602160045260246000fd5b9081602091031261014557516001600160a01b03811681036101455790565b919082039182116103f757565b90608083805181010312610145576020928381015192600480851015610145576040948584015160018060a01b0393848216968783036101455760806060880151970151958616809603610145576108308461078d565b831592838015610cdd575b15610afb5761084990610cf0565b90670de0b6b3a764000090818102918183041490151715610ae6578161086e91610d56565b6000198101908111610ae6578115610ad1579061088c9291046107cc565b948511610a8e57865163afd27bf560e01b8152888185818a5afa908115610a835786888b9594936108c593600091610a66575b50610d93565b6108d060009261078d565b156109d75750855163db74aa1560e01b8152308184019081526001600160a01b03909416602085015291928290819060400103816000885af19081156109cc5790869160009161099b575b50938551928380926336501cf560e21b82525afa908115610990579061094b91600091610963575b503390610fcf565b825193840152818301528152610960816106d7565b90565b6109839150863d8811610989575b61097b818361070f565b8101906107ad565b38610943565b503d610971565b84513d6000823e3d90fd5b9182813d83116109c5575b6109b0818361070f565b810103126109c257508590513861091b565b80fd5b503d6109a6565b85513d6000823e3d90fd5b865163db74aa1560e01b81526001600160a01b039094169284019283523060208401529183908190604001038184885af1908115610a5b578091610a29575b50610a249150923390610fcf565b61094b565b90508582813d8311610a54575b610a40818361070f565b810103126109c25750610a24905138610a16565b503d610a36565b8551903d90823e3d90fd5b610a7d9150873d89116109895761097b818361070f565b386108bf565b88513d6000823e3d90fd5b865162461bcd60e51b8152808401899052601f60248201527f526f757465723a204d617820535920746f2070756c6c206578636565646564006044820152606490fd5b601286634e487b7160e01b6000525260246000fd5b601186634e487b7160e01b6000525260246000fd5b5093929150948511610c9a5780610b1360019261078d565b03610c4557610b23848680610d93565b855163bcb7ea5d60e01b81523082820152600092908881602481878b5af1908115610c3b578491610c0a575b50808211610bc9578891610b62916107cc565b9587519283809263afd27bf560e01b82525afa918215610bbe5761094b939291869192610b9d575b508192610b9692610d93565b3390610fcf565b610b969250610bb890893d8b116109895761097b818361070f565b91610b8a565b8651903d90823e3d90fd5b6064838a808b519262461bcd60e51b845283015260248201527f526f757465723a20496e73756666696369656e742053592072656465656d65646044820152fd5b90508881813d8311610c34575b610c21818361070f565b81010312610c30575138610b4f565b8380fd5b503d610c17565b88513d86823e3d90fd5b85516336501cf560e21b815287818381895afa908115610c8f5786610c73928792600091610c785750610d93565b610b23565b610a7d91508b3d8d116109895761097b818361070f565b87513d6000823e3d90fd5b865162461bcd60e51b8152808301899052601f60248201527f526f757465723a204d617820505920746f2070756c6c206578636565646564006044820152606490fd5b50610ce78561078d565b6002851461083b565b604051630754bb7160e21b815290602090829060049082906000906001600160a01b03165af190811561015257600091610d28575090565b906020823d8211610d4e575b81610d416020938361070f565b810103126109c257505190565b3d9150610d34565b919082018092116103f757565b3d15610d8e573d90610d7482610731565b91610d82604051938461070f565b82523d6000602084013e565b606090565b8215610f15576001600160a01b0390811680610dfb575050600080809381935af1610dbc610d63565b5015610dc457565b60405162461bcd60e51b815260206004820152600f60248201526e195d1a081cd95b990819985a5b1959608a1b6044820152606490fd5b604093919351916020948584019463a9059cbb60e01b8652166024840152604483015260448252610e2b826106f3565b604051916040830183811067ffffffffffffffff8211176103a6576040528483527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648386015251610e8d93600091829182855af1610e87610d63565b91610f32565b805190828215928315610efd575b50505015610ea65750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b610f0d9350820181019101610f1a565b388281610e9b565b505050565b90816020910312610145575180151581036101455790565b91929015610f945750815115610f46575090565b3b15610f4f5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015610fa75750805190602001fd5b60405162461bcd60e51b815260206004820152908190610fcb90602483019061074d565b0390fd5b6001600160a01b0380821692909183156111d15760408051636eb1769f60e11b81523060048201526001600160a01b03841660248201526020959193918690829060449082905afa801561099057600090611198575b6b7fffffffffffffffffffffff915010611041575b5050505050565b8251936000808787019263095ea7b360e01b9485855216928360248901526044978289820152888152611073816106f3565b519082875af1611081610d63565b81611168575b501561113657916000929183809386519089820193845260248201528119888201528781526110b5816106f3565b51925af16110c1610d63565b81611106575b50156110d457808061103a565b5162461bcd60e51b81526004810192909252600c60248301526b5361666520417070726f766560a01b90820152606490fd5b8051801592508590831561111e575b505050386110c7565b61112e9350820181019101610f1a565b388481611115565b835162461bcd60e51b815260048101879052600c60248201526b5361666520417070726f766560a01b81870152606490fd5b80518015925088908315611180575b50505038611087565b6111909350820181019101610f1a565b388781611177565b8682813d83116111ca575b6111ad818361070f565b810103126109c257506b7fffffffffffffffffffffff9051611025565b503d6111a3565b50505050565b6000808213156111e5575090565b600160ff1b82146111f4570390565b634e487b7160e01b81526011600452602490fd5b8051156112155760200190565b634e487b7160e01b600052603260045260246000fd5b805160011015611215576040019056fea2646970667358221220eae915742837c414d25a30152a5f7f94e40f065ccd94d68e1efc7451465ed65a64736f6c63430008140033
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063eb3a7d47146106435763fa483e721461003257600080fd5b346101455760603660031901126101455760243567ffffffffffffffff6044351161014557366023604435011215610145576044356004013567ffffffffffffffff81116101455760443560248181019236920101116101455780356100978161078d565b8061015e575050506100aa6004356111d7565b60405163db74aa1560e01b81523360048201526001600160a01b03604480358082013583166024850152602092849291839160009160640135165af19081156101525760009161011c575b508181106100ff57005b6044916040519163c217d4a960e01b835260048301526024820152fd5b90506020813d821161014a575b816101366020938361070f565b810103126101455751386100f5565b600080fd5b3d9150610129565b6040513d6000823e3d90fd5b6101678161078d565b6001810361040d57505061018060646044350135610cf0565b9080806000030560001914811517156103f75760008181031261014557604051916101aa836106d7565b600283526040366020850137604051916101c3836106d7565b6002835260403660208501378015600082900383810204831417156103f75760008190038202670de0b6b3a76400008101106103f75760008190038202670de0b6b3a76400008101670de0b6b3a763ffff909101116103f757670de0b6b3a764000091670de0b6b3a763ffff9160000302010461023f82611208565b523361024a83611208565b52600060043512610145579061026b61026283611208565b516004356107cc565b6102748361122b565b5261027e8161122b565b60018060a01b0360448035013516905260405191829163b0d8898160e01b83526044830160406004850152815180915260206064850192019060005b8181106103d5575050506003198382030160248401526020808351928381520192019060005b8181106103bc575060009392839003915082905083604435606401356001600160a01b03165af1801561015257610314575b005b3d806000833e610324818361070f565b8101906020818303126101455780519067ffffffffffffffff821161014557019080601f830112156101455781519167ffffffffffffffff83116103a6576020808460051b946040519061037a8388018361070f565b8152019382010191821161014557602001915b81831061039657005b825181526020928301920161038d565b634e487b7160e01b600052604160045260246000fd5b82518452859450602093840193909201916001016102e0565b82516001600160a01b03168452869550602093840193909201916001016102ba565b634e487b7160e01b600052601160045260246000fd5b6104168161078d565b60028103610502575060608101359160408201359160208101359160809091013590610441906111d7565b93600435600081126101455760009161047661045f876020946107cc565b6001600160a01b0392831695909216918286610d93565b60246040518094819363bcb7ea5d60e01b83523360048401525af1908115610152576000916104d1575b508481106104b357506103129350610d93565b604490856040519163042b0dcf60e31b835260048301526024820152fd5b90506020813d82116104fa575b816104eb6020938361070f565b810103126101455751386104a0565b3d91506104de565b60039192506105108161078d565b0361062d57602061057e61053a600093906020820135916040810135916080606083013592013590565b61054b6004969395929496356111d7565b60405163db74aa1560e01b81523360048201526001600160a01b0390971660248801529596879283919082906044820190565b03926001600160a01b03165af1938415610152576000946105fa575b508084106105dc5750816105ae8483610d56565b106105b557005b6044926105c191610d56565b906040519163c217d4a960e01b835260048301526024820152fd5b836044916040519163a59b8c3160e01b835260048301526024820152fd5b9093506020813d8211610625575b816106156020938361070f565b810103126101455751923861059a565b3d9150610608565b634e487b7160e01b600052600160045260246000fd5b346101455760803660031901126101455760643567ffffffffffffffff811161014557366023820112156101455780600401359061068082610731565b61068d604051918261070f565b82815236602484840101116101455760006020846106d39560246106bf960183860137830101526024356004356107d9565b60405191829160208352602083019061074d565b0390f35b6060810190811067ffffffffffffffff8211176103a657604052565b6080810190811067ffffffffffffffff8211176103a657604052565b90601f8019910116810190811067ffffffffffffffff8211176103a657604052565b67ffffffffffffffff81116103a657601f01601f191660200190565b919082519283825260005b848110610779575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610758565b6004111561079757565b634e487b7160e01b600052602160045260246000fd5b9081602091031261014557516001600160a01b03811681036101455790565b919082039182116103f757565b90608083805181010312610145576020928381015192600480851015610145576040948584015160018060a01b0393848216968783036101455760806060880151970151958616809603610145576108308461078d565b831592838015610cdd575b15610afb5761084990610cf0565b90670de0b6b3a764000090818102918183041490151715610ae6578161086e91610d56565b6000198101908111610ae6578115610ad1579061088c9291046107cc565b948511610a8e57865163afd27bf560e01b8152888185818a5afa908115610a835786888b9594936108c593600091610a66575b50610d93565b6108d060009261078d565b156109d75750855163db74aa1560e01b8152308184019081526001600160a01b03909416602085015291928290819060400103816000885af19081156109cc5790869160009161099b575b50938551928380926336501cf560e21b82525afa908115610990579061094b91600091610963575b503390610fcf565b825193840152818301528152610960816106d7565b90565b6109839150863d8811610989575b61097b818361070f565b8101906107ad565b38610943565b503d610971565b84513d6000823e3d90fd5b9182813d83116109c5575b6109b0818361070f565b810103126109c257508590513861091b565b80fd5b503d6109a6565b85513d6000823e3d90fd5b865163db74aa1560e01b81526001600160a01b039094169284019283523060208401529183908190604001038184885af1908115610a5b578091610a29575b50610a249150923390610fcf565b61094b565b90508582813d8311610a54575b610a40818361070f565b810103126109c25750610a24905138610a16565b503d610a36565b8551903d90823e3d90fd5b610a7d9150873d89116109895761097b818361070f565b386108bf565b88513d6000823e3d90fd5b865162461bcd60e51b8152808401899052601f60248201527f526f757465723a204d617820535920746f2070756c6c206578636565646564006044820152606490fd5b601286634e487b7160e01b6000525260246000fd5b601186634e487b7160e01b6000525260246000fd5b5093929150948511610c9a5780610b1360019261078d565b03610c4557610b23848680610d93565b855163bcb7ea5d60e01b81523082820152600092908881602481878b5af1908115610c3b578491610c0a575b50808211610bc9578891610b62916107cc565b9587519283809263afd27bf560e01b82525afa918215610bbe5761094b939291869192610b9d575b508192610b9692610d93565b3390610fcf565b610b969250610bb890893d8b116109895761097b818361070f565b91610b8a565b8651903d90823e3d90fd5b6064838a808b519262461bcd60e51b845283015260248201527f526f757465723a20496e73756666696369656e742053592072656465656d65646044820152fd5b90508881813d8311610c34575b610c21818361070f565b81010312610c30575138610b4f565b8380fd5b503d610c17565b88513d86823e3d90fd5b85516336501cf560e21b815287818381895afa908115610c8f5786610c73928792600091610c785750610d93565b610b23565b610a7d91508b3d8d116109895761097b818361070f565b87513d6000823e3d90fd5b865162461bcd60e51b8152808301899052601f60248201527f526f757465723a204d617820505920746f2070756c6c206578636565646564006044820152606490fd5b50610ce78561078d565b6002851461083b565b604051630754bb7160e21b815290602090829060049082906000906001600160a01b03165af190811561015257600091610d28575090565b906020823d8211610d4e575b81610d416020938361070f565b810103126109c257505190565b3d9150610d34565b919082018092116103f757565b3d15610d8e573d90610d7482610731565b91610d82604051938461070f565b82523d6000602084013e565b606090565b8215610f15576001600160a01b0390811680610dfb575050600080809381935af1610dbc610d63565b5015610dc457565b60405162461bcd60e51b815260206004820152600f60248201526e195d1a081cd95b990819985a5b1959608a1b6044820152606490fd5b604093919351916020948584019463a9059cbb60e01b8652166024840152604483015260448252610e2b826106f3565b604051916040830183811067ffffffffffffffff8211176103a6576040528483527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648386015251610e8d93600091829182855af1610e87610d63565b91610f32565b805190828215928315610efd575b50505015610ea65750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b610f0d9350820181019101610f1a565b388281610e9b565b505050565b90816020910312610145575180151581036101455790565b91929015610f945750815115610f46575090565b3b15610f4f5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015610fa75750805190602001fd5b60405162461bcd60e51b815260206004820152908190610fcb90602483019061074d565b0390fd5b6001600160a01b0380821692909183156111d15760408051636eb1769f60e11b81523060048201526001600160a01b03841660248201526020959193918690829060449082905afa801561099057600090611198575b6b7fffffffffffffffffffffff915010611041575b5050505050565b8251936000808787019263095ea7b360e01b9485855216928360248901526044978289820152888152611073816106f3565b519082875af1611081610d63565b81611168575b501561113657916000929183809386519089820193845260248201528119888201528781526110b5816106f3565b51925af16110c1610d63565b81611106575b50156110d457808061103a565b5162461bcd60e51b81526004810192909252600c60248301526b5361666520417070726f766560a01b90820152606490fd5b8051801592508590831561111e575b505050386110c7565b61112e9350820181019101610f1a565b388481611115565b835162461bcd60e51b815260048101879052600c60248201526b5361666520417070726f766560a01b81870152606490fd5b80518015925088908315611180575b50505038611087565b6111909350820181019101610f1a565b388781611177565b8682813d83116111ca575b6111ad818361070f565b810103126109c257506b7fffffffffffffffffffffff9051611025565b503d6111a3565b50505050565b6000808213156111e5575090565b600160ff1b82146111f4570390565b634e487b7160e01b81526011600452602490fd5b8051156112155760200190565b634e487b7160e01b600052603260045260246000fd5b805160011015611215576040019056fea2646970667358221220eae915742837c414d25a30152a5f7f94e40f065ccd94d68e1efc7451465ed65a64736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.