编译器
0.8.17+commit.8df45f5f
文件 1 的 35:ActionBaseMintRedeem.sol
pragma solidity 0.8.17;
import "../../core/libraries/TokenHelper.sol";
import "../../interfaces/IStandardizedYield.sol";
import "../../interfaces/IPYieldToken.sol";
import "../../interfaces/IPBulkSeller.sol";
import "../../core/libraries/Errors.sol";
import "../swap-aggregator/IPSwapAggregator.sol";
struct TokenInput {
address tokenIn;
uint256 netTokenIn;
address tokenMintSy;
address bulk;
address pendleSwap;
SwapData swapData;
}
struct TokenOutput {
address tokenOut;
uint256 minTokenOut;
address tokenRedeemSy;
address bulk;
address pendleSwap;
SwapData swapData;
}
abstract contract ActionBaseMintRedeem is TokenHelper {
bytes internal constant EMPTY_BYTES = abi.encode();
function _mintSyFromToken(
address receiver,
address SY,
uint256 minSyOut,
TokenInput calldata inp
) internal returns (uint256 netSyOut) {
SwapType swapType = inp.swapData.swapType;
uint256 netTokenMintSy;
if (swapType == SwapType.NONE) {
_transferIn(inp.tokenIn, msg.sender, inp.netTokenIn);
netTokenMintSy = inp.netTokenIn;
} else if (swapType == SwapType.ETH_WETH) {
_transferIn(inp.tokenIn, msg.sender, inp.netTokenIn);
_wrap_unwrap_ETH(inp.tokenIn, inp.tokenMintSy, inp.netTokenIn);
netTokenMintSy = inp.netTokenIn;
} else {
if (inp.tokenIn == NATIVE) _transferIn(NATIVE, msg.sender, inp.netTokenIn);
else _transferFrom(IERC20(inp.tokenIn), msg.sender, inp.pendleSwap, inp.netTokenIn);
IPSwapAggregator(inp.pendleSwap).swap{
value: inp.tokenIn == NATIVE ? inp.netTokenIn : 0
}(inp.tokenIn, inp.netTokenIn, inp.swapData);
netTokenMintSy = _selfBalance(inp.tokenMintSy);
}
netSyOut = __mintSy(receiver, SY, netTokenMintSy, minSyOut, inp);
}
function __mintSy(
address receiver,
address SY,
uint256 netTokenMintSy,
uint256 minSyOut,
TokenInput calldata inp
) private returns (uint256 netSyOut) {
uint256 netNative = inp.tokenMintSy == NATIVE ? netTokenMintSy : 0;
if (inp.bulk != address(0)) {
netSyOut = IPBulkSeller(inp.bulk).swapExactTokenForSy{ value: netNative }(
receiver,
netTokenMintSy,
minSyOut
);
} else {
netSyOut = IStandardizedYield(SY).deposit{ value: netNative }(
receiver,
inp.tokenMintSy,
netTokenMintSy,
minSyOut
);
}
}
function _redeemSyToToken(
address receiver,
address SY,
uint256 netSyIn,
TokenOutput calldata out,
bool doPull
) internal returns (uint256 netTokenOut) {
SwapType swapType = out.swapData.swapType;
if (swapType == SwapType.NONE) {
netTokenOut = __redeemSy(receiver, SY, netSyIn, out, doPull);
} else if (swapType == SwapType.ETH_WETH) {
netTokenOut = __redeemSy(address(this), SY, netSyIn, out, doPull);
_wrap_unwrap_ETH(out.tokenRedeemSy, out.tokenOut, netTokenOut);
_transferOut(out.tokenOut, receiver, netTokenOut);
} else {
uint256 netTokenRedeemed = __redeemSy(out.pendleSwap, SY, netSyIn, out, doPull);
IPSwapAggregator(out.pendleSwap).swap(
out.tokenRedeemSy,
netTokenRedeemed,
out.swapData
);
netTokenOut = _selfBalance(out.tokenOut);
_transferOut(out.tokenOut, receiver, netTokenOut);
}
if (netTokenOut < out.minTokenOut) {
revert Errors.RouterInsufficientTokenOut(netTokenOut, out.minTokenOut);
}
}
function __redeemSy(
address receiver,
address SY,
uint256 netSyIn,
TokenOutput calldata out,
bool doPull
) private returns (uint256 netTokenRedeemed) {
if (doPull) {
_transferFrom(IERC20(SY), msg.sender, _syOrBulk(SY, out), netSyIn);
}
if (out.bulk != address(0)) {
netTokenRedeemed = IPBulkSeller(out.bulk).swapExactSyForToken(
receiver,
netSyIn,
0,
true
);
} else {
netTokenRedeemed = IStandardizedYield(SY).redeem(
receiver,
netSyIn,
out.tokenRedeemSy,
0,
true
);
}
}
function _mintPyFromSy(
address receiver,
address SY,
address YT,
uint256 netSyIn,
uint256 minPyOut,
bool doPull
) internal returns (uint256 netPyOut) {
if (doPull) {
_transferFrom(IERC20(SY), msg.sender, YT, netSyIn);
}
netPyOut = IPYieldToken(YT).mintPY(receiver, receiver);
if (netPyOut < minPyOut) revert Errors.RouterInsufficientPYOut(netPyOut, minPyOut);
}
function _redeemPyToSy(
address receiver,
address YT,
uint256 netPyIn,
uint256 minSyOut
) internal returns (uint256 netSyOut) {
address PT = IPYieldToken(YT).PT();
_transferFrom(IERC20(PT), msg.sender, YT, netPyIn);
bool needToBurnYt = (!IPYieldToken(YT).isExpired());
if (needToBurnYt) _transferFrom(IERC20(YT), msg.sender, YT, netPyIn);
netSyOut = IPYieldToken(YT).redeemPY(receiver);
if (netSyOut < minSyOut) revert Errors.RouterInsufficientSyOut(netSyOut, minSyOut);
}
function _syOrBulk(address SY, TokenOutput calldata output)
internal
pure
returns (address addr)
{
return output.bulk != address(0) ? output.bulk : SY;
}
}
文件 2 的 35:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
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");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 3 的 35:BulkSellerMathCore.sol
pragma solidity 0.8.17;
import "../libraries/TokenHelper.sol";
import "../libraries/math/Math.sol";
import "../libraries/Errors.sol";
struct BulkSellerState {
uint256 rateTokenToSy;
uint256 rateSyToToken;
uint256 totalToken;
uint256 totalSy;
uint256 feeRate;
}
library BulkSellerMathCore {
using Math for uint256;
function swapExactTokenForSy(BulkSellerState memory state, uint256 netTokenIn)
internal
pure
returns (uint256 netSyOut)
{
netSyOut = calcSwapExactTokenForSy(state, netTokenIn);
state.totalToken += netTokenIn;
state.totalSy -= netSyOut;
}
function swapExactSyForToken(BulkSellerState memory state, uint256 netSyIn)
internal
pure
returns (uint256 netTokenOut)
{
netTokenOut = calcSwapExactSyForToken(state, netSyIn);
state.totalSy += netSyIn;
state.totalToken -= netTokenOut;
}
function calcSwapExactTokenForSy(BulkSellerState memory state, uint256 netTokenIn)
internal
pure
returns (uint256 netSyOut)
{
uint256 postFeeRate = state.rateTokenToSy.mulDown(Math.ONE - state.feeRate);
assert(postFeeRate != 0);
netSyOut = netTokenIn.mulDown(postFeeRate);
if (netSyOut > state.totalSy)
revert Errors.BulkInsufficientSyForTrade(state.totalSy, netSyOut);
}
function calcSwapExactSyForToken(BulkSellerState memory state, uint256 netSyIn)
internal
pure
returns (uint256 netTokenOut)
{
uint256 postFeeRate = state.rateSyToToken.mulDown(Math.ONE - state.feeRate);
assert(postFeeRate != 0);
netTokenOut = netSyIn.mulDown(postFeeRate);
if (netTokenOut > state.totalToken)
revert Errors.BulkInsufficientTokenForTrade(state.totalToken, netTokenOut);
}
function getTokenProp(BulkSellerState memory state) internal pure returns (uint256) {
uint256 totalToken = state.totalToken;
uint256 totalTokenFromSy = state.totalSy.mulDown(state.rateSyToToken);
return totalToken.divDown(totalToken + totalTokenFromSy);
}
function getReBalanceParams(BulkSellerState memory state, uint256 targetTokenProp)
internal
pure
returns (uint256 netTokenToDeposit, uint256 netSyToRedeem)
{
uint256 currentTokenProp = getTokenProp(state);
if (currentTokenProp > targetTokenProp) {
netTokenToDeposit = state
.totalToken
.mulDown(currentTokenProp - targetTokenProp)
.divDown(currentTokenProp);
} else {
uint256 currentSyProp = Math.ONE - currentTokenProp;
netSyToRedeem = state.totalSy.mulDown(targetTokenProp - currentTokenProp).divDown(
currentSyProp
);
}
}
function reBalanceTokenToSy(
BulkSellerState memory state,
uint256 netTokenToDeposit,
uint256 netSyFromToken,
uint256 maxDiff
) internal pure {
uint256 rate = netSyFromToken.divDown(netTokenToDeposit);
if (!Math.isAApproxB(rate, state.rateTokenToSy, maxDiff))
revert Errors.BulkBadRateTokenToSy(rate, state.rateTokenToSy, maxDiff);
state.totalToken -= netTokenToDeposit;
state.totalSy += netSyFromToken;
}
function reBalanceSyToToken(
BulkSellerState memory state,
uint256 netSyToRedeem,
uint256 netTokenFromSy,
uint256 maxDiff
) internal pure {
uint256 rate = netTokenFromSy.divDown(netSyToRedeem);
if (!Math.isAApproxB(rate, state.rateSyToToken, maxDiff))
revert Errors.BulkBadRateSyToToken(rate, state.rateSyToToken, maxDiff);
state.totalToken += netTokenFromSy;
state.totalSy -= netSyToRedeem;
}
function setRate(
BulkSellerState memory state,
uint256 rateSyToToken,
uint256 rateTokenToSy,
uint256 maxDiff
) internal pure {
if (
state.rateTokenToSy != 0 &&
!Math.isAApproxB(rateTokenToSy, state.rateTokenToSy, maxDiff)
) {
revert Errors.BulkBadRateTokenToSy(rateTokenToSy, state.rateTokenToSy, maxDiff);
}
if (
state.rateSyToToken != 0 &&
!Math.isAApproxB(rateSyToToken, state.rateSyToToken, maxDiff)
) {
revert Errors.BulkBadRateSyToToken(rateSyToToken, state.rateSyToToken, maxDiff);
}
state.rateTokenToSy = rateTokenToSy;
state.rateSyToToken = rateSyToToken;
}
}
文件 4 的 35:Errors.sol
pragma solidity 0.8.17;
library Errors {
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);
error ApproxFail();
error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps);
error ApproxBinarySearchInputInvalid(
uint256 approxGuessMin,
uint256 approxGuessMax,
uint256 minGuessMin,
uint256 maxGuessMax
);
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 MarketFactoryReserveFeePercentTooHigh(
uint8 reserveFeePercent,
uint8 maxReserveFeePercent
);
error MarketFactoryZeroTreasury();
error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor);
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 RouterExceededLimitSyIn(uint256 actualSyIn, uint256 limitSyIn);
error RouterExceededLimitPtIn(uint256 actualPtIn, uint256 limitPtIn);
error RouterExceededLimitYtIn(uint256 actualYtIn, uint256 limitYtIn);
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 YCExpired();
error YCNotExpired();
error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy);
error YCNothingToRedeem();
error YCPostExpiryDataNotSet();
error YCNoFloatingSy();
error YCFactoryInvalidExpiry();
error YCFactoryYieldContractExisted();
error YCFactoryZeroExpiryDivisor();
error YCFactoryZeroTreasury();
error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate);
error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate);
error SYInvalidTokenIn(address token);
error SYInvalidTokenOut(address token);
error SYZeroDeposit();
error SYZeroRedeem();
error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut);
error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);
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 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);
error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path);
error MsgNotFromReceiveEndpoint(address sender);
error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee);
error ApproxDstExecutionGasNotSet();
error InvalidRetryData();
error ArrayLengthMismatch();
error ArrayEmpty();
error ArrayOutOfBounds();
error ZeroAddress();
error FailedToSendEther();
error OnlyLayerZeroEndpoint();
error OnlyYT();
error OnlyYCFactory();
error OnlyWhitelisted();
error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual);
error UnsupportedSelector(uint256 aggregatorType, bytes4 selector);
}
文件 5 的 35:IDiamondCut.sol
pragma solidity ^0.8.0;
interface IDiamondCut {
enum FacetCutAction {
Add,
Replace,
Remove
}
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external;
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
文件 6 的 35:IDiamondLoupe.sol
pragma solidity ^0.8.0;
interface IDiamondLoupe {
struct Facet {
address facetAddress;
bytes4[] functionSelectors;
}
function facets() external view returns (Facet[] memory facets_);
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
function facetAddresses() external view returns (address[] memory facetAddresses_);
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
文件 7 的 35:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 8 的 35:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 35:IPActionAddRemoveLiq.sol
pragma solidity 0.8.17;
import "../router/base/MarketApproxLib.sol";
import "../router/base/ActionBaseMintRedeem.sol";
interface IPActionAddRemoveLiq {
event AddLiquidityDualSyAndPt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netSyUsed,
uint256 netPtUsed,
uint256 netLpOut
);
event AddLiquidityDualTokenAndPt(
address indexed caller,
address indexed market,
address indexed tokenIn,
address receiver,
uint256 netTokenUsed,
uint256 netPtUsed,
uint256 netLpOut
);
event AddLiquiditySinglePt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netPtIn,
uint256 netLpOut
);
event AddLiquiditySingleSy(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netSyIn,
uint256 netLpOut
);
event AddLiquiditySingleToken(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
uint256 netTokenIn,
uint256 netLpOut
);
event AddLiquiditySingleSyKeepYt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netSyIn,
uint256 netLpOut,
uint256 netYtOut
);
event AddLiquiditySingleTokenKeepYt(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
uint256 netTokenIn,
uint256 netLpOut,
uint256 netYtOut
);
event RemoveLiquidityDualSyAndPt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netLpToRemove,
uint256 netPtOut,
uint256 netSyOut
);
event RemoveLiquidityDualTokenAndPt(
address indexed caller,
address indexed market,
address indexed tokenOut,
address receiver,
uint256 netLpToRemove,
uint256 netPtOut,
uint256 netTokenOut
);
event RemoveLiquiditySinglePt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netLpToRemove,
uint256 netPtOut
);
event RemoveLiquiditySingleSy(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netLpToRemove,
uint256 netSyOut
);
event RemoveLiquiditySingleToken(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
uint256 netLpToRemove,
uint256 netTokenOut
);
function addLiquidityDualSyAndPt(
address receiver,
address market,
uint256 netSyDesired,
uint256 netPtDesired,
uint256 minLpOut
)
external
returns (
uint256 netLpOut,
uint256 netSyUsed,
uint256 netPtUsed
);
function addLiquidityDualTokenAndPt(
address receiver,
address market,
TokenInput calldata input,
uint256 netPtDesired,
uint256 minLpOut
)
external
payable
returns (
uint256 netLpOut,
uint256 netTokenUsed,
uint256 netPtUsed
);
function addLiquiditySinglePt(
address receiver,
address market,
uint256 netPtIn,
uint256 minLpOut,
ApproxParams calldata guessPtSwapToSy
) external returns (uint256 netLpOut, uint256 netSyFee);
function addLiquiditySingleSy(
address receiver,
address market,
uint256 netSyIn,
uint256 minLpOut,
ApproxParams calldata guessPtReceivedFromSy
) external returns (uint256 netLpOut, uint256 netSyFee);
function addLiquiditySingleToken(
address receiver,
address market,
uint256 minLpOut,
ApproxParams calldata guessPtReceivedFromSy,
TokenInput calldata input
) external payable returns (uint256 netLpOut, uint256 netSyFee);
function addLiquiditySingleSyKeepYt(
address receiver,
address market,
uint256 netSyIn,
uint256 minLpOut,
uint256 minYtOut
) external returns (uint256 netLpOut, uint256 netYtOut);
function addLiquiditySingleTokenKeepYt(
address receiver,
address market,
uint256 minLpOut,
uint256 minYtOut,
TokenInput calldata input
) external returns (uint256 netLpOut, uint256 netYtOut);
function removeLiquidityDualSyAndPt(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minSyOut,
uint256 minPtOut
) external returns (uint256 netSyOut, uint256 netPtOut);
function removeLiquidityDualTokenAndPt(
address receiver,
address market,
uint256 netLpToRemove,
TokenOutput calldata output,
uint256 minPtOut
) external returns (uint256 netTokenOut, uint256 netPtOut);
function removeLiquiditySinglePt(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minPtOut,
ApproxParams calldata guessPtOut
) external returns (uint256 netPtOut, uint256 netSyFee);
function removeLiquiditySingleSy(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minSyOut
) external returns (uint256 netSyOut, uint256 netSyFee);
function removeLiquiditySingleToken(
address receiver,
address market,
uint256 netLpToRemove,
TokenOutput calldata output
) external returns (uint256 netTokenOut, uint256 netSyFee);
}
文件 10 的 35:IPActionMintRedeem.sol
pragma solidity 0.8.17;
import "../router/base/MarketApproxLib.sol";
import "../router/base/ActionBaseMintRedeem.sol";
interface IPActionMintRedeem {
event MintSyFromToken(
address indexed caller,
address indexed tokenIn,
address indexed SY,
address receiver,
uint256 netTokenIn,
uint256 netSyOut
);
event RedeemSyToToken(
address indexed caller,
address indexed tokenOut,
address indexed SY,
address receiver,
uint256 netSyIn,
uint256 netTokenOut
);
event MintPyFromSy(
address indexed caller,
address indexed receiver,
address indexed YT,
uint256 netSyIn,
uint256 netPyOut
);
event RedeemPyToSy(
address indexed caller,
address indexed receiver,
address indexed YT,
uint256 netPyIn,
uint256 netSyOut
);
event MintPyFromToken(
address indexed caller,
address indexed tokenIn,
address indexed YT,
address receiver,
uint256 netTokenIn,
uint256 netPyOut
);
event RedeemPyToToken(
address indexed caller,
address indexed tokenOut,
address indexed YT,
address receiver,
uint256 netPyIn,
uint256 netTokenOut
);
function mintSyFromToken(
address receiver,
address SY,
uint256 minSyOut,
TokenInput calldata input
) external payable returns (uint256 netSyOut);
function redeemSyToToken(
address receiver,
address SY,
uint256 netSyIn,
TokenOutput calldata output
) external returns (uint256 netTokenOut);
function mintPyFromToken(
address receiver,
address YT,
uint256 minPyOut,
TokenInput calldata input
) external payable returns (uint256 netPyOut);
function redeemPyToToken(
address receiver,
address YT,
uint256 netPyIn,
TokenOutput calldata output
) external returns (uint256 netTokenOut);
function mintPyFromSy(
address receiver,
address YT,
uint256 netSyIn,
uint256 minPyOut
) external returns (uint256 netPyOut);
function redeemPyToSy(
address receiver,
address YT,
uint256 netPyIn,
uint256 minSyOut
) external returns (uint256 netSyOut);
function redeemDueInterestAndRewards(
address user,
address[] calldata sys,
address[] calldata yts,
address[] calldata markets
) external;
}
文件 11 的 35:IPActionMisc.sol
pragma solidity 0.8.17;
interface IPActionMisc {
struct MultiApproval {
address[] tokens;
address spender;
}
struct Call3 {
bool allowFailure;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
function approveInf(MultiApproval[] calldata) external;
function batchExec(Call3[] calldata calls) external returns (Result[] memory returnData);
}
文件 12 的 35:IPActionSwapPT.sol
pragma solidity 0.8.17;
import "../router/base/MarketApproxLib.sol";
import "../router/base/ActionBaseMintRedeem.sol";
interface IPActionSwapPT {
event SwapPtAndSy(
address indexed caller,
address indexed market,
address indexed receiver,
int256 netPtToAccount,
int256 netSyToAccount
);
event SwapPtAndToken(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
int256 netPtToAccount,
int256 netTokenToAccount
);
function swapExactPtForSy(
address receiver,
address market,
uint256 exactPtIn,
uint256 minSyOut
) external returns (uint256 netSyOut, uint256 netSyFee);
function swapPtForExactSy(
address receiver,
address market,
uint256 exactSyOut,
uint256 maxPtIn,
ApproxParams calldata guessPtIn
) external returns (uint256 netPtIn, uint256 netSyFee);
function swapSyForExactPt(
address receiver,
address market,
uint256 exactPtOut,
uint256 maxSyIn
) external returns (uint256 netSyIn, uint256 netSyFee);
function swapExactSyForPt(
address receiver,
address market,
uint256 exactSyIn,
uint256 minPtOut,
ApproxParams calldata guessPtOut
) external returns (uint256 netPtOut, uint256 netSyFee);
function swapExactTokenForPt(
address receiver,
address market,
uint256 minPtOut,
ApproxParams calldata guessPtOut,
TokenInput calldata input
) external payable returns (uint256 netPtOut, uint256 netSyFee);
function swapExactPtForToken(
address receiver,
address market,
uint256 exactPtIn,
TokenOutput calldata output
) external returns (uint256 netTokenOut, uint256 netSyFee);
}
文件 13 的 35:IPActionSwapYT.sol
pragma solidity 0.8.17;
import "../router/base/MarketApproxLib.sol";
import "../router/base/ActionBaseMintRedeem.sol";
interface IPActionSwapYT {
event SwapYtAndSy(
address indexed caller,
address indexed market,
address indexed receiver,
int256 netYtToAccount,
int256 netSyToAccount
);
event SwapYtAndToken(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
int256 netYtToAccount,
int256 netTokenToAccount
);
event SwapPtAndYt(
address indexed caller,
address indexed market,
address indexed receiver,
int256 netPtToAccount,
int256 netYtToAccount
);
function swapExactSyForYt(
address receiver,
address market,
uint256 exactSyIn,
uint256 minYtOut,
ApproxParams calldata guessYtOut
) external returns (uint256 netYtOut, uint256 netSyFee);
function swapExactYtForSy(
address receiver,
address market,
uint256 exactYtIn,
uint256 minSyOut
) external returns (uint256 netSyOut, uint256 netSyFee);
function swapSyForExactYt(
address receiver,
address market,
uint256 exactYtOut,
uint256 maxSyIn
) external returns (uint256 netSyIn, uint256 netSyFee);
function swapYtForExactSy(
address receiver,
address market,
uint256 exactSyOut,
uint256 maxYtIn,
ApproxParams calldata guessYtIn
) external returns (uint256 netYtIn, uint256 netSyFee);
function swapExactTokenForYt(
address receiver,
address market,
uint256 minYtOut,
ApproxParams calldata guessYtOut,
TokenInput calldata input
) external payable returns (uint256 netYtOut, uint256 netSyFee);
function swapExactYtForToken(
address receiver,
address market,
uint256 netYtIn,
TokenOutput calldata output
) external returns (uint256 netTokenOut, uint256 netSyFee);
function swapExactPtForYt(
address receiver,
address market,
uint256 exactPtIn,
uint256 minYtOut,
ApproxParams calldata guessTotalPtToSwap
) external returns (uint256 netYtOut, uint256 netSyFee);
function swapExactYtForPt(
address receiver,
address market,
uint256 exactYtIn,
uint256 minPtOut,
ApproxParams calldata guessTotalPtSwapped
) external returns (uint256 netPtOut, uint256 netSyFee);
}
文件 14 的 35:IPAllAction.sol
pragma solidity 0.8.17;
import "./IPActionAddRemoveLiq.sol";
import "./IPActionSwapPT.sol";
import "./IPActionSwapYT.sol";
import "./IPActionMintRedeem.sol";
import "./IPActionMisc.sol";
import "./IPMarketSwapCallback.sol";
import "./IDiamondLoupe.sol";
interface IPAllAction is
IPActionAddRemoveLiq,
IPActionSwapPT,
IPActionSwapYT,
IPActionMintRedeem,
IPActionMisc,
IPMarketSwapCallback,
IDiamondLoupe
{}
文件 15 的 35:IPBulkSeller.sol
pragma solidity 0.8.17;
import "../core/BulkSeller/BulkSellerMathCore.sol";
interface IPBulkSeller {
event SwapExactTokenForSy(address receiver, uint256 netTokenIn, uint256 netSyOut);
event SwapExactSyForToken(address receiver, uint256 netSyIn, uint256 netTokenOut);
event RateUpdated(
uint256 newRateTokenToSy,
uint256 newRateSyToToken,
uint256 oldRateTokenToSy,
uint256 oldRateSyToToken
);
event ReBalanceTokenToSy(
uint256 netTokenDeposit,
uint256 netSyFromToken,
uint256 newTokenProp,
uint256 oldTokenProp
);
event ReBalanceSyToToken(
uint256 netSyRedeem,
uint256 netTokenFromSy,
uint256 newTokenProp,
uint256 oldTokenProp
);
event ReserveUpdated(uint256 totalToken, uint256 totalSy);
event FeeRateUpdated(uint256 newFeeRate, uint256 oldFeeRate);
function swapExactTokenForSy(
address receiver,
uint256 netTokenIn,
uint256 minSyOut
) external payable returns (uint256 netSyOut);
function swapExactSyForToken(
address receiver,
uint256 exactSyIn,
uint256 minTokenOut,
bool swapFromInternalBalance
) external returns (uint256 netTokenOut);
function SY() external view returns (address);
function token() external view returns (address);
function readState() external view returns (BulkSellerState memory);
}
文件 16 的 35:IPInterestManagerYT.sol
pragma solidity 0.8.17;
interface IPInterestManagerYT {
function userInterest(address user)
external
view
returns (uint128 lastPYIndex, uint128 accruedInterest);
}
文件 17 的 35:IPMarketSwapCallback.sol
pragma solidity 0.8.17;
interface IPMarketSwapCallback {
function swapCallback(
int256 ptToAccount,
int256 syToAccount,
bytes calldata data
) external;
}
文件 18 的 35:IPPrincipalToken.sol
pragma solidity 0.8.17;
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);
}
文件 19 的 35:IPSwapAggregator.sol
pragma solidity 0.8.17;
struct SwapData {
SwapType swapType;
address extRouter;
bytes extCalldata;
bool needScale;
}
enum SwapType {
NONE,
KYBERSWAP,
ONE_INCH,
ETH_WETH
}
interface IPSwapAggregator {
function swap(
address tokenIn,
uint256 amountIn,
SwapData calldata swapData
) external payable;
}
文件 20 的 35:IPYieldToken.sol
pragma solidity 0.8.17;
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 WithdrawFeeToTreasury(uint256[] amountRewardsOut, uint256 syOut);
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);
}
文件 21 的 35:IRewardManager.sol
pragma solidity 0.8.17;
interface IRewardManager {
function userReward(address token, address user)
external
view
returns (uint128 index, uint128 accrued);
}
文件 22 的 35:IStandardizedYield.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IStandardizedYield is IERC20Metadata {
event Deposit(
address indexed caller,
address indexed receiver,
address indexed tokenIn,
uint256 amountDeposited,
uint256 amountSyOut
);
event Redeem(
address indexed caller,
address indexed receiver,
address indexed tokenOut,
uint256 amountSyToRedeem,
uint256 amountTokenOut
);
enum AssetType {
TOKEN,
LIQUIDITY
}
event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts);
function deposit(
address receiver,
address tokenIn,
uint256 amountTokenToDeposit,
uint256 minSharesOut
) external payable returns (uint256 amountSharesOut);
function redeem(
address receiver,
uint256 amountSharesToRedeem,
address tokenOut,
uint256 minTokenOut,
bool burnFromInternalBalance
) external returns (uint256 amountTokenOut);
function exchangeRate() external view returns (uint256 res);
function claimRewards(address user) external returns (uint256[] memory rewardAmounts);
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);
function getRewardTokens() external view returns (address[] memory);
function yieldToken() external view returns (address);
function getTokensIn() external view returns (address[] memory res);
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);
function assetInfo()
external
view
returns (
AssetType assetType,
address assetAddress,
uint8 assetDecimals
);
}
文件 23 的 35:IWETH.sol
pragma solidity 0.8.17;
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;
}
文件 24 的 35:LogExpMath.sol
pragma solidity 0.8.17;
library LogExpMath {
int256 constant ONE_18 = 1e18;
int256 constant ONE_20 = 1e20;
int256 constant ONE_36 = 1e36;
int256 constant MAX_NATURAL_EXPONENT = 130e18;
int256 constant MIN_NATURAL_EXPONENT = -41e18;
int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17;
int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17;
uint256 constant MILD_EXPONENT_BOUND = 2**254 / uint256(ONE_20);
int256 constant x0 = 128000000000000000000;
int256 constant a0 = 38877084059945950922200000000000000000000000000000000000;
int256 constant x1 = 64000000000000000000;
int256 constant a1 = 6235149080811616882910000000;
int256 constant x2 = 3200000000000000000000;
int256 constant a2 = 7896296018268069516100000000000000;
int256 constant x3 = 1600000000000000000000;
int256 constant a3 = 888611052050787263676000000;
int256 constant x4 = 800000000000000000000;
int256 constant a4 = 298095798704172827474000;
int256 constant x5 = 400000000000000000000;
int256 constant a5 = 5459815003314423907810;
int256 constant x6 = 200000000000000000000;
int256 constant a6 = 738905609893065022723;
int256 constant x7 = 100000000000000000000;
int256 constant a7 = 271828182845904523536;
int256 constant x8 = 50000000000000000000;
int256 constant a8 = 164872127070012814685;
int256 constant x9 = 25000000000000000000;
int256 constant a9 = 128402541668774148407;
int256 constant x10 = 12500000000000000000;
int256 constant a10 = 113314845306682631683;
int256 constant x11 = 6250000000000000000;
int256 constant a11 = 106449445891785942956;
function exp(int256 x) internal pure returns (int256) {
unchecked {
require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, "Invalid exponent");
if (x < 0) {
return ((ONE_18 * ONE_18) / exp(-x));
}
int256 firstAN;
if (x >= x0) {
x -= x0;
firstAN = a0;
} else if (x >= x1) {
x -= x1;
firstAN = a1;
} else {
firstAN = 1;
}
x *= 100;
int256 product = ONE_20;
if (x >= x2) {
x -= x2;
product = (product * a2) / ONE_20;
}
if (x >= x3) {
x -= x3;
product = (product * a3) / ONE_20;
}
if (x >= x4) {
x -= x4;
product = (product * a4) / ONE_20;
}
if (x >= x5) {
x -= x5;
product = (product * a5) / ONE_20;
}
if (x >= x6) {
x -= x6;
product = (product * a6) / ONE_20;
}
if (x >= x7) {
x -= x7;
product = (product * a7) / ONE_20;
}
if (x >= x8) {
x -= x8;
product = (product * a8) / ONE_20;
}
if (x >= x9) {
x -= x9;
product = (product * a9) / ONE_20;
}
int256 seriesSum = ONE_20;
int256 term;
term = x;
seriesSum += term;
term = ((term * x) / ONE_20) / 2;
seriesSum += term;
term = ((term * x) / ONE_20) / 3;
seriesSum += term;
term = ((term * x) / ONE_20) / 4;
seriesSum += term;
term = ((term * x) / ONE_20) / 5;
seriesSum += term;
term = ((term * x) / ONE_20) / 6;
seriesSum += term;
term = ((term * x) / ONE_20) / 7;
seriesSum += term;
term = ((term * x) / ONE_20) / 8;
seriesSum += term;
term = ((term * x) / ONE_20) / 9;
seriesSum += term;
term = ((term * x) / ONE_20) / 10;
seriesSum += term;
term = ((term * x) / ONE_20) / 11;
seriesSum += term;
term = ((term * x) / ONE_20) / 12;
seriesSum += term;
return (((product * seriesSum) / ONE_20) * firstAN) / 100;
}
}
function ln(int256 a) internal pure returns (int256) {
unchecked {
require(a > 0, "out of bounds");
if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) {
return _ln_36(a) / ONE_18;
} else {
return _ln(a);
}
}
}
function pow(uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
if (y == 0) {
return uint256(ONE_18);
}
if (x == 0) {
return 0;
}
require(x < 2**255, "x out of bounds");
int256 x_int256 = int256(x);
require(y < MILD_EXPONENT_BOUND, "y out of bounds");
int256 y_int256 = int256(y);
int256 logx_times_y;
if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) {
int256 ln_36_x = _ln_36(x_int256);
logx_times_y = ((ln_36_x / ONE_18) *
y_int256 +
((ln_36_x % ONE_18) * y_int256) /
ONE_18);
} else {
logx_times_y = _ln(x_int256) * y_int256;
}
logx_times_y /= ONE_18;
require(
MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT,
"product out of bounds"
);
return uint256(exp(logx_times_y));
}
}
function _ln(int256 a) private pure returns (int256) {
unchecked {
if (a < ONE_18) {
return (-_ln((ONE_18 * ONE_18) / a));
}
int256 sum = 0;
if (a >= a0 * ONE_18) {
a /= a0;
sum += x0;
}
if (a >= a1 * ONE_18) {
a /= a1;
sum += x1;
}
sum *= 100;
a *= 100;
if (a >= a2) {
a = (a * ONE_20) / a2;
sum += x2;
}
if (a >= a3) {
a = (a * ONE_20) / a3;
sum += x3;
}
if (a >= a4) {
a = (a * ONE_20) / a4;
sum += x4;
}
if (a >= a5) {
a = (a * ONE_20) / a5;
sum += x5;
}
if (a >= a6) {
a = (a * ONE_20) / a6;
sum += x6;
}
if (a >= a7) {
a = (a * ONE_20) / a7;
sum += x7;
}
if (a >= a8) {
a = (a * ONE_20) / a8;
sum += x8;
}
if (a >= a9) {
a = (a * ONE_20) / a9;
sum += x9;
}
if (a >= a10) {
a = (a * ONE_20) / a10;
sum += x10;
}
if (a >= a11) {
a = (a * ONE_20) / a11;
sum += x11;
}
int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20);
int256 z_squared = (z * z) / ONE_20;
int256 num = z;
int256 seriesSum = num;
num = (num * z_squared) / ONE_20;
seriesSum += num / 3;
num = (num * z_squared) / ONE_20;
seriesSum += num / 5;
num = (num * z_squared) / ONE_20;
seriesSum += num / 7;
num = (num * z_squared) / ONE_20;
seriesSum += num / 9;
num = (num * z_squared) / ONE_20;
seriesSum += num / 11;
seriesSum *= 2;
return (sum + seriesSum) / 100;
}
}
function _ln_36(int256 x) private pure returns (int256) {
unchecked {
x *= ONE_18;
int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36);
int256 z_squared = (z * z) / ONE_36;
int256 num = z;
int256 seriesSum = num;
num = (num * z_squared) / ONE_36;
seriesSum += num / 3;
num = (num * z_squared) / ONE_36;
seriesSum += num / 5;
num = (num * z_squared) / ONE_36;
seriesSum += num / 7;
num = (num * z_squared) / ONE_36;
seriesSum += num / 9;
num = (num * z_squared) / ONE_36;
seriesSum += num / 11;
num = (num * z_squared) / ONE_36;
seriesSum += num / 13;
num = (num * z_squared) / ONE_36;
seriesSum += num / 15;
return seriesSum * 2;
}
}
}
文件 25 的 35:MarketApproxLib.sol
pragma solidity 0.8.17;
import "../../core/libraries/math/Math.sol";
import "../../core/Market/MarketMathCore.sol";
struct ApproxParams {
uint256 guessMin;
uint256 guessMax;
uint256 guessOffchain;
uint256 maxIteration;
uint256 eps;
}
library MarketApproxPtInLib {
using MarketMathCore for MarketState;
using PYIndexLib for PYIndex;
using Math for uint256;
using Math for int256;
using LogExpMath for int256;
function approxSwapPtForExactSy(
MarketState memory market,
PYIndex index,
uint256 minSyOut,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMax = Math.min(approx.guessMax, calcMaxPtIn(market, comp));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);
if (netSyOut >= minSyOut) {
if (Math.isAGreaterApproxB(netSyOut, minSyOut, approx.eps))
return (guess, netSyOut, netSyFee);
approx.guessMax = guess;
} else {
approx.guessMin = guess;
}
}
revert Errors.ApproxFail();
}
function approxSwapExactSyForYt(
MarketState memory market,
PYIndex index,
uint256 exactSyIn,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMin = Math.max(approx.guessMin, index.syToAsset(exactSyIn));
approx.guessMax = Math.min(approx.guessMax, calcMaxPtIn(market, comp));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);
uint256 netSyToTokenizePt = index.assetToSyUp(guess);
uint256 netSyToPull = netSyToTokenizePt - netSyOut;
if (netSyToPull <= exactSyIn) {
if (Math.isASmallerApproxB(netSyToPull, exactSyIn, approx.eps))
return (guess, netSyFee);
approx.guessMin = guess;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function approxSwapPtToAddLiquidity(
MarketState memory market,
PYIndex index,
uint256 totalPtIn,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMax = Math.min(approx.guessMax, calcMaxPtIn(market, comp));
approx.guessMax = Math.min(approx.guessMax, totalPtIn);
validateApprox(approx);
require(market.totalLp != 0, "no existing lp");
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(
uint256 syNumerator,
uint256 ptNumerator,
uint256 netSyOut,
uint256 netSyFee,
) = calcNumerators(market, index, totalPtIn, comp, guess);
if (Math.isAApproxB(syNumerator, ptNumerator, approx.eps))
return (guess, netSyOut, netSyFee);
if (syNumerator <= ptNumerator) {
approx.guessMin = guess + 1;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function calcNumerators(
MarketState memory market,
PYIndex index,
uint256 totalPtIn,
MarketPreCompute memory comp,
uint256 guess
)
internal
pure
returns (
uint256 syNumerator,
uint256 ptNumerator,
uint256 netSyOut,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(netSyOut, netSyFee, netSyToReserve) = calcSyOut(market, comp, index, guess);
uint256 newTotalPt = uint256(market.totalPt) + guess;
uint256 newTotalSy = (uint256(market.totalSy) - netSyOut - netSyToReserve);
syNumerator = netSyOut * newTotalPt;
ptNumerator = (totalPtIn - guess) * newTotalSy;
}
struct Args7 {
MarketState market;
PYIndex index;
uint256 exactPtIn;
uint256 blockTime;
}
function approxSwapExactPtForYt(
MarketState memory market,
PYIndex index,
uint256 exactPtIn,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMin = Math.max(approx.guessMin, exactPtIn);
approx.guessMax = Math.min(approx.guessMax, calcMaxPtIn(market, comp));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);
uint256 netAssetOut = index.syToAsset(netSyOut);
uint256 netPtToPull = guess - netAssetOut;
if (netPtToPull <= exactPtIn) {
if (Math.isASmallerApproxB(netPtToPull, exactPtIn, approx.eps))
return (netAssetOut, guess, netSyFee);
approx.guessMin = guess;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function calcSyOut(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
uint256 netPtIn
)
internal
pure
returns (
uint256 netSyOut,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyOut, int256 _netSyFee, int256 _netSyToReserve) = market.calcTrade(
comp,
index,
-int256(netPtIn)
);
netSyOut = uint256(_netSyOut);
netSyFee = uint256(_netSyFee);
netSyToReserve = uint256(_netSyToReserve);
}
function nextGuess(ApproxParams memory approx, uint256 iter) internal pure returns (uint256) {
if (iter == 0 && approx.guessOffchain != 0) return approx.guessOffchain;
if (approx.guessMin <= approx.guessMax) return (approx.guessMin + approx.guessMax) / 2;
revert Errors.ApproxFail();
}
function validateApprox(ApproxParams memory approx) internal pure {
if (approx.guessMin > approx.guessMax || approx.eps > Math.ONE)
revert Errors.ApproxParamsInvalid(approx.guessMin, approx.guessMax, approx.eps);
}
function calcMaxPtIn(MarketState memory market, MarketPreCompute memory comp)
internal
pure
returns (uint256)
{
uint256 low = 0;
uint256 hi = uint256(comp.totalAsset) - 1;
while (low != hi) {
uint256 mid = (low + hi + 1) / 2;
if (calcSlope(comp, market.totalPt, int256(mid)) < 0) hi = mid - 1;
else low = mid;
}
return low;
}
function calcSlope(
MarketPreCompute memory comp,
int256 totalPt,
int256 ptToMarket
) internal pure returns (int256) {
int256 diffAssetPtToMarket = comp.totalAsset - ptToMarket;
int256 sumPt = ptToMarket + totalPt;
require(diffAssetPtToMarket > 0 && sumPt > 0, "invalid ptToMarket");
int256 part1 = (ptToMarket * (totalPt + comp.totalAsset)).divDown(
sumPt * diffAssetPtToMarket
);
int256 part2 = sumPt.divDown(diffAssetPtToMarket).ln();
int256 part3 = Math.IONE.divDown(comp.rateScalar);
return comp.rateAnchor - (part1 - part2).mulDown(part3);
}
}
library MarketApproxPtOutLib {
using MarketMathCore for MarketState;
using PYIndexLib for PYIndex;
using Math for uint256;
using Math for int256;
using LogExpMath for int256;
function approxSwapExactSyForPt(
MarketState memory market,
PYIndex index,
uint256 exactSyIn,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMax = Math.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyIn, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);
if (netSyIn <= exactSyIn) {
if (Math.isASmallerApproxB(netSyIn, exactSyIn, approx.eps))
return (guess, netSyFee);
approx.guessMin = guess;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function approxSwapYtForExactSy(
MarketState memory market,
PYIndex index,
uint256 minSyOut,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMax = Math.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyOwed, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);
uint256 netAssetToRepay = index.syToAssetUp(netSyOwed);
uint256 netSyOut = index.assetToSy(guess - netAssetToRepay);
if (netSyOut >= minSyOut) {
if (Math.isAGreaterApproxB(netSyOut, minSyOut, approx.eps))
return (guess, netSyOut, netSyFee);
approx.guessMax = guess;
} else {
approx.guessMin = guess + 1;
}
}
revert Errors.ApproxFail();
}
struct Args6 {
MarketState market;
PYIndex index;
uint256 totalSyIn;
uint256 blockTime;
ApproxParams approx;
}
function approxSwapSyToAddLiquidity(
MarketState memory _market,
PYIndex _index,
uint256 _totalSyIn,
uint256 _blockTime,
ApproxParams memory _approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
Args6 memory a = Args6(_market, _index, _totalSyIn, _blockTime, _approx);
MarketPreCompute memory comp = a.market.getMarketPreCompute(a.index, a.blockTime);
if (a.approx.guessOffchain == 0) {
a.approx.guessMax = Math.min(a.approx.guessMax, calcMaxPtOut(comp, a.market.totalPt));
validateApprox(a.approx);
require(a.market.totalLp != 0, "no existing lp");
}
for (uint256 iter = 0; iter < a.approx.maxIteration; ++iter) {
uint256 guess = nextGuess(a.approx, iter);
(uint256 netSyIn, uint256 netSyFee, uint256 netSyToReserve) = calcSyIn(
a.market,
comp,
a.index,
guess
);
if (netSyIn > a.totalSyIn) {
a.approx.guessMax = guess - 1;
continue;
}
uint256 syNumerator;
uint256 ptNumerator;
{
uint256 newTotalPt = uint256(a.market.totalPt) - guess;
uint256 netTotalSy = uint256(a.market.totalSy) + netSyIn - netSyToReserve;
ptNumerator = guess * netTotalSy;
syNumerator = (a.totalSyIn - netSyIn) * newTotalPt;
}
if (Math.isAApproxB(ptNumerator, syNumerator, a.approx.eps))
return (guess, netSyIn, netSyFee);
if (ptNumerator <= syNumerator) {
a.approx.guessMin = guess + 1;
} else {
a.approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function approxSwapExactYtForPt(
MarketState memory market,
PYIndex index,
uint256 exactYtIn,
uint256 blockTime,
ApproxParams memory approx
)
internal
pure
returns (
uint256,
uint256,
uint256
)
{
MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);
if (approx.guessOffchain == 0) {
approx.guessMin = Math.max(approx.guessMin, exactYtIn);
approx.guessMax = Math.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));
validateApprox(approx);
}
for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {
uint256 guess = nextGuess(approx, iter);
(uint256 netSyOwed, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);
uint256 netYtToPull = index.syToAssetUp(netSyOwed);
if (netYtToPull <= exactYtIn) {
if (Math.isASmallerApproxB(netYtToPull, exactYtIn, approx.eps))
return (guess - netYtToPull, guess, netSyFee);
approx.guessMin = guess;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
function calcSyIn(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
uint256 netPtOut
)
internal
pure
returns (
uint256 netSyIn,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyIn, int256 _netSyFee, int256 _netSyToReserve) = market.calcTrade(
comp,
index,
int256(netPtOut)
);
netSyIn = uint256(-_netSyIn);
netSyFee = uint256(_netSyFee);
netSyToReserve = uint256(_netSyToReserve);
}
function calcMaxPtOut(MarketPreCompute memory comp, int256 totalPt)
internal
pure
returns (uint256)
{
int256 logitP = (comp.feeRate - comp.rateAnchor).mulDown(comp.rateScalar).exp();
int256 proportion = logitP.divDown(logitP + Math.IONE);
int256 numerator = proportion.mulDown(totalPt + comp.totalAsset);
int256 maxPtOut = totalPt - numerator;
return (uint256(maxPtOut) * 999) / 1000;
}
function nextGuess(ApproxParams memory approx, uint256 iter) internal pure returns (uint256) {
if (iter == 0 && approx.guessOffchain != 0) return approx.guessOffchain;
if (approx.guessMin <= approx.guessMax) return (approx.guessMin + approx.guessMax) / 2;
revert Errors.ApproxFail();
}
function validateApprox(ApproxParams memory approx) internal pure {
if (approx.guessMin > approx.guessMax || approx.eps > Math.ONE)
revert Errors.ApproxParamsInvalid(approx.guessMin, approx.guessMax, approx.eps);
}
}
文件 26 的 35:MarketMathCore.sol
pragma solidity 0.8.17;
import "../libraries/math/Math.sol";
import "../libraries/math/LogExpMath.sol";
import "../StandardizedYield/PYIndex.sol";
import "../libraries/MiniHelpers.sol";
import "../libraries/Errors.sol";
struct MarketState {
int256 totalPt;
int256 totalSy;
int256 totalLp;
address treasury;
int256 scalarRoot;
uint256 expiry;
uint256 lnFeeRateRoot;
uint256 reserveFeePercent;
uint256 lastLnImpliedRate;
}
struct MarketPreCompute {
int256 rateScalar;
int256 totalAsset;
int256 rateAnchor;
int256 feeRate;
}
library MarketMathCore {
using Math for uint256;
using Math for int256;
using LogExpMath for int256;
using PYIndexLib for PYIndex;
int256 internal constant MINIMUM_LIQUIDITY = 10**3;
int256 internal constant PERCENTAGE_DECIMALS = 100;
uint256 internal constant DAY = 86400;
uint256 internal constant IMPLIED_RATE_TIME = 365 * DAY;
int256 internal constant MAX_MARKET_PROPORTION = (1e18 * 96) / 100;
using Math for uint256;
using Math for int256;
function addLiquidity(
MarketState memory market,
uint256 syDesired,
uint256 ptDesired,
uint256 blockTime
)
internal
pure
returns (
uint256 lpToReserve,
uint256 lpToAccount,
uint256 syUsed,
uint256 ptUsed
)
{
(
int256 _lpToReserve,
int256 _lpToAccount,
int256 _syUsed,
int256 _ptUsed
) = addLiquidityCore(market, syDesired.Int(), ptDesired.Int(), blockTime);
lpToReserve = _lpToReserve.Uint();
lpToAccount = _lpToAccount.Uint();
syUsed = _syUsed.Uint();
ptUsed = _ptUsed.Uint();
}
function removeLiquidity(MarketState memory market, uint256 lpToRemove)
internal
pure
returns (uint256 netSyToAccount, uint256 netPtToAccount)
{
(int256 _syToAccount, int256 _ptToAccount) = removeLiquidityCore(market, lpToRemove.Int());
netSyToAccount = _syToAccount.Uint();
netPtToAccount = _ptToAccount.Uint();
}
function swapExactPtForSy(
MarketState memory market,
PYIndex index,
uint256 exactPtToMarket,
uint256 blockTime
)
internal
pure
returns (
uint256 netSyToAccount,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(
market,
index,
exactPtToMarket.neg(),
blockTime
);
netSyToAccount = _netSyToAccount.Uint();
netSyFee = _netSyFee.Uint();
netSyToReserve = _netSyToReserve.Uint();
}
function swapSyForExactPt(
MarketState memory market,
PYIndex index,
uint256 exactPtToAccount,
uint256 blockTime
)
internal
pure
returns (
uint256 netSyToMarket,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(
market,
index,
exactPtToAccount.Int(),
blockTime
);
netSyToMarket = _netSyToAccount.neg().Uint();
netSyFee = _netSyFee.Uint();
netSyToReserve = _netSyToReserve.Uint();
}
function addLiquidityCore(
MarketState memory market,
int256 syDesired,
int256 ptDesired,
uint256 blockTime
)
internal
pure
returns (
int256 lpToReserve,
int256 lpToAccount,
int256 syUsed,
int256 ptUsed
)
{
if (syDesired == 0 || ptDesired == 0) revert Errors.MarketZeroAmountsInput();
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
if (market.totalLp == 0) {
lpToAccount = Math.sqrt((syDesired * ptDesired).Uint()).Int() - MINIMUM_LIQUIDITY;
lpToReserve = MINIMUM_LIQUIDITY;
syUsed = syDesired;
ptUsed = ptDesired;
} else {
int256 netLpByPt = (ptDesired * market.totalLp) / market.totalPt;
int256 netLpBySy = (syDesired * market.totalLp) / market.totalSy;
if (netLpByPt < netLpBySy) {
lpToAccount = netLpByPt;
ptUsed = ptDesired;
syUsed = (market.totalSy * lpToAccount) / market.totalLp;
} else {
lpToAccount = netLpBySy;
syUsed = syDesired;
ptUsed = (market.totalPt * lpToAccount) / market.totalLp;
}
}
if (lpToAccount <= 0) revert Errors.MarketZeroAmountsOutput();
market.totalSy += syUsed;
market.totalPt += ptUsed;
market.totalLp += lpToAccount + lpToReserve;
}
function removeLiquidityCore(MarketState memory market, int256 lpToRemove)
internal
pure
returns (int256 netSyToAccount, int256 netPtToAccount)
{
if (lpToRemove == 0) revert Errors.MarketZeroAmountsInput();
netSyToAccount = (lpToRemove * market.totalSy) / market.totalLp;
netPtToAccount = (lpToRemove * market.totalPt) / market.totalLp;
if (netSyToAccount == 0 && netPtToAccount == 0) revert Errors.MarketZeroAmountsOutput();
market.totalLp = market.totalLp.subNoNeg(lpToRemove);
market.totalPt = market.totalPt.subNoNeg(netPtToAccount);
market.totalSy = market.totalSy.subNoNeg(netSyToAccount);
}
function executeTradeCore(
MarketState memory market,
PYIndex index,
int256 netPtToAccount,
uint256 blockTime
)
internal
pure
returns (
int256 netSyToAccount,
int256 netSyFee,
int256 netSyToReserve
)
{
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
if (market.totalPt <= netPtToAccount)
revert Errors.MarketInsufficientPtForTrade(market.totalPt, netPtToAccount);
MarketPreCompute memory comp = getMarketPreCompute(market, index, blockTime);
(netSyToAccount, netSyFee, netSyToReserve) = calcTrade(
market,
comp,
index,
netPtToAccount
);
_setNewMarketStateTrade(
market,
comp,
index,
netPtToAccount,
netSyToAccount,
netSyToReserve,
blockTime
);
}
function getMarketPreCompute(
MarketState memory market,
PYIndex index,
uint256 blockTime
) internal pure returns (MarketPreCompute memory res) {
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
uint256 timeToExpiry = market.expiry - blockTime;
res.rateScalar = _getRateScalar(market, timeToExpiry);
res.totalAsset = index.syToAsset(market.totalSy);
if (market.totalPt == 0 || res.totalAsset == 0)
revert Errors.MarketZeroTotalPtOrTotalAsset(market.totalPt, res.totalAsset);
res.rateAnchor = _getRateAnchor(
market.totalPt,
market.lastLnImpliedRate,
res.totalAsset,
res.rateScalar,
timeToExpiry
);
res.feeRate = _getExchangeRateFromImpliedRate(market.lnFeeRateRoot, timeToExpiry);
}
function calcTrade(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
int256 netPtToAccount
)
internal
pure
returns (
int256 netSyToAccount,
int256 netSyFee,
int256 netSyToReserve
)
{
int256 preFeeExchangeRate = _getExchangeRate(
market.totalPt,
comp.totalAsset,
comp.rateScalar,
comp.rateAnchor,
netPtToAccount
);
int256 preFeeAssetToAccount = netPtToAccount.divDown(preFeeExchangeRate).neg();
int256 fee = comp.feeRate;
if (netPtToAccount > 0) {
int256 postFeeExchangeRate = preFeeExchangeRate.divDown(fee);
if (postFeeExchangeRate < Math.IONE)
revert Errors.MarketExchangeRateBelowOne(postFeeExchangeRate);
fee = preFeeAssetToAccount.mulDown(Math.IONE - fee);
} else {
fee = ((preFeeAssetToAccount * (Math.IONE - fee)) / fee).neg();
}
int256 netAssetToReserve = (fee * market.reserveFeePercent.Int()) / PERCENTAGE_DECIMALS;
int256 netAssetToAccount = preFeeAssetToAccount - fee;
netSyToAccount = netAssetToAccount < 0
? index.assetToSyUp(netAssetToAccount)
: index.assetToSy(netAssetToAccount);
netSyFee = index.assetToSy(fee);
netSyToReserve = index.assetToSy(netAssetToReserve);
}
function _setNewMarketStateTrade(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
int256 netPtToAccount,
int256 netSyToAccount,
int256 netSyToReserve,
uint256 blockTime
) internal pure {
uint256 timeToExpiry = market.expiry - blockTime;
market.totalPt = market.totalPt.subNoNeg(netPtToAccount);
market.totalSy = market.totalSy.subNoNeg(netSyToAccount + netSyToReserve);
market.lastLnImpliedRate = _getLnImpliedRate(
market.totalPt,
index.syToAsset(market.totalSy),
comp.rateScalar,
comp.rateAnchor,
timeToExpiry
);
if (market.lastLnImpliedRate == 0) revert Errors.MarketZeroLnImpliedRate();
}
function _getRateAnchor(
int256 totalPt,
uint256 lastLnImpliedRate,
int256 totalAsset,
int256 rateScalar,
uint256 timeToExpiry
) internal pure returns (int256 rateAnchor) {
int256 newExchangeRate = _getExchangeRateFromImpliedRate(lastLnImpliedRate, timeToExpiry);
if (newExchangeRate < Math.IONE) revert Errors.MarketExchangeRateBelowOne(newExchangeRate);
{
int256 proportion = totalPt.divDown(totalPt + totalAsset);
int256 lnProportion = _logProportion(proportion);
rateAnchor = newExchangeRate - lnProportion.divDown(rateScalar);
}
}
function _getLnImpliedRate(
int256 totalPt,
int256 totalAsset,
int256 rateScalar,
int256 rateAnchor,
uint256 timeToExpiry
) internal pure returns (uint256 lnImpliedRate) {
int256 exchangeRate = _getExchangeRate(totalPt, totalAsset, rateScalar, rateAnchor, 0);
uint256 lnRate = exchangeRate.ln().Uint();
lnImpliedRate = (lnRate * IMPLIED_RATE_TIME) / timeToExpiry;
}
function _getExchangeRateFromImpliedRate(uint256 lnImpliedRate, uint256 timeToExpiry)
internal
pure
returns (int256 exchangeRate)
{
uint256 rt = (lnImpliedRate * timeToExpiry) / IMPLIED_RATE_TIME;
exchangeRate = LogExpMath.exp(rt.Int());
}
function _getExchangeRate(
int256 totalPt,
int256 totalAsset,
int256 rateScalar,
int256 rateAnchor,
int256 netPtToAccount
) internal pure returns (int256 exchangeRate) {
int256 numerator = totalPt.subNoNeg(netPtToAccount);
int256 proportion = (numerator.divDown(totalPt + totalAsset));
if (proportion > MAX_MARKET_PROPORTION)
revert Errors.MarketProportionTooHigh(proportion, MAX_MARKET_PROPORTION);
int256 lnProportion = _logProportion(proportion);
exchangeRate = lnProportion.divDown(rateScalar) + rateAnchor;
if (exchangeRate < Math.IONE) revert Errors.MarketExchangeRateBelowOne(exchangeRate);
}
function _logProportion(int256 proportion) internal pure returns (int256 res) {
if (proportion == Math.IONE) revert Errors.MarketProportionMustNotEqualOne();
int256 logitP = proportion.divDown(Math.IONE - proportion);
res = logitP.ln();
}
function _getRateScalar(MarketState memory market, uint256 timeToExpiry)
internal
pure
returns (int256 rateScalar)
{
rateScalar = (market.scalarRoot * IMPLIED_RATE_TIME.Int()) / timeToExpiry.Int();
if (rateScalar <= 0) revert Errors.MarketRateScalarBelowZero(rateScalar);
}
function setInitialLnImpliedRate(
MarketState memory market,
PYIndex index,
int256 initialAnchor,
uint256 blockTime
) internal pure {
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
int256 totalAsset = index.syToAsset(market.totalSy);
uint256 timeToExpiry = market.expiry - blockTime;
int256 rateScalar = _getRateScalar(market, timeToExpiry);
market.lastLnImpliedRate = _getLnImpliedRate(
market.totalPt,
totalAsset,
rateScalar,
initialAnchor,
timeToExpiry
);
}
}
文件 27 的 35:Math.sol
pragma solidity 0.8.17;
library Math {
uint256 internal constant ONE = 1e18;
int256 internal constant IONE = 1e18;
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;
}
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;
}
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 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);
}
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));
}
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 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 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);
}
}
文件 28 的 35:MiniHelpers.sol
pragma solidity 0.8.17;
library MiniHelpers {
function isCurrentlyExpired(uint256 expiry) internal view returns (bool) {
return (expiry <= block.timestamp);
}
function isExpired(uint256 expiry, uint256 blockTime) internal pure returns (bool) {
return (expiry <= blockTime);
}
function isTimeInThePast(uint256 timestamp) internal view returns (bool) {
return (timestamp <= block.timestamp);
}
}
文件 29 的 35:PYIndex.sol
pragma solidity 0.8.17;
import "../../interfaces/IPYieldToken.sol";
import "../../interfaces/IPPrincipalToken.sol";
import "./SYUtils.sol";
import "../libraries/math/Math.sol";
type PYIndex is uint256;
library PYIndexLib {
using Math for uint256;
using Math 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();
}
}
文件 30 的 35:PendleRouter.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/proxy/Proxy.sol";
import "../interfaces/IPAllAction.sol";
import "../interfaces/IDiamondLoupe.sol";
import "../interfaces/IDiamondCut.sol";
contract PendleRouter is Proxy, IDiamondLoupe {
address internal immutable ACTION_MINT_REDEEM;
address internal immutable ACTION_ADD_REMOVE_LIQ;
address internal immutable ACTION_SWAP_PT;
address internal immutable ACTION_SWAP_YT;
address internal immutable ACTION_MISC;
event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);
constructor(
address _ACTION_MINT_REDEEM,
address _ACTION_ADD_REMOVE_LIQ,
address _ACTION_SWAP_PT,
address _ACTION_SWAP_YT,
address _ACTION_MISC
) {
ACTION_MINT_REDEEM = _ACTION_MINT_REDEEM;
ACTION_ADD_REMOVE_LIQ = _ACTION_ADD_REMOVE_LIQ;
ACTION_SWAP_PT = _ACTION_SWAP_PT;
ACTION_SWAP_YT = _ACTION_SWAP_YT;
ACTION_MISC = _ACTION_MISC;
_emitEvents();
}
function _emitEvents() internal {
Facet[] memory facets_ = facets();
uint256 nFacets = facets_.length;
IDiamondCut.FacetCut[] memory cuts = new IDiamondCut.FacetCut[](nFacets);
for (uint256 i; i < nFacets; ) {
cuts[i].facetAddress = facets_[i].facetAddress;
cuts[i].action = IDiamondCut.FacetCutAction.Add;
cuts[i].functionSelectors = facets_[i].functionSelectors;
unchecked {
++i;
}
}
emit DiamondCut(cuts, address(0), "");
}
receive() external payable virtual override {}
function facets() public view returns (Facet[] memory facets_) {
address[] memory facetAddresses_ = facetAddresses();
uint256 numFacets = facetAddresses_.length;
facets_ = new Facet[](numFacets);
for (uint256 i; i < numFacets; ) {
facets_[i].facetAddress = facetAddresses_[i];
facets_[i].functionSelectors = facetFunctionSelectors(facetAddresses_[i]);
unchecked {
i++;
}
}
}
function facetFunctionSelectors(address facet) public view returns (bytes4[] memory res) {
if (facet == ACTION_ADD_REMOVE_LIQ) {
res = new bytes4[](12);
res[0] = 0x97ee279e;
res[1] = 0xcb591eb2;
res[2] = 0x3af1f329;
res[3] = 0x409c7a89;
res[4] = 0x015491d1;
res[5] = 0xb7d75b8b;
res[6] = 0xe6eaba01;
res[7] = 0x694ab559;
res[8] = 0x178d29d3;
res[9] = 0x690807ad;
res[10] = 0xdfbc814e;
res[11] = 0x844384aa;
return res;
}
if (facet == ACTION_MINT_REDEEM) {
res = new bytes4[](7);
res[0] = 0x1a8631b2;
res[1] = 0x46eb2db6;
res[2] = 0x443e6512;
res[3] = 0xf7e375e8;
res[4] = 0x339748cb;
res[5] = 0x527df199;
res[6] = 0x85b29936;
return res;
}
if (facet == ACTION_SWAP_PT) {
res = new bytes4[](6);
res[0] = 0x2032aecd;
res[1] = 0xb85f50ba;
res[2] = 0x83c71b69;
res[3] = 0xa5f9931b;
res[4] = 0xdd371acd;
res[5] = 0x6b8bdf32;
return res;
}
if (facet == ACTION_SWAP_YT) {
res = new bytes4[](9);
res[0] = 0xfa483e72;
res[1] = 0xc861a898;
res[2] = 0x448b9b95;
res[3] = 0xfdd71f43;
res[4] = 0xc4a9c7de;
res[5] = 0x357d6540;
res[6] = 0xd6308fa4;
res[7] = 0xbf1bd434;
res[8] = 0xe15cc098;
return res;
}
if (facet == ACTION_MISC) {
res = new bytes4[](2);
res[0] = 0xacdb32df;
res[1] = 0xd617b03b;
return res;
}
if (facet == address(this)) {
res = new bytes4[](4);
res[0] = 0xcdffacc6;
res[1] = 0x52ef6b2c;
res[2] = 0xadfca15e;
res[3] = 0x7a0ed627;
return res;
}
revert Errors.RouterInvalidFacet(facet);
}
function facetAddress(bytes4 sig) public view returns (address) {
if (sig < 0x97ee279e) {
if (sig < 0x46eb2db6) {
if (sig < 0x357d6540) {
if (sig < 0x1a8631b2) {
if (sig == 0x015491d1) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0x178d29d3) return ACTION_ADD_REMOVE_LIQ;
} else {
if (sig == 0x1a8631b2) return ACTION_MINT_REDEEM;
if (sig == 0x2032aecd) return ACTION_SWAP_PT;
if (sig == 0x339748cb) return ACTION_MINT_REDEEM;
}
} else {
if (sig < 0x409c7a89) {
if (sig == 0x357d6540) return ACTION_SWAP_YT;
if (sig == 0x3af1f329) return ACTION_ADD_REMOVE_LIQ;
} else {
if (sig == 0x409c7a89) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0x443e6512) return ACTION_MINT_REDEEM;
if (sig == 0x448b9b95) return ACTION_SWAP_YT;
}
}
} else {
if (sig < 0x6b8bdf32) {
if (sig < 0x52ef6b2c) {
if (sig == 0x46eb2db6) return ACTION_MINT_REDEEM;
if (sig == 0x527df199) return ACTION_MINT_REDEEM;
} else {
if (sig == 0x690807ad) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0x694ab559) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0x52ef6b2c) return address(this);
}
} else {
if (sig < 0x83c71b69) {
if (sig == 0x6b8bdf32) return ACTION_SWAP_PT;
if (sig == 0x7a0ed627) return address(this);
} else {
if (sig == 0x85b29936) return ACTION_MINT_REDEEM;
if (sig == 0x844384aa) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0x83c71b69) return ACTION_SWAP_PT;
}
}
}
} else {
if (sig < 0xcdffacc6) {
if (sig < 0xb85f50ba) {
if (sig < 0xacdb32df) {
if (sig == 0xa5f9931b) return ACTION_SWAP_PT;
if (sig == 0x97ee279e) return ACTION_ADD_REMOVE_LIQ;
} else {
if (sig == 0xb7d75b8b) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0xacdb32df) return ACTION_MISC;
if (sig == 0xadfca15e) return address(this);
}
} else {
if (sig < 0xc4a9c7de) {
if (sig == 0xb85f50ba) return ACTION_SWAP_PT;
if (sig == 0xbf1bd434) return ACTION_SWAP_YT;
} else {
if (sig == 0xc4a9c7de) return ACTION_SWAP_YT;
if (sig == 0xcb591eb2) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0xc861a898) return ACTION_SWAP_YT;
}
}
} else {
if (sig < 0xe15cc098) {
if (sig < 0xd6308fa4) {
if (sig == 0xd617b03b) return ACTION_MISC;
if (sig == 0xcdffacc6) return address(this);
} else {
if (sig == 0xd6308fa4) return ACTION_SWAP_YT;
if (sig == 0xdfbc814e) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0xdd371acd) return ACTION_SWAP_PT;
}
} else {
if (sig < 0xf7e375e8) {
if (sig == 0xe6eaba01) return ACTION_ADD_REMOVE_LIQ;
if (sig == 0xe15cc098) return ACTION_SWAP_YT;
} else {
if (sig == 0xfa483e72) return ACTION_SWAP_YT;
if (sig == 0xf7e375e8) return ACTION_MINT_REDEEM;
if (sig == 0xfdd71f43) return ACTION_SWAP_YT;
}
}
}
}
revert Errors.RouterInvalidAction(sig);
}
function facetAddresses() public view returns (address[] memory) {
address[] memory res = new address[](6);
res[0] = ACTION_ADD_REMOVE_LIQ;
res[1] = ACTION_MINT_REDEEM;
res[2] = ACTION_SWAP_PT;
res[3] = ACTION_SWAP_YT;
res[4] = ACTION_MISC;
res[5] = address(this);
return res;
}
function _implementation() internal view override returns (address) {
return facetAddress(msg.sig);
}
}
文件 31 的 35:Proxy.sol
pragma solidity ^0.8.0;
abstract contract Proxy {
function _delegate(address implementation) internal virtual {
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
function _implementation() internal view virtual returns (address);
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
fallback() external payable virtual {
_fallback();
}
receive() external payable virtual {
_fallback();
}
function _beforeFallback() internal virtual {}
}
文件 32 的 35:SYUtils.sol
pragma solidity 0.8.17;
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;
}
}
文件 33 的 35:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
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));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
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");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
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");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 34 的 35:TokenHelper.sol
pragma solidity 0.8.17;
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;
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));
}
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);
}
}
文件 35 的 35:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/pendle/contracts/router/PendleRouter.sol": "PendleRouter"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"_ACTION_MINT_REDEEM","type":"address"},{"internalType":"address","name":"_ACTION_ADD_REMOVE_LIQ","type":"address"},{"internalType":"address","name":"_ACTION_SWAP_PT","type":"address"},{"internalType":"address","name":"_ACTION_SWAP_YT","type":"address"},{"internalType":"address","name":"_ACTION_MISC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"RouterInvalidAction","type":"error"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"RouterInvalidFacet","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCut.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondCut.FacetCut[]","name":"_diamondCut","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"_init","type":"address"},{"indexed":false,"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"DiamondCut","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes4","name":"sig","type":"bytes4"}],"name":"facetAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facetAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"facetFunctionSelectors","outputs":[{"internalType":"bytes4[]","name":"res","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facets","outputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"internalType":"struct IDiamondLoupe.Facet[]","name":"facets_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]