编译器
0.8.19+commit.7dd6d404
文件 1 的 52: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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
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 {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 52:BaseAction.sol
pragma solidity ^0.8.19;
abstract contract BaseAction {
error Action__revertBytes_emptyRevertBytes();
function _delegateCall(address to, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returnData) = to.delegatecall(data);
if (!success) _revertBytes(returnData);
return returnData;
}
function _revertBytes(bytes memory errMsg) internal pure {
if (errMsg.length != 0) {
assembly {
revert(add(32, errMsg), mload(errMsg))
}
}
revert Action__revertBytes_emptyRevertBytes();
}
}
文件 3 的 52:Errors.sol
pragma solidity ^0.8.0;
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 MarketFactoryOverriddenFeeTooHigh(uint80 overriddenFee, uint256 marketLnFeeRateRoot);
error MarketFactoryReserveFeePercentTooHigh(uint8 reserveFeePercent, uint8 maxReserveFeePercent);
error MarketFactoryZeroTreasury();
error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor);
error MFNotPendleMarket(address addr);
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);
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 SYStargateRedeemCapExceeded(uint256 amountLpDesired, uint256 amountLpRedeemable);
error SYBalancerReentrancy();
error NotFromTrustedRemote(uint16 srcChainId, bytes path);
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 InvalidMerkleProof();
error OnlyLayerZeroEndpoint();
error OnlyYT();
error OnlyYCFactory();
error OnlyWhitelisted();
error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual);
error UnsupportedSelector(uint256 aggregatorType, bytes4 selector);
}
文件 4 的 52:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 5 的 52:IAsset.sol
pragma solidity >=0.7.0 <0.9.0;
interface IAsset {
}
文件 6 的 52:IBalancerVault.sol
pragma solidity ^0.8.19;
import {IAsset} from "src/vendor/IAsset.sol";
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
address assetIn;
address assetOut;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct JoinPoolRequest {
address[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
enum JoinKind {
INIT,
EXACT_TOKENS_IN_FOR_BPT_OUT,
TOKEN_IN_FOR_EXACT_BPT_OUT,
ALL_TOKENS_IN_FOR_EXACT_BPT_OUT
}
enum ExitKind {
EXACT_BPT_IN_FOR_ONE_TOKEN_OUT,
EXACT_BPT_IN_FOR_TOKENS_OUT,
BPT_IN_FOR_EXACT_TOKENS_OUT,
MANAGEMENT_FEE_TOKENS_OUT
}
struct ExitPoolRequest {
address[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
interface IVault {
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
address[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external payable returns (int256[] memory);
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
function getPoolTokens(
bytes32 poolId
) external view returns (address[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock);
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
address[] memory assets,
FundManagement memory funds
) external view returns (int256[] memory assetDeltas);
function manageUserBalance(UserBalanceOp[] memory ops) external payable;
struct UserBalanceOp {
UserBalanceOpKind kind;
IAsset asset;
uint256 amount;
address sender;
address payable recipient;
}
enum UserBalanceOpKind {
DEPOSIT_INTERNAL,
WITHDRAW_INTERNAL,
TRANSFER_INTERNAL,
TRANSFER_EXTERNAL
}
enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
}
文件 7 的 52:ICDPVault.sol
pragma solidity ^0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {IOracle} from "./IOracle.sol";
import {IPause} from "./IPause.sol";
import {IPermission} from "./IPermission.sol";
import {IInterestRateModel} from "./IInterestRateModel.sol";
import {IPoolV3} from "./IPoolV3.sol";
struct CDPVaultConstants {
IPoolV3 pool;
IOracle oracle;
IERC20 token;
uint256 tokenScale;
}
struct CDPVaultConfig {
uint128 debtFloor;
uint64 liquidationRatio;
uint64 liquidationPenalty;
uint64 liquidationDiscount;
address roleAdmin;
address vaultAdmin;
address pauseAdmin;
}
interface ICDPVaultBase is IAccessControl, IPause, IPermission {
function pool() external view returns (IPoolV3);
function oracle() external view returns (IOracle);
function token() external view returns (IERC20);
function tokenScale() external view returns (uint256);
function poolUnderlying() external view returns (IERC20);
function poolUnderlyingScale() external view returns (uint256);
function vaultConfig() external view returns (uint128 debtFloor, uint64 liquidationRatio);
function totalDebt() external view returns (uint256);
function positions(
address owner
)
external
view
returns (
uint256 collateral,
uint256 debt,
uint256 lastDebtUpdate,
uint256 cumulativeIndexLastUpdate,
uint192 cumulativeQuotaIndexLU,
uint128 cumulativeQuotaInterest
);
function deposit(address to, uint256 amount) external returns (uint256);
function withdraw(address to, uint256 amount) external returns (uint256);
function spotPrice() external returns (uint256);
function modifyCollateralAndDebt(
address owner,
address collateralizer,
address creditor,
int256 deltaCollateral,
int256 deltaNormalDebt
) external;
}
interface ICDPVault is ICDPVaultBase {
function paused() external view returns (bool);
function virtualDebt(address position) external view returns (uint256);
function getAccruedInterest(address position) external view returns (uint256 accruedInterest);
}
文件 8 的 52:IEIP712.sol
pragma solidity ^0.8.17;
interface IEIP712 {
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 9 的 52: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);
}
文件 10 的 52: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);
}
文件 11 的 52: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);
}
文件 12 的 52:IERC4626.sol
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
import "../token/ERC20/extensions/IERC20Metadata.sol";
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
function asset() external view returns (address assetTokenAddress);
function totalAssets() external view returns (uint256 totalManagedAssets);
function convertToShares(uint256 assets) external view returns (uint256 shares);
function convertToAssets(uint256 shares) external view returns (uint256 assets);
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
function previewDeposit(uint256 assets) external view returns (uint256 shares);
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
function maxMint(address receiver) external view returns (uint256 maxShares);
function previewMint(uint256 shares) external view returns (uint256 assets);
function mint(uint256 shares, address receiver) external returns (uint256 assets);
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
function maxRedeem(address owner) external view returns (uint256 maxShares);
function previewRedeem(uint256 shares) external view returns (uint256 assets);
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
文件 13 的 52:IFlashlender.sol
pragma solidity ^0.8.19;
import {IPoolV3} from "./IPoolV3.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IERC3156FlashBorrower {
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}
interface IERC3156FlashLender {
function maxFlashLoan(address token) external view returns (uint256);
function flashFee(address token, uint256 amount) external view returns (uint256);
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}
interface ICreditFlashBorrower {
function onCreditFlashLoan(
address initiator,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}
interface ICreditFlashLender {
function creditFlashLoan(
ICreditFlashBorrower receiver,
uint256 amount,
bytes calldata data
) external returns (bool);
}
interface IFlashlender is IERC3156FlashLender, ICreditFlashLender {
function pool() external view returns (IPoolV3);
function underlyingToken() external view returns (IERC20);
function CALLBACK_SUCCESS() external view returns (bytes32);
function CALLBACK_SUCCESS_CREDIT() external view returns (bytes32);
function maxFlashLoan(address token) external view override returns (uint256);
function flashFee(address token, uint256 amount) external view override returns (uint256);
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
function creditFlashLoan(
ICreditFlashBorrower receiver,
uint256 amount,
bytes calldata data
) external returns (bool);
}
abstract contract FlashLoanReceiverBase is ICreditFlashBorrower, IERC3156FlashBorrower {
IFlashlender public immutable flashlender;
bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
bytes32 public constant CALLBACK_SUCCESS_CREDIT = keccak256("CreditFlashBorrower.onCreditFlashLoan");
constructor(address flashlender_) {
flashlender = IFlashlender(flashlender_);
}
function approvePayback(uint256 amount) internal {
flashlender.underlyingToken().approve(address(flashlender), amount);
}
}
文件 14 的 52:IInterestRateModel.sol
pragma solidity ^0.8.19;
interface IInterestRateModel {
function getIRS() external view returns (int64, uint64, uint64, uint64, uint256);
function getAccruedInterest() external view returns (uint256 accruedInterest);
function virtualRateAccumulator() external view returns (uint64 rateAccumulator);
}
文件 15 的 52:IOracle.sol
pragma solidity ^0.8.19;
bytes32 constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
interface IOracle {
function spot(address token) external view returns (uint256);
function getStatus(address token) external view returns (bool);
}
文件 16 的 52:IPActionAddRemoveLiqV3.sol
pragma solidity ^0.8.0;
import "../router/base/MarketApproxLib.sol";
import "./IPAllActionTypeV3.sol";
interface IPActionAddRemoveLiqV3 {
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,
uint256 netSyInterm
);
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,
uint256 netSyInterm
);
event AddLiquiditySingleSyKeepYt(
address indexed caller,
address indexed market,
address indexed receiver,
uint256 netSyIn,
uint256 netSyMintPy,
uint256 netLpOut,
uint256 netYtOut
);
event AddLiquiditySingleTokenKeepYt(
address indexed caller,
address indexed market,
address indexed token,
address receiver,
uint256 netTokenIn,
uint256 netLpOut,
uint256 netYtOut,
uint256 netSyMintPy,
uint256 netSyInterm
);
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,
uint256 netSyInterm
);
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,
uint256 netSyInterm
);
function addLiquidityDualTokenAndPt(
address receiver,
address market,
TokenInput calldata input,
uint256 netPtDesired,
uint256 minLpOut
) external payable returns (uint256 netLpOut, uint256 netPtUsed, uint256 netSyInterm);
function addLiquidityDualSyAndPt(
address receiver,
address market,
uint256 netSyDesired,
uint256 netPtDesired,
uint256 minLpOut
) external returns (uint256 netLpOut, uint256 netSyUsed, uint256 netPtUsed);
function addLiquiditySinglePt(
address receiver,
address market,
uint256 netPtIn,
uint256 minLpOut,
ApproxParams calldata guessPtSwapToSy,
LimitOrderData calldata limit
) external returns (uint256 netLpOut, uint256 netSyFee);
function addLiquiditySingleToken(
address receiver,
address market,
uint256 minLpOut,
ApproxParams calldata guessPtReceivedFromSy,
TokenInput calldata input,
LimitOrderData calldata limit
) external payable returns (uint256 netLpOut, uint256 netSyFee, uint256 netSyInterm);
function addLiquiditySingleSy(
address receiver,
address market,
uint256 netSyIn,
uint256 minLpOut,
ApproxParams calldata guessPtReceivedFromSy,
LimitOrderData calldata limit
) external returns (uint256 netLpOut, uint256 netSyFee);
function addLiquiditySingleTokenKeepYt(
address receiver,
address market,
uint256 minLpOut,
uint256 minYtOut,
TokenInput calldata input
) external payable returns (uint256 netLpOut, uint256 netYtOut, uint256 netSyMintPy, uint256 netSyInterm);
function addLiquiditySingleSyKeepYt(
address receiver,
address market,
uint256 netSyIn,
uint256 minLpOut,
uint256 minYtOut
) external returns (uint256 netLpOut, uint256 netYtOut, uint256 netSyMintPy);
function removeLiquidityDualTokenAndPt(
address receiver,
address market,
uint256 netLpToRemove,
TokenOutput calldata output,
uint256 minPtOut
) external returns (uint256 netTokenOut, uint256 netPtOut, uint256 netSyInterm);
function removeLiquidityDualSyAndPt(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minSyOut,
uint256 minPtOut
) external returns (uint256 netSyOut, uint256 netPtOut);
function removeLiquiditySinglePt(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minPtOut,
ApproxParams calldata guessPtReceivedFromSy,
LimitOrderData calldata limit
) external returns (uint256 netPtOut, uint256 netSyFee);
function removeLiquiditySingleToken(
address receiver,
address market,
uint256 netLpToRemove,
TokenOutput calldata output,
LimitOrderData calldata limit
) external returns (uint256 netTokenOut, uint256 netSyFee, uint256 netSyInterm);
function removeLiquiditySingleSy(
address receiver,
address market,
uint256 netLpToRemove,
uint256 minSyOut,
LimitOrderData calldata limit
) external returns (uint256 netSyOut, uint256 netSyFee);
}
文件 17 的 52:IPAllActionTypeV3.sol
pragma solidity ^0.8.0;
import "../router/swap-aggregator/IPSwapAggregator.sol";
import "./IPLimitRouter.sol";
struct TokenInput {
address tokenIn;
uint256 netTokenIn;
address tokenMintSy;
address pendleSwap;
SwapData swapData;
}
struct TokenOutput {
address tokenOut;
uint256 minTokenOut;
address tokenRedeemSy;
address pendleSwap;
SwapData swapData;
}
struct LimitOrderData {
address limitRouter;
uint256 epsSkipMarket;
FillOrderParams[] normalFills;
FillOrderParams[] flashFills;
bytes optData;
}
文件 18 的 52:IPGauge.sol
pragma solidity ^0.8.0;
interface IPGauge {
function totalActiveSupply() external view returns (uint256);
function activeBalance(address user) external view returns (uint256);
event RedeemRewards(address indexed user, uint256[] rewardsOut);
}
文件 19 的 52:IPInterestManagerYT.sol
pragma solidity ^0.8.0;
interface IPInterestManagerYT {
event CollectInterestFee(uint256 amountInterestFee);
function userInterest(address user) external view returns (uint128 lastPYIndex, uint128 accruedInterest);
}
文件 20 的 52:IPLimitRouter.sol
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
}
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
);
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;
event OrderFilled(
bytes32 indexed orderHash,
OrderType indexed orderType,
address indexed YT,
address token,
uint256 netInputFromMaker,
uint256 netOutputToMaker,
uint256 feeAmount,
uint256 notionalVolume
);
}
文件 21 的 52:IPMarket.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./IPPrincipalToken.sol";
import "./IPYieldToken.sol";
import "./IStandardizedYield.sol";
import "./IPGauge.sol";
import "../core/Market/MarketMathCore.sol";
interface IPMarket is IERC20Metadata, IPGauge {
event Mint(address indexed receiver, uint256 netLpMinted, uint256 netSyUsed, uint256 netPtUsed);
event Burn(
address indexed receiverSy,
address indexed receiverPt,
uint256 netLpBurned,
uint256 netSyOut,
uint256 netPtOut
);
event Swap(
address indexed caller,
address indexed receiver,
int256 netPtOut,
int256 netSyOut,
uint256 netSyFee,
uint256 netSyToReserve
);
event UpdateImpliedRate(uint256 indexed timestamp, uint256 lnLastImpliedRate);
event IncreaseObservationCardinalityNext(
uint16 observationCardinalityNextOld,
uint16 observationCardinalityNextNew
);
function mint(
address receiver,
uint256 netSyDesired,
uint256 netPtDesired
) external returns (uint256 netLpOut, uint256 netSyUsed, uint256 netPtUsed);
function burn(
address receiverSy,
address receiverPt,
uint256 netLpToBurn
) external returns (uint256 netSyOut, uint256 netPtOut);
function swapExactPtForSy(
address receiver,
uint256 exactPtIn,
bytes calldata data
) external returns (uint256 netSyOut, uint256 netSyFee);
function swapSyForExactPt(
address receiver,
uint256 exactPtOut,
bytes calldata data
) external returns (uint256 netSyIn, uint256 netSyFee);
function redeemRewards(address user) external returns (uint256[] memory);
function readState(address router) external view returns (MarketState memory market);
function observe(uint32[] memory secondsAgos) external view returns (uint216[] memory lnImpliedRateCumulative);
function increaseObservationsCardinalityNext(uint16 cardinalityNext) external;
function readTokens() external view returns (IStandardizedYield _SY, IPPrincipalToken _PT, IPYieldToken _YT);
function getRewardTokens() external view returns (address[] memory);
function isExpired() external view returns (bool);
function expiry() external view returns (uint256);
function observations(
uint256 index
) external view returns (uint32 blockTimestamp, uint216 lnImpliedRateCumulative, bool initialized);
function _storage()
external
view
returns (
int128 totalPt,
int128 totalSy,
uint96 lastLnImpliedRate,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext
);
}
文件 22 的 52:IPPrincipalToken.sol
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);
}
文件 23 的 52:IPSwapAggregator.sol
pragma solidity ^0.8.0;
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;
}
文件 24 的 52:IPYieldToken.sol
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);
}
文件 25 的 52:IPause.sol
pragma solidity ^0.8.19;
interface IPause {
function pausedAt() external view returns (uint256);
function pause() external;
function unpause() external;
}
文件 26 的 52:IPermission.sol
pragma solidity ^0.8.19;
interface IPermission {
function hasPermission(address owner, address caller) external view returns (bool);
function modifyPermission(address caller, bool allowed) external;
function modifyPermission(address owner, address caller, bool allowed) external;
}
文件 27 的 52:IPoolV3.sol
pragma solidity ^0.8.17;
pragma abicoder v1;
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol";
interface IPoolV3Events {
event Refer(address indexed onBehalfOf, uint256 indexed referralCode, uint256 amount);
event Borrow(address indexed creditManager, address indexed creditAccount, uint256 amount);
event Repay(address indexed creditManager, uint256 borrowedAmount, uint256 profit, uint256 loss);
event IncurUncoveredLoss(address indexed creditManager, uint256 loss);
event SetInterestRateModel(address indexed newInterestRateModel);
event SetPoolQuotaKeeper(address indexed newPoolQuotaKeeper);
event SetTotalDebtLimit(uint256 limit);
event AddCreditManager(address indexed creditManager);
event SetCreditManagerDebtLimit(address indexed creditManager, uint256 newLimit);
event SetWithdrawFee(uint256 fee);
}
interface IPoolV3 is IVersion, IPoolV3Events, IERC4626, IERC20Permit {
function addressProvider() external view returns (address);
function underlyingToken() external view returns (address);
function treasury() external view returns (address);
function withdrawFee() external view returns (uint16);
function creditManagers() external view returns (address[] memory);
function availableLiquidity() external view returns (uint256);
function expectedLiquidity() external view returns (uint256);
function expectedLiquidityLU() external view returns (uint256);
function depositWithReferral(
uint256 assets,
address receiver,
uint256 referralCode
) external returns (uint256 shares);
function mintWithReferral(uint256 shares, address receiver, uint256 referralCode) external returns (uint256 assets);
function totalBorrowed() external view returns (uint256);
function totalDebtLimit() external view returns (uint256);
function creditManagerBorrowed(address creditManager) external view returns (uint256);
function creditManagerDebtLimit(address creditManager) external view returns (uint256);
function creditManagerBorrowable(address creditManager) external view returns (uint256 borrowable);
function lendCreditAccount(uint256 borrowedAmount, address creditAccount) external;
function repayCreditAccount(uint256 repaidAmount, uint256 profit, uint256 loss) external;
function interestRateModel() external view returns (address);
function baseInterestRate() external view returns (uint256);
function supplyRate() external view returns (uint256);
function baseInterestIndex() external view returns (uint256);
function baseInterestIndexLU() external view returns (uint256);
function lastBaseInterestUpdate() external view returns (uint40);
function poolQuotaKeeper() external view returns (address);
function quotaRevenue() external view returns (uint256);
function lastQuotaRevenueUpdate() external view returns (uint40);
function updateQuotaRevenue(int256 quotaRevenueDelta) external;
function setQuotaRevenue(uint256 newQuotaRevenue) external;
function setInterestRateModel(address newInterestRateModel) external;
function setPoolQuotaKeeper(address newPoolQuotaKeeper) external;
function setTreasury(address treasury_) external;
function setTotalDebtLimit(uint256 newLimit) external;
function setCreditManagerDebtLimit(address creditManager, uint256 newLimit) external;
function setWithdrawFee(uint256 newWithdrawFee) external;
function mintProfit(uint256 amount) external;
}
文件 28 的 52:IRewardManager.sol
pragma solidity ^0.8.0;
interface IRewardManager {
function userReward(address token, address user) external view returns (uint128 index, uint128 accrued);
}
文件 29 的 52:ISignatureTransfer.sol
pragma solidity ^0.8.17;
import {IEIP712} from "./IEIP712.sol";
interface ISignatureTransfer is IEIP712 {
error InvalidAmount(uint256 maxAmount);
error LengthMismatch();
event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);
struct TokenPermissions {
address token;
uint256 amount;
}
struct PermitTransferFrom {
TokenPermissions permitted;
uint256 nonce;
uint256 deadline;
}
struct SignatureTransferDetails {
address to;
uint256 requestedAmount;
}
struct PermitBatchTransferFrom {
TokenPermissions[] permitted;
uint256 nonce;
uint256 deadline;
}
function nonceBitmap(address, uint256) external view returns (uint256);
function permitTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes calldata signature
) external;
function permitWitnessTransferFrom(
PermitTransferFrom memory permit,
SignatureTransferDetails calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
function permitTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes calldata signature
) external;
function permitWitnessTransferFrom(
PermitBatchTransferFrom memory permit,
SignatureTransferDetails[] calldata transferDetails,
address owner,
bytes32 witness,
string calldata witnessTypeString,
bytes calldata signature
) external;
function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}
文件 30 的 52:ISpectraRouter.sol
pragma solidity ^0.8.19;
interface ISpectraRouter {
function execute(bytes calldata _commands, bytes[] calldata _inputs, uint256 _deadline) external payable;
}
文件 31 的 52:IStableSwapTranchess.sol
pragma solidity ^0.8.4;
interface IStableSwap {
function baseTranche() external view returns (uint256);
function baseAddress() external view returns (address);
function quoteAddress() external view returns (address);
function allBalances() external view returns (uint256, uint256);
function getOraclePrice() external view returns (uint256);
function getCurrentD() external view returns (uint256);
function getCurrentPriceOverOracle() external view returns (uint256);
function getCurrentPrice() external view returns (uint256);
function getPriceOverOracleIntegral() external view returns (uint256);
function addLiquidity(uint256 version, address recipient) external returns (uint256);
function removeLiquidity(
uint256 version,
uint256 lpIn,
uint256 minBaseOut,
uint256 minQuoteOut
) external returns (uint256 baseOut, uint256 quoteOut);
function removeLiquidityUnwrap(
uint256 version,
uint256 lpIn,
uint256 minBaseOut,
uint256 minQuoteOut
) external returns (uint256 baseOut, uint256 quoteOut);
function removeBaseLiquidity(uint256 version, uint256 lpIn, uint256 minBaseOut) external returns (uint256 baseOut);
function removeQuoteLiquidity(
uint256 version,
uint256 lpIn,
uint256 minQuoteOut
) external returns (uint256 quoteOut);
function removeQuoteLiquidityUnwrap(
uint256 version,
uint256 lpIn,
uint256 minQuoteOut
) external returns (uint256 quoteOut);
}
文件 32 的 52:IStandardizedYield.sol
pragma solidity ^0.8.0;
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);
}
文件 33 的 52:ISwapRouterTranchess.sol
pragma solidity ^0.8.4;
interface ISwapRouter {
function addLiquidity(
address baseToken,
address quoteToken,
uint256 baseDelta,
uint256 quoteDelta,
uint256 minMintAmount,
uint256 version,
uint256 deadline
) external payable;
}
文件 34 的 52:IUniswapV3Router.sol
pragma solidity ^0.8.19;
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
error UniswapV3Router_toAddress_overflow();
error UniswapV3Router_toAddress_outOfBounds();
error UniswapV3Router_decodeLastToken_invalidPath();
function toAddress(bytes memory _bytes, uint256 _start) pure returns (address) {
if (_start + 20 < _start) revert UniswapV3Router_toAddress_overflow();
if (_bytes.length < _start + 20) revert UniswapV3Router_toAddress_outOfBounds();
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function decodeLastToken(bytes memory path) pure returns (address token) {
if (path.length < 20) revert UniswapV3Router_decodeLastToken_invalidPath();
token = toAddress(path, path.length - 20);
}
interface IUniswapV3Router {
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 35 的 52:IVaultRegistry.sol
pragma solidity ^0.8.19;
import {ICDPVault} from "./ICDPVault.sol";
interface IVaultRegistry {
function addVault(ICDPVault vault) external;
function removeVault(ICDPVault vault) external;
function getVaults() external view returns (ICDPVault[] memory);
function getUserTotalDebt(address user) external view returns (uint256 totalNormalDebt);
function isVaultRegistered(address vault) external view returns (bool);
}
文件 36 的 52:IVersion.sol
pragma solidity ^0.8.10;
interface IVersion {
function version() external view returns (uint256);
}
文件 37 的 52:IWETH.sol
pragma solidity ^0.8.19;
interface IWETH {
function balanceOf(address) external returns (uint256);
function deposit() external payable;
function withdraw(uint256) external;
function approve(address guy, uint256 wad) external returns (bool);
function transferFrom(address src, address dst, uint256 wad) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external returns (uint256);
}
文件 38 的 52:LogExpMath.sol
pragma solidity ^0.8.0;
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;
}
}
}
文件 39 的 52:MarketApproxLib.sol
pragma solidity ^0.8.0;
import "../../core/libraries/math/PMath.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 PMath for uint256;
using PMath 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 = PMath.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 (PMath.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 = PMath.max(approx.guessMin, index.syToAsset(exactSyIn));
approx.guessMax = PMath.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 (PMath.isASmallerApproxB(netSyToPull, exactSyIn, approx.eps)) {
return (guess, netSyFee);
}
approx.guessMin = guess;
} else {
approx.guessMax = guess - 1;
}
}
revert Errors.ApproxFail();
}
struct Args5 {
MarketState market;
PYIndex index;
uint256 totalPtIn;
uint256 netSyHolding;
uint256 blockTime;
ApproxParams approx;
}
function approxSwapPtToAddLiquidity(
MarketState memory _market,
PYIndex _index,
uint256 _totalPtIn,
uint256 _netSyHolding,
uint256 _blockTime,
ApproxParams memory approx
) internal pure returns (uint256, uint256, uint256 ) {
Args5 memory a = Args5(_market, _index, _totalPtIn, _netSyHolding, _blockTime, approx);
MarketPreCompute memory comp = a.market.getMarketPreCompute(a.index, a.blockTime);
if (approx.guessOffchain == 0) {
approx.guessMax = PMath.min(approx.guessMax, calcMaxPtIn(a.market, comp));
approx.guessMax = PMath.min(approx.guessMax, a.totalPtIn);
validateApprox(approx);
require(a.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(
a.market,
a.index,
a.totalPtIn,
a.netSyHolding,
comp,
guess
);
if (PMath.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,
uint256 netSyHolding,
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 + netSyHolding) * newTotalPt;
ptNumerator = (totalPtIn - guess) * newTotalSy;
}
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 = PMath.max(approx.guessMin, exactPtIn);
approx.guessMax = PMath.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 (PMath.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 > PMath.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 = PMath.IONE.divDown(comp.rateScalar);
return comp.rateAnchor - (part1 - part2).mulDown(part3);
}
}
library MarketApproxPtOutLib {
using MarketMathCore for MarketState;
using PYIndexLib for PYIndex;
using PMath for uint256;
using PMath 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 = PMath.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 (PMath.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 = PMath.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 (PMath.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 netPtHolding;
uint256 blockTime;
ApproxParams approx;
}
function approxSwapSyToAddLiquidity(
MarketState memory _market,
PYIndex _index,
uint256 _totalSyIn,
uint256 _netPtHolding,
uint256 _blockTime,
ApproxParams memory _approx
) internal pure returns (uint256, uint256, uint256 ) {
Args6 memory a = Args6(_market, _index, _totalSyIn, _netPtHolding, _blockTime, _approx);
MarketPreCompute memory comp = a.market.getMarketPreCompute(a.index, a.blockTime);
if (a.approx.guessOffchain == 0) {
a.approx.guessMax = PMath.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 + a.netPtHolding) * netTotalSy;
syNumerator = (a.totalSyIn - netSyIn) * newTotalPt;
}
if (PMath.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 = PMath.max(approx.guessMin, exactYtIn);
approx.guessMax = PMath.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 (PMath.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 + PMath.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 > PMath.ONE) {
revert Errors.ApproxParamsInvalid(approx.guessMin, approx.guessMax, approx.eps);
}
}
}
文件 40 的 52:MarketMathCore.sol
pragma solidity ^0.8.0;
import "../libraries/math/PMath.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 PMath for uint256;
using PMath 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 PMath for uint256;
using PMath 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 = PMath.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 < PMath.IONE) revert Errors.MarketExchangeRateBelowOne(postFeeExchangeRate);
fee = preFeeAssetToAccount.mulDown(PMath.IONE - fee);
} else {
fee = ((preFeeAssetToAccount * (PMath.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 < PMath.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 < PMath.IONE) revert Errors.MarketExchangeRateBelowOne(exchangeRate);
}
function _logProportion(int256 proportion) internal pure returns (int256 res) {
if (proportion == PMath.IONE) revert Errors.MarketProportionMustNotEqualOne();
int256 logitP = proportion.divDown(PMath.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
);
}
}
文件 41 的 52:Math.sol
pragma solidity ^0.8.19;
error Math__toInt256_overflow();
error Math__toUint64_overflow();
error Math__add_overflow_signed();
error Math__sub_overflow_signed();
error Math__mul_overflow_signed();
error Math__mul_overflow();
error Math__div_overflow();
uint256 constant WAD = 1e18;
function toInt256(uint256 x) pure returns (int256) {
if (x >= 1 << 255) revert Math__toInt256_overflow();
return int256(x);
}
function toUint64(uint256 x) pure returns (uint64) {
if (x >= 1 << 64) revert Math__toUint64_overflow();
return uint64(x);
}
function abs(int256 x) pure returns (uint256 z) {
assembly ("memory-safe") {
let mask := sub(0, shr(255, x))
z := xor(mask, add(mask, x))
}
}
function min(uint256 x, uint256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
z := xor(x, mul(xor(x, y), lt(y, x)))
}
}
function min(int256 x, int256 y) pure returns (int256 z) {
assembly ("memory-safe") {
z := xor(x, mul(xor(x, y), slt(y, x)))
}
}
function max(uint256 x, uint256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
z := xor(x, mul(xor(x, y), gt(y, x)))
}
}
function add(uint256 x, int256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
z := add(x, y)
}
if ((y > 0 && z < x) || (y < 0 && z > x)) revert Math__add_overflow_signed();
}
function sub(uint256 x, int256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
z := sub(x, y)
}
if ((y > 0 && z > x) || (y < 0 && z < x)) revert Math__sub_overflow_signed();
}
function mul(uint256 x, int256 y) pure returns (int256 z) {
unchecked {
z = int256(x) * y;
if (int256(x) < 0 || (y != 0 && z / y != int256(x))) revert Math__mul_overflow_signed();
}
}
function wmul(uint256 x, uint256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xc4c5d7f5)
revert(0x1c, 0x04)
}
z := div(mul(x, y), WAD)
}
}
function wmul(uint256 x, int256 y) pure returns (int256 z) {
unchecked {
z = mul(x, y) / int256(WAD);
}
}
function wmulUp(uint256 x, uint256 y) pure returns (uint256 z) {
assembly {
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xc4c5d7f5)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
}
}
function wdiv(uint256 x, uint256 y) pure returns (uint256 z) {
assembly ("memory-safe") {
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0xbcbede65)
revert(0x1c, 0x04)
}
z := div(mul(x, WAD), y)
}
}
function wdivUp(uint256 x, uint256 y) pure returns (uint256 z) {
assembly {
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0xbcbede65)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
}
}
function wpow(uint256 x, uint256 n, uint256 b) pure returns (uint256 z) {
unchecked {
assembly ("memory-safe") {
switch n
case 0 {
z := b
}
default {
switch x
case 0 {
z := 0
}
default {
switch mod(n, 2)
case 0 {
z := b
}
default {
z := x
}
let half := div(b, 2)
for {
n := div(n, 2)
} n {
n := div(n, 2)
} {
let xx := mul(x, x)
if shr(128, x) {
revert(0, 0)
}
let xxRound := add(xx, half)
if lt(xxRound, xx) {
revert(0, 0)
}
x := div(xxRound, b)
if mod(n, 2) {
let zx := mul(z, x)
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) {
revert(0, 0)
}
let zxRound := add(zx, half)
if lt(zxRound, zx) {
revert(0, 0)
}
z := div(zxRound, b)
}
}
}
}
}
}
}
function wpow(int256 x, int256 y) pure returns (int256) {
return wexp((wln(x) * y) / int256(WAD));
}
function wexp(int256 x) pure returns (int256 r) {
unchecked {
if (x <= -42139678854452767551) return r;
assembly {
if iszero(slt(x, 135305999368893231589)) {
mstore(0x00, 0xa37bfec9)
revert(0x1c, 0x04)
}
}
x = (x << 78) / 5 ** 18;
int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;
x = x - k * 54916777467707473351141471128;
int256 y = x + 1346386616545796478920950773328;
y = ((y * x) >> 96) + 57155421227552351082224309758442;
int256 p = y + x - 94201549194550492254356042504812;
p = ((p * y) >> 96) + 28719021644029726153956944680412240;
p = p * x + (4385272521454847904659076985693276 << 96);
int256 q = x - 2855989394907223263936484059900;
q = ((q * x) >> 96) + 50020603652535783019961831881945;
q = ((q * x) >> 96) - 533845033583426703283633433725380;
q = ((q * x) >> 96) + 3604857256930695427073651918091429;
q = ((q * x) >> 96) - 14423608567350463180887372962807573;
q = ((q * x) >> 96) + 26449188498355588339934803723976023;
assembly {
r := sdiv(p, q)
}
r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));
}
}
function wln(int256 x) pure returns (int256 r) {
unchecked {
assembly {
if iszero(sgt(x, 0)) {
mstore(0x00, 0x1615e638)
revert(0x1c, 0x04)
}
}
int256 t;
assembly {
t := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
t := or(t, shl(6, lt(0xffffffffffffffff, shr(t, x))))
t := or(t, shl(5, lt(0xffffffff, shr(t, x))))
t := or(t, shl(4, lt(0xffff, shr(t, x))))
t := or(t, shl(3, lt(0xff, shr(t, x))))
t := xor(
t,
byte(
and(0x1f, shr(shr(t, x), 0x8421084210842108cc6318c6db6d54be)),
0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff
)
)
}
x = int256(uint256(x << uint256(t)) >> 159);
int256 p = x + 3273285459638523848632254066296;
p = ((p * x) >> 96) + 24828157081833163892658089445524;
p = ((p * x) >> 96) + 43456485725739037958740375743393;
p = ((p * x) >> 96) - 11111509109440967052023855526967;
p = ((p * x) >> 96) - 45023709667254063763336534515857;
p = ((p * x) >> 96) - 14706773417378608786704636184526;
p = p * x - (795164235651350426258249787498 << 96);
int256 q = x + 5573035233440673466300451813936;
q = ((q * x) >> 96) + 71694874799317883764090561454958;
q = ((q * x) >> 96) + 283447036172924575727196451306956;
q = ((q * x) >> 96) + 401686690394027663651624208769553;
q = ((q * x) >> 96) + 204048457590392012362485061816622;
q = ((q * x) >> 96) + 31853899698501571402653359427138;
q = ((q * x) >> 96) + 909429971244387300277376558375;
assembly {
r := sdiv(p, q)
}
r *= 1677202110996718588342820967067443963516166;
r += 16597577552685614221487285958193947469193820559219878177908093499208371 * (159 - t);
r += 600920179829731861736702779321621459595472258049074101567377883020018308;
r >>= 174;
}
}
文件 42 的 52:MiniHelpers.sol
pragma solidity ^0.8.0;
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);
}
}
文件 43 的 52:PMath.sol
pragma solidity ^0.8.0;
library PMath {
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 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);
}
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 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);
}
}
文件 44 的 52:PYIndex.sol
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();
}
}
文件 45 的 52:PoolAction.sol
pragma solidity ^0.8.19;
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {TransferAction, PermitParams} from "./TransferAction.sol";
import {IVault, JoinKind, JoinPoolRequest, ExitKind, ExitPoolRequest} from "../vendor/IBalancerVault.sol";
import {IPActionAddRemoveLiqV3} from "pendle/interfaces/IPActionAddRemoveLiqV3.sol";
import {TokenInput, LimitOrderData} from "pendle/interfaces/IPAllActionTypeV3.sol";
import {ApproxParams} from "pendle/router/base/MarketApproxLib.sol";
import {IPPrincipalToken} from "pendle/interfaces/IPPrincipalToken.sol";
import {IStandardizedYield} from "pendle/interfaces/IStandardizedYield.sol";
import {IPYieldToken} from "pendle/interfaces/IPYieldToken.sol";
import {IPMarket} from "pendle/interfaces/IPMarket.sol";
import {ISwapRouter} from "src/interfaces/ISwapRouterTranchess.sol";
import {IStableSwap} from "src/interfaces/IStableSwapTranchess.sol";
import {ISpectraRouter} from "src/interfaces/ISpectraRouter.sol";
interface ILiquidityGauge {
function stableSwap() external view returns (address);
}
enum Protocol {
BALANCER,
UNIV3,
PENDLE,
TRANCHESS,
SPECTRA
}
struct PoolActionParams {
Protocol protocol;
uint256 minOut;
address recipient;
bytes args;
}
contract PoolAction is TransferAction {
using SafeERC20 for IERC20;
IVault public immutable balancerVault;
IPActionAddRemoveLiqV3 public immutable pendleRouter;
ISwapRouter public immutable tranchessRouter;
ISpectraRouter public immutable spectraRouter;
error PoolAction__join_unsupportedProtocol();
error PoolAction__transferAndJoin_unsupportedProtocol();
error PoolAction__transferAndJoin_invalidPermitParams();
error PoolAction__transferAndJoin_invalidAssetOrder();
error PoolAction__exit_unsupportedProtocol();
constructor(address balancerVault_, address _pendleRouter, address _tranchessRouter, address _spectraRouter) {
balancerVault = IVault(balancerVault_);
pendleRouter = IPActionAddRemoveLiqV3(_pendleRouter);
tranchessRouter = ISwapRouter(_tranchessRouter);
spectraRouter = ISpectraRouter(_spectraRouter);
}
function transferAndJoin(
address from,
PermitParams[] calldata permitParams,
PoolActionParams calldata poolActionParams
) external {
if (from != address(this)) {
if (poolActionParams.protocol == Protocol.BALANCER) {
(, address[] memory assets, , uint256[] memory maxAmountsIn) = abi.decode(
poolActionParams.args,
(bytes32, address[], uint256[], uint256[])
);
if (assets.length != permitParams.length) {
revert PoolAction__transferAndJoin_invalidPermitParams();
}
if (assets.length > 1) {
for (uint256 i = 0; i < assets.length - 1; i++) {
if (assets[i] > assets[i + 1]) {
revert PoolAction__transferAndJoin_invalidAssetOrder();
}
}
}
for (uint256 i = 0; i < assets.length; ) {
if (maxAmountsIn[i] != 0) {
_transferFrom(assets[i], from, address(this), maxAmountsIn[i], permitParams[i]);
}
unchecked {
++i;
}
}
} else if (poolActionParams.protocol == Protocol.PENDLE) {
(, , TokenInput memory input, ) = abi.decode(
poolActionParams.args,
(address, ApproxParams, TokenInput, LimitOrderData)
);
if (input.tokenIn != address(0)) {
_transferFrom(input.tokenIn, from, address(this), input.netTokenIn, permitParams[0]);
}
} else if (poolActionParams.protocol == Protocol.TRANCHESS) {
(address lpToken, uint256 baseDelta, uint256 quoteDelta, , ) = abi.decode(
poolActionParams.args,
(address, uint256, uint256, uint256, uint256)
);
IStableSwap stableSwap = IStableSwap(ILiquidityGauge(lpToken).stableSwap());
address baseAddress = stableSwap.baseAddress();
address quoteAddress = stableSwap.quoteAddress();
if (baseDelta != 0) {
_transferFrom(baseAddress, from, address(this), baseDelta, permitParams[0]);
}
if (quoteDelta != 0) {
_transferFrom(quoteAddress, from, address(this), quoteDelta, permitParams[1]);
}
} else if (poolActionParams.protocol == Protocol.SPECTRA) {
(, bytes[] memory inputs, ) = abi.decode(poolActionParams.args, (bytes, bytes[], uint256));
(address tokenIn, uint256 amountIn) = abi.decode(inputs[0], (address, uint256));
if (tokenIn != address(0)) {
_transferFrom(tokenIn, from, address(this), amountIn, permitParams[0]);
}
} else revert PoolAction__transferAndJoin_unsupportedProtocol();
}
join(poolActionParams);
}
function join(PoolActionParams memory poolActionParams) public {
if (poolActionParams.protocol == Protocol.BALANCER) {
_balancerJoin(poolActionParams);
} else if (poolActionParams.protocol == Protocol.PENDLE) {
_pendleJoin(poolActionParams);
} else if (poolActionParams.protocol == Protocol.TRANCHESS) {
_tranchessJoin(poolActionParams);
} else if (poolActionParams.protocol == Protocol.SPECTRA) {
_spectraJoin(poolActionParams);
} else revert PoolAction__join_unsupportedProtocol();
}
function _balancerJoin(PoolActionParams memory poolActionParams) internal {
(bytes32 poolId, address[] memory assets, uint256[] memory assetsIn, uint256[] memory maxAmountsIn) = abi
.decode(poolActionParams.args, (bytes32, address[], uint256[], uint256[]));
for (uint256 i = 0; i < assets.length; ) {
if (maxAmountsIn[i] != 0) {
IERC20(assets[i]).forceApprove(address(balancerVault), maxAmountsIn[i]);
}
unchecked {
++i;
}
}
balancerVault.joinPool(
poolId,
address(this),
poolActionParams.recipient,
JoinPoolRequest({
assets: assets,
maxAmountsIn: maxAmountsIn,
userData: abi.encode(JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, assetsIn, poolActionParams.minOut),
fromInternalBalance: false
})
);
}
function _pendleJoin(PoolActionParams memory poolActionParams) internal {
(
address market,
ApproxParams memory guessPtReceivedFromSy,
TokenInput memory input,
LimitOrderData memory limit
) = abi.decode(poolActionParams.args, (address, ApproxParams, TokenInput, LimitOrderData));
if (input.tokenIn != address(0)) {
IERC20(input.tokenIn).forceApprove(address(pendleRouter), input.netTokenIn);
}
pendleRouter.addLiquiditySingleToken(
poolActionParams.recipient,
market,
poolActionParams.minOut,
guessPtReceivedFromSy,
input,
limit
);
}
function _tranchessJoin(PoolActionParams memory poolActionParams) internal {
(address lpToken, uint256 baseDelta, uint256 quoteDelta, uint256 version, uint256 deadline) = abi.decode(
poolActionParams.args,
(address, uint256, uint256, uint256, uint256)
);
IStableSwap stableSwap = IStableSwap(ILiquidityGauge(lpToken).stableSwap());
address baseAddress = stableSwap.baseAddress();
address quoteAddress = stableSwap.quoteAddress();
if (baseDelta != 0) {
IERC20(baseAddress).forceApprove(address(tranchessRouter), baseDelta);
}
if (quoteDelta != 0) {
IERC20(quoteAddress).forceApprove(address(tranchessRouter), quoteDelta);
}
tranchessRouter.addLiquidity(
baseAddress,
quoteAddress,
baseDelta,
quoteDelta,
poolActionParams.minOut,
version,
deadline
);
if (poolActionParams.recipient != address(this)) {
IERC20(lpToken).safeTransfer(poolActionParams.recipient, IERC20(lpToken).balanceOf(address(this)));
}
}
function _spectraJoin(PoolActionParams memory poolActionParams) internal {
(bytes memory commands, bytes[] memory inputs, uint256 deadline) = abi.decode(
poolActionParams.args,
(bytes, bytes[], uint256)
);
(address tokenIn, uint256 amountIn) = abi.decode(inputs[0], (address, uint256));
IERC20(tokenIn).forceApprove(address(spectraRouter), amountIn);
spectraRouter.execute(commands, inputs, deadline);
}
function updateLeverJoin(
PoolActionParams memory poolActionParams,
address joinToken,
address upFrontToken,
uint256 flashLoanAmount,
uint256 upfrontAmount
) external view returns (PoolActionParams memory outParams) {
outParams = poolActionParams;
if (poolActionParams.protocol == Protocol.BALANCER) {
(bytes32 poolId, address[] memory assets, uint256[] memory assetsIn, uint256[] memory maxAmountsIn) = abi
.decode(poolActionParams.args, (bytes32, address[], uint256[], uint256[]));
(address poolToken, ) = balancerVault.getPool(poolId);
uint256 len = assets.length;
bool skipIndex = false;
uint256 joinAmount = flashLoanAmount;
if (upFrontToken == joinToken) {
joinAmount += upfrontAmount;
}
for (uint256 i = 0; i < len; ) {
uint256 assetIndex = i - (skipIndex ? 1 : 0);
if (assets[i] == joinToken) {
maxAmountsIn[i] = joinAmount;
assetsIn[assetIndex] = joinAmount;
} else if (assets[i] == upFrontToken && assets[i] != poolToken) {
maxAmountsIn[i] = upfrontAmount;
assetsIn[assetIndex] = upfrontAmount;
} else {
skipIndex = skipIndex || assets[i] == poolToken;
if (assets[i] == poolToken) {
maxAmountsIn[i] = 0;
}
}
unchecked {
i++;
}
}
outParams.args = abi.encode(poolId, assets, assetsIn, maxAmountsIn);
}
}
function exit(PoolActionParams memory poolActionParams) public returns (uint256 retAmount) {
if (poolActionParams.protocol == Protocol.BALANCER) {
retAmount = _balancerExit(poolActionParams);
} else if (poolActionParams.protocol == Protocol.PENDLE) {
retAmount = _pendleExit(poolActionParams);
} else if (poolActionParams.protocol == Protocol.TRANCHESS) {
retAmount = _tranchessExit(poolActionParams);
} else if (poolActionParams.protocol == Protocol.SPECTRA) {
retAmount = _spectraExit(poolActionParams);
} else revert PoolAction__exit_unsupportedProtocol();
}
function _balancerExit(PoolActionParams memory poolActionParams) internal returns (uint256 retAmount) {
(
bytes32 poolId,
address bpt,
uint256 bptAmount,
uint256 outIndex,
address[] memory assets,
uint256[] memory minAmountsOut
) = abi.decode(poolActionParams.args, (bytes32, address, uint256, uint256, address[], uint256[]));
if (bptAmount != 0) IERC20(bpt).forceApprove(address(balancerVault), bptAmount);
uint256 tmpOutIndex = outIndex;
for (uint256 i = 0; i <= tmpOutIndex; i++) if (assets[i] == bpt) tmpOutIndex++;
uint256 balanceBefore = IERC20(assets[tmpOutIndex]).balanceOf(poolActionParams.recipient);
balancerVault.exitPool(
poolId,
address(this),
payable(poolActionParams.recipient),
ExitPoolRequest({
assets: assets,
minAmountsOut: minAmountsOut,
userData: abi.encode(ExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, bptAmount, outIndex),
toInternalBalance: false
})
);
return IERC20(assets[tmpOutIndex]).balanceOf(poolActionParams.recipient) - balanceBefore;
}
function _pendleExit(PoolActionParams memory poolActionParams) internal returns (uint256 retAmount) {
(address market, uint256 netLpIn, address tokenOut) = abi.decode(
poolActionParams.args,
(address, uint256, address)
);
(IStandardizedYield SY, IPPrincipalToken PT, IPYieldToken YT) = IPMarket(market).readTokens();
if (poolActionParams.recipient != address(this)) {
IPMarket(market).transferFrom(poolActionParams.recipient, market, netLpIn);
} else {
IPMarket(market).transfer(market, netLpIn);
}
uint256 netSyToRedeem;
if (PT.isExpired()) {
(uint256 netSyRemoved, ) = IPMarket(market).burn(address(SY), address(YT), netLpIn);
uint256 netSyFromPt = YT.redeemPY(address(SY));
netSyToRedeem = netSyRemoved + netSyFromPt;
} else {
(uint256 netSyRemoved, uint256 netPtRemoved) = IPMarket(market).burn(address(SY), market, netLpIn);
bytes memory empty;
(uint256 netSySwappedOut, ) = IPMarket(market).swapExactPtForSy(address(SY), netPtRemoved, empty);
netSyToRedeem = netSyRemoved + netSySwappedOut;
}
return SY.redeem(poolActionParams.recipient, netSyToRedeem, tokenOut, poolActionParams.minOut, true);
}
function _tranchessExit(PoolActionParams memory poolActionParams) internal returns (uint256 retAmount) {
(uint256 version, address lpToken, uint256 lpIn) = abi.decode(
poolActionParams.args,
(uint256, address, uint256)
);
IStableSwap stableSwap = IStableSwap(ILiquidityGauge(lpToken).stableSwap());
retAmount = stableSwap.removeQuoteLiquidity(version, lpIn, poolActionParams.minOut);
if (poolActionParams.recipient != address(this)) {
IERC20(stableSwap.quoteAddress()).safeTransfer(poolActionParams.recipient, retAmount);
}
}
function _spectraExit(PoolActionParams memory poolActionParams) internal returns (uint256 retAmount) {
(bytes memory commands, bytes[] memory inputs, address tokenOut, uint256 deadline) = abi.decode(
poolActionParams.args,
(bytes, bytes[], address, uint256)
);
(address tokenIn, uint256 amountIn) = abi.decode(inputs[0], (address, uint256));
uint256 balBefore = IERC20(tokenOut).balanceOf(address(this));
IERC20(tokenIn).forceApprove(address(spectraRouter), amountIn);
spectraRouter.execute(commands, inputs, deadline);
retAmount = IERC20(tokenOut).balanceOf(address(this)) - balBefore;
}
}
文件 46 的 52:PositionAction.sol
pragma solidity ^0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IPoolV3} from "../interfaces/IPoolV3.sol";
import {IPermission} from "../interfaces/IPermission.sol";
import {ICDPVault} from "../interfaces/ICDPVault.sol";
import {toInt256, wmul, wdiv, min} from "../utils/Math.sol";
import {TransferAction, PermitParams} from "./TransferAction.sol";
import {BaseAction} from "./BaseAction.sol";
import {SwapAction, SwapParams, SwapType} from "./SwapAction.sol";
import {PoolAction, PoolActionParams} from "./PoolAction.sol";
import {IVaultRegistry} from "../interfaces/IVaultRegistry.sol";
import {IWETH} from "../reward/interfaces/IWETH.sol";
import {IFlashlender, IERC3156FlashBorrower, ICreditFlashBorrower} from "../interfaces/IFlashlender.sol";
struct CollateralParams {
address targetToken;
uint256 amount;
address collateralizer;
SwapParams auxSwap;
uint256 minAmountOut;
}
struct CreditParams {
uint256 amount;
address creditor;
SwapParams auxSwap;
}
struct LeverParams {
address position;
address vault;
address collateralToken;
SwapParams primarySwap;
SwapParams auxSwap;
PoolActionParams auxAction;
}
struct LocalVars {
uint256 totalDebt;
uint256 subDebt;
uint256 withdrawnCollateral;
uint256 swapAmountOut;
uint256 residualDestAmount;
uint256 residualSrcAmount;
uint256 estimatedSwapInAmount;
}
abstract contract PositionAction is IERC3156FlashBorrower, ICreditFlashBorrower, TransferAction, BaseAction {
using SafeERC20 for IERC20;
bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
bytes32 public constant CALLBACK_SUCCESS_CREDIT = keccak256("CreditFlashBorrower.onCreditFlashLoan");
IVaultRegistry public immutable vaultRegistry;
IFlashlender public immutable flashlender;
IPoolV3 public immutable pool;
IERC20 public immutable underlyingToken;
address public immutable self;
SwapAction public immutable swapAction;
PoolAction public immutable poolAction;
IWETH public immutable WETH;
error PositionAction__constructor_InvalidParam();
error PositionAction__deposit_InvalidAuxSwap();
error PositionAction__borrow_InvalidAuxSwap();
error PositionAction__repay_InvalidAuxSwap();
error PositionAction__increaseLever_invalidPrimarySwap();
error PositionAction__increaseLever_invalidAuxSwap();
error PositionAction__decreaseLever_invalidPrimarySwap();
error PositionAction__decreaseLever_invalidAuxSwap();
error PositionAction__decreaseLever_invalidClosePositionPrimarySwap();
error PositionAction__decreaseLever_invalidResidualRecipient();
error PositionAction__onFlashLoan__invalidSender();
error PositionAction__onFlashLoan__invalidInitiator();
error PositionAction__onCreditFlashLoan__invalidSender();
error PositionAction__onlyDelegatecall();
error PositionAction__unregisteredVault();
constructor(address flashlender_, address swapAction_, address poolAction_, address vaultRegistry_, address weth_) {
if (
flashlender_ == address(0) ||
swapAction_ == address(0) ||
poolAction_ == address(0) ||
vaultRegistry_ == address(0)
) revert PositionAction__constructor_InvalidParam();
flashlender = IFlashlender(flashlender_);
pool = flashlender.pool();
vaultRegistry = IVaultRegistry(vaultRegistry_);
underlyingToken = IERC20(pool.underlyingToken());
self = address(this);
swapAction = SwapAction(swapAction_);
poolAction = PoolAction(poolAction_);
WETH = IWETH(weth_);
}
modifier onlyDelegatecall() {
if (address(this) == self) revert PositionAction__onlyDelegatecall();
_;
}
modifier onlyRegisteredVault(address vault) {
if (!vaultRegistry.isVaultRegistered(vault)) revert PositionAction__unregisteredVault();
_;
}
function _onDeposit(
address vault,
address position,
address src,
uint256 amount
) internal virtual returns (uint256);
function _onWithdraw(
address vault,
address position,
address dst,
uint256 amount,
uint256 minAmountOut
) internal virtual returns (uint256);
function _onIncreaseLever(
LeverParams memory leverParams,
address upFrontToken,
uint256 upFrontAmount,
uint256 swapAmountOut
) internal virtual returns (uint256);
function _onDecreaseLever(LeverParams memory leverParams, uint256 subCollateral) internal virtual returns (uint256);
function deposit(
address position,
address vault,
CollateralParams calldata collateralParams,
PermitParams calldata permitParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_deposit(vault, position, collateralParams, permitParams);
}
function withdraw(
address position,
address vault,
CollateralParams calldata collateralParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_withdraw(vault, position, collateralParams);
}
function borrow(
address position,
address vault,
CreditParams calldata creditParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_borrow(vault, position, creditParams);
}
function repay(
address position,
address vault,
CreditParams calldata creditParams,
PermitParams calldata permitParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_repay(vault, position, creditParams, permitParams);
}
function depositAndBorrow(
address position,
address vault,
CollateralParams calldata collateralParams,
CreditParams calldata creditParams,
PermitParams calldata permitParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_deposit(vault, position, collateralParams, permitParams);
_borrow(vault, position, creditParams);
}
function withdrawAndRepay(
address position,
address vault,
CollateralParams calldata collateralParams,
CreditParams calldata creditParams,
PermitParams calldata permitParams
) external onlyRegisteredVault(vault) onlyDelegatecall {
_repay(vault, position, creditParams, permitParams);
_withdraw(vault, position, collateralParams);
}
function multisend(
address[] calldata targets,
bytes[] calldata data,
bool[] calldata delegateCall
) external onlyDelegatecall {
uint256 totalTargets = targets.length;
for (uint256 i; i < totalTargets; ) {
if (delegateCall[i]) {
_delegateCall(targets[i], data[i]);
} else {
(bool success, bytes memory response) = targets[i].call(data[i]);
if (!success) _revertBytes(response);
}
unchecked {
++i;
}
}
}
function increaseLever(
LeverParams calldata leverParams,
address upFrontToken,
uint256 upFrontAmount,
address collateralizer,
PermitParams calldata permitParams
) external payable onlyDelegatecall onlyRegisteredVault(leverParams.vault) {
if (
leverParams.primarySwap.swapType != SwapType.EXACT_IN ||
leverParams.primarySwap.assetIn != address(underlyingToken) ||
leverParams.primarySwap.recipient != self
) revert PositionAction__increaseLever_invalidPrimarySwap();
if (
leverParams.auxSwap.assetIn != address(0) &&
(leverParams.auxSwap.swapType != SwapType.EXACT_IN ||
leverParams.auxSwap.assetIn != upFrontToken ||
leverParams.auxSwap.recipient != self)
) revert PositionAction__increaseLever_invalidAuxSwap();
if (msg.value > 0) {
WETH.deposit{value: msg.value}();
WETH.transfer(self, upFrontAmount);
} else if (upFrontAmount > 0) {
if (collateralizer == address(this)) {
IERC20(upFrontToken).safeTransfer(self, upFrontAmount);
} else {
_transferFrom(upFrontToken, collateralizer, self, upFrontAmount, permitParams);
}
}
IPermission(leverParams.vault).modifyPermission(leverParams.position, self, true);
flashlender.flashLoan(
IERC3156FlashBorrower(self),
address(underlyingToken),
leverParams.primarySwap.amount,
abi.encode(leverParams, upFrontToken, upFrontAmount)
);
IPermission(leverParams.vault).modifyPermission(leverParams.position, self, false);
}
function decreaseLever(
LeverParams memory leverParams,
uint256 subCollateral,
address residualRecipient
) external onlyDelegatecall onlyRegisteredVault(leverParams.vault) {
if (leverParams.primarySwap.recipient != self) revert PositionAction__decreaseLever_invalidPrimarySwap();
IPermission(leverParams.vault).modifyPermission(leverParams.position, self, true);
if (residualRecipient == address(0)) {
revert PositionAction__decreaseLever_invalidResidualRecipient();
}
flashlender.creditFlashLoan(
ICreditFlashBorrower(self),
leverParams.primarySwap.swapType == SwapType.EXACT_IN
? leverParams.primarySwap.limit
: leverParams.primarySwap.amount,
abi.encode(leverParams, subCollateral, residualRecipient)
);
IPermission(leverParams.vault).modifyPermission(leverParams.position, self, false);
}
function onFlashLoan(
address ,
address ,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32) {
if (msg.sender != address(flashlender)) revert PositionAction__onFlashLoan__invalidSender();
(LeverParams memory leverParams, address upFrontToken, uint256 upFrontAmount) = abi.decode(
data,
(LeverParams, address, uint256)
);
if (leverParams.auxSwap.assetIn != address(0)) {
bytes memory auxSwapData = _delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.auxSwap)
);
upFrontAmount = abi.decode(auxSwapData, (uint256));
}
bytes memory swapData = _delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.primarySwap)
);
uint256 swapAmountOut = abi.decode(swapData, (uint256));
uint256 collateral = _onIncreaseLever(leverParams, upFrontToken, upFrontAmount, swapAmountOut);
uint256 addDebt = amount + fee;
ICDPVault(leverParams.vault).modifyCollateralAndDebt(
leverParams.position,
address(this),
address(this),
toInt256(collateral),
toInt256(addDebt)
);
underlyingToken.forceApprove(address(flashlender), addDebt);
return CALLBACK_SUCCESS;
}
function onCreditFlashLoan(
address ,
uint256 ,
uint256 fee,
bytes calldata data
) external returns (bytes32) {
if (msg.sender != address(flashlender)) revert PositionAction__onCreditFlashLoan__invalidSender();
(LeverParams memory leverParams, uint256 subCollateral, address residualRecipient) = abi.decode(
data,
(LeverParams, uint256, address)
);
LocalVars memory vars;
vars.totalDebt = ICDPVault(leverParams.vault).virtualDebt(leverParams.position);
if (leverParams.primarySwap.swapType == SwapType.EXACT_IN) {
vars.subDebt = min(vars.totalDebt + fee, leverParams.primarySwap.limit);
underlyingToken.forceApprove(address(leverParams.vault), vars.subDebt + fee);
ICDPVault(leverParams.vault).modifyCollateralAndDebt(
leverParams.position,
address(this),
address(this),
0,
-toInt256(vars.subDebt - fee)
);
vars.estimatedSwapInAmount = leverParams.primarySwap.amount;
vars.withdrawnCollateral = _onDecreaseLever(leverParams, subCollateral);
leverParams.primarySwap.amount = vars.withdrawnCollateral;
bytes memory swapData = _delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.primarySwap)
);
vars.swapAmountOut = abi.decode(swapData, (uint256));
vars.residualDestAmount = vars.swapAmountOut - (vars.subDebt + fee);
if (vars.residualDestAmount > 0) {
if (vars.subDebt < vars.totalDebt) {
underlyingToken.forceApprove(address(leverParams.vault), vars.residualDestAmount);
ICDPVault(leverParams.vault).modifyCollateralAndDebt(
leverParams.position,
address(this),
address(this),
0,
-toInt256(vars.residualDestAmount)
);
} else if (
leverParams.auxSwap.assetIn != address(0) && leverParams.auxSwap.swapType == SwapType.EXACT_IN
) {
leverParams.auxSwap.amount = vars.residualDestAmount;
_delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.auxSwap)
);
} else {
underlyingToken.safeTransfer(residualRecipient, vars.residualDestAmount);
}
}
vars.residualSrcAmount = vars.withdrawnCollateral - vars.estimatedSwapInAmount;
if (vars.residualSrcAmount > 0) {
IERC20(leverParams.primarySwap.assetIn).safeTransfer(residualRecipient, vars.residualSrcAmount);
}
underlyingToken.forceApprove(address(flashlender), leverParams.primarySwap.limit + fee);
} else {
leverParams.primarySwap.amount = min(vars.totalDebt + fee, leverParams.primarySwap.amount);
vars.subDebt = leverParams.primarySwap.amount;
underlyingToken.forceApprove(address(leverParams.vault), vars.subDebt + fee);
ICDPVault(leverParams.vault).modifyCollateralAndDebt(
leverParams.position,
address(this),
address(this),
0,
-toInt256(vars.subDebt - fee)
);
vars.withdrawnCollateral = _onDecreaseLever(leverParams, subCollateral);
bytes memory swapData = _delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.primarySwap)
);
uint256 swapAmountIn = abi.decode(swapData, (uint256));
vars.residualSrcAmount = vars.withdrawnCollateral - swapAmountIn;
if (vars.residualSrcAmount > 0) {
if (leverParams.auxSwap.assetIn != address(0) && leverParams.auxSwap.swapType == SwapType.EXACT_IN) {
leverParams.auxSwap.amount = vars.residualSrcAmount;
_delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, leverParams.auxSwap)
);
} else {
IERC20(leverParams.primarySwap.assetIn).safeTransfer(residualRecipient, vars.residualSrcAmount);
}
}
underlyingToken.forceApprove(address(flashlender), vars.subDebt + fee);
}
return CALLBACK_SUCCESS_CREDIT;
}
function _deposit(
address vault,
address position,
CollateralParams calldata collateralParams,
PermitParams calldata permitParams
) internal returns (uint256) {
uint256 amount = collateralParams.amount;
if (collateralParams.auxSwap.assetIn != address(0)) {
if (
collateralParams.auxSwap.assetIn != collateralParams.targetToken ||
collateralParams.auxSwap.recipient != address(this)
) revert PositionAction__deposit_InvalidAuxSwap();
amount = _transferAndSwap(collateralParams.collateralizer, collateralParams.auxSwap, permitParams);
} else if (collateralParams.collateralizer != address(this)) {
_transferFrom(
collateralParams.targetToken,
collateralParams.collateralizer,
address(this),
amount,
permitParams
);
}
return _onDeposit(vault, position, collateralParams.targetToken, amount);
}
function _withdraw(
address vault,
address position,
CollateralParams calldata collateralParams
) internal returns (uint256) {
uint256 collateral = _onWithdraw(vault, position, collateralParams.targetToken, collateralParams.amount, collateralParams.minAmountOut);
uint256 scaledCollateral = wmul(collateral, ICDPVault(vault).tokenScale());
if (collateralParams.auxSwap.assetIn != address(0)) {
SwapParams memory auxSwap = collateralParams.auxSwap;
if (auxSwap.swapType == SwapType.EXACT_IN) {
auxSwap.amount = scaledCollateral;
}
_delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.swap.selector, auxSwap)
);
} else {
IERC20(collateralParams.targetToken).safeTransfer(collateralParams.collateralizer, scaledCollateral);
}
return scaledCollateral;
}
function _borrow(address vault, address position, CreditParams calldata creditParams) internal {
uint256 scaledBorrowAmount = wdiv(creditParams.amount, ICDPVault(vault).poolUnderlyingScale());
ICDPVault(vault).modifyCollateralAndDebt(
position,
address(this),
address(this),
0,
toInt256(scaledBorrowAmount)
);
if (creditParams.auxSwap.assetIn == address(0)) {
underlyingToken.forceApprove(address(this), creditParams.amount);
underlyingToken.safeTransferFrom(address(this), creditParams.creditor, creditParams.amount);
} else {
if (creditParams.auxSwap.assetIn != address(underlyingToken)) {
revert PositionAction__borrow_InvalidAuxSwap();
}
_delegateCall(address(swapAction), abi.encodeWithSelector(swapAction.swap.selector, creditParams.auxSwap));
}
}
function _repay(
address vault,
address position,
CreditParams calldata creditParams,
PermitParams calldata permitParams
) internal {
uint256 amount = creditParams.amount;
if (creditParams.auxSwap.assetIn != address(0)) {
if (creditParams.auxSwap.recipient != address(this)) revert PositionAction__repay_InvalidAuxSwap();
amount = _transferAndSwap(creditParams.creditor, creditParams.auxSwap, permitParams);
} else {
if (creditParams.creditor != address(this)) {
_transferFrom(
address(underlyingToken),
creditParams.creditor,
address(this),
creditParams.amount,
permitParams
);
}
}
underlyingToken.forceApprove(address(vault), amount);
uint256 scaledAmount = wdiv(amount, ICDPVault(vault).poolUnderlyingScale());
ICDPVault(vault).modifyCollateralAndDebt(
position,
address(this),
address(this),
0,
-toInt256(scaledAmount)
);
}
function _transferAndSwap(
address sender,
SwapParams calldata swapParams,
PermitParams calldata permitParams
) internal returns (uint256 amountOut) {
bytes memory response = _delegateCall(
address(swapAction),
abi.encodeWithSelector(swapAction.transferAndSwap.selector, sender, permitParams, swapParams)
);
uint256 retAmount = abi.decode(response, (uint256));
if (swapParams.swapType == SwapType.EXACT_OUT) {
uint256 remainder = swapParams.limit - retAmount;
if (remainder > 0) {
IERC20(swapParams.assetIn).safeTransfer(sender, remainder);
}
amountOut = swapParams.amount;
} else {
amountOut = retAmount;
}
}
}
文件 47 的 52:PositionActionTranchess.sol
pragma solidity ^0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ICDPVault} from "../interfaces/ICDPVault.sol";
import {PositionAction, LeverParams} from "./PositionAction.sol";
contract PositionActionTranchess is PositionAction {
using SafeERC20 for IERC20;
constructor(
address flashlender_,
address swapAction_,
address poolAction_,
address vaultRegistry_,
address weth_
) PositionAction(flashlender_, swapAction_, poolAction_, vaultRegistry_, weth_) {}
function _onDeposit(
address vault,
address position,
address ,
uint256 amount
) internal override returns (uint256) {
address collateralToken = address(ICDPVault(vault).token());
IERC20(collateralToken).forceApprove(vault, amount);
return ICDPVault(vault).deposit(position, amount);
}
function _onWithdraw(
address vault,
address position,
address ,
uint256 amount,
uint256
) internal override returns (uint256) {
return ICDPVault(vault).withdraw(position, amount);
}
function _onIncreaseLever(
LeverParams memory leverParams,
address ,
uint256 ,
uint256
) internal override returns (uint256 addCollateralAmount) {
if (leverParams.auxAction.args.length != 0) {
_delegateCall(address(poolAction), abi.encodeWithSelector(poolAction.join.selector, leverParams.auxAction));
}
addCollateralAmount = ICDPVault(leverParams.vault).token().balanceOf(address(this));
IERC20(leverParams.collateralToken).forceApprove(leverParams.vault, addCollateralAmount);
return addCollateralAmount;
}
function _onDecreaseLever(
LeverParams memory leverParams,
uint256 subCollateral
) internal override returns (uint256 tokenOut) {
_onWithdraw(leverParams.vault, leverParams.position, address(0), subCollateral, 0);
if (leverParams.auxAction.args.length != 0) {
bytes memory exitData = _delegateCall(
address(poolAction),
abi.encodeWithSelector(poolAction.exit.selector, leverParams.auxAction)
);
tokenOut = abi.decode(exitData, (uint256));
}
}
}
文件 48 的 52:SYUtils.sol
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;
}
}
文件 49 的 52:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/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 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
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));
}
}
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);
}
}
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");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 50 的 52:SwapAction.sol
pragma solidity ^0.8.19;
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IUniswapV3Router, ExactInputParams, ExactOutputParams, decodeLastToken} from "../vendor/IUniswapV3Router.sol";
import {IVault, SwapKind, BatchSwapStep, FundManagement} from "../vendor/IBalancerVault.sol";
import {TokenInput, LimitOrderData} from "pendle/interfaces/IPAllActionTypeV3.sol";
import {ApproxParams} from "pendle/router/base/MarketApproxLib.sol";
import {IPActionAddRemoveLiqV3} from "pendle/interfaces/IPActionAddRemoveLiqV3.sol";
import {IPPrincipalToken} from "pendle/interfaces/IPPrincipalToken.sol";
import {IStandardizedYield} from "pendle/interfaces/IStandardizedYield.sol";
import {IPYieldToken} from "pendle/interfaces/IPYieldToken.sol";
import {IPMarket} from "pendle/interfaces/IPMarket.sol";
import {toInt256, abs} from "../utils/Math.sol";
import {TransferAction, PermitParams} from "./TransferAction.sol";
import {ISwapRouter} from "src/interfaces/ISwapRouterTranchess.sol";
import {IStableSwap} from "src/interfaces/IStableSwapTranchess.sol";
import {ISpectraRouter} from "src/interfaces/ISpectraRouter.sol";
interface ILiquidityGauge {
function stableSwap() external view returns (address);
}
enum SwapProtocol {
BALANCER,
UNIV3,
PENDLE_IN,
PENDLE_OUT,
KYBER,
TRANCHESS_IN,
TRANCHESS_OUT,
SPECTRA
}
enum SwapType {
EXACT_IN,
EXACT_OUT
}
struct SwapParams {
SwapProtocol swapProtocol;
SwapType swapType;
address assetIn;
uint256 amount;
uint256 limit;
address recipient;
address residualRecipient;
uint256 deadline;
bytes args;
}
contract SwapAction is TransferAction {
using SafeERC20 for IERC20;
IVault public immutable balancerVault;
IUniswapV3Router public immutable uniRouter;
IPActionAddRemoveLiqV3 public immutable pendleRouter;
address public immutable kyberRouter;
ISwapRouter public immutable tranchessRouter;
ISpectraRouter public immutable spectraRouter;
error SwapAction__swap_notSupported();
error SwapAction__revertBytes_emptyRevertBytes();
error SwapAction__kyberSwap_slippageFailed();
constructor(
IVault balancerVault_,
IUniswapV3Router uniRouter_,
IPActionAddRemoveLiqV3 pendleRouter_,
address kyberRouter_,
address tranchessRouter_,
address spectraRouter_
) {
balancerVault = balancerVault_;
uniRouter = uniRouter_;
pendleRouter = pendleRouter_;
kyberRouter = kyberRouter_;
tranchessRouter = ISwapRouter(tranchessRouter_);
spectraRouter = ISpectraRouter(spectraRouter_);
}
function transferAndSwap(
address from,
PermitParams calldata permitParams,
SwapParams calldata swapParams
) external returns (uint256) {
if (from != address(this)) {
uint256 amount = swapParams.swapType == SwapType.EXACT_IN ? swapParams.amount : swapParams.limit;
_transferFrom(swapParams.assetIn, from, address(this), amount, permitParams);
}
return swap(swapParams);
}
function swap(SwapParams memory swapParams) public returns (uint256 retAmount) {
if (block.timestamp > swapParams.deadline) {
_revertBytes("SwapAction: swap deadline passed");
}
if (swapParams.swapProtocol == SwapProtocol.BALANCER) {
(bytes32[] memory poolIds, address[] memory assetPath) = abi.decode(
swapParams.args,
(bytes32[], address[])
);
retAmount = balancerSwap(
swapParams.swapType,
swapParams.assetIn,
poolIds,
assetPath,
swapParams.amount,
swapParams.limit,
swapParams.recipient,
swapParams.deadline
);
} else if (swapParams.swapProtocol == SwapProtocol.KYBER && swapParams.swapType == SwapType.EXACT_IN) {
retAmount = kyberSwap(swapParams.assetIn, swapParams.amount, swapParams.limit, swapParams.args);
} else if (swapParams.swapProtocol == SwapProtocol.UNIV3) {
retAmount = uniV3Swap(
swapParams.swapType,
swapParams.assetIn,
swapParams.amount,
swapParams.limit,
swapParams.recipient,
swapParams.deadline,
swapParams.args
);
} else if (swapParams.swapProtocol == SwapProtocol.PENDLE_IN) {
retAmount = pendleJoin(swapParams.recipient, swapParams.limit, swapParams.args);
} else if (swapParams.swapProtocol == SwapProtocol.PENDLE_OUT) {
retAmount = pendleExit(swapParams.recipient, swapParams.limit, swapParams.args);
} else if (swapParams.swapProtocol == SwapProtocol.TRANCHESS_IN) {
retAmount = tranchessJoin(swapParams);
} else if (swapParams.swapProtocol == SwapProtocol.TRANCHESS_OUT) {
retAmount = tranchessExit(swapParams.recipient, swapParams.limit, swapParams.args);
} else if (swapParams.swapProtocol == SwapProtocol.SPECTRA) {
retAmount = spectra(swapParams);
} else revert SwapAction__swap_notSupported();
if (swapParams.swapType == SwapType.EXACT_OUT && swapParams.recipient != address(this)) {
if (swapParams.residualRecipient != address(0)) {
IERC20(swapParams.assetIn).safeTransfer(swapParams.residualRecipient, swapParams.limit - retAmount);
} else {
IERC20(swapParams.assetIn).safeTransfer(swapParams.recipient, swapParams.limit - retAmount);
}
}
}
function balancerSwap(
SwapType swapType,
address assetIn,
bytes32[] memory poolIds,
address[] memory assets,
uint256 amount,
uint256 limit,
address recipient,
uint256 deadline
) internal returns (uint256) {
uint256 pathLength = poolIds.length;
int256[] memory limits = new int256[](pathLength + 1);
BatchSwapStep[] memory swaps = new BatchSwapStep[](pathLength);
{
bytes memory userData;
uint256 inIncrement;
uint256 outIncrement;
if (swapType == SwapType.EXACT_IN) outIncrement = 1;
else inIncrement = 1;
for (uint256 i; i < pathLength; ) {
unchecked {
swaps[i] = BatchSwapStep({
poolId: poolIds[i],
assetInIndex: i + inIncrement,
assetOutIndex: i + outIncrement,
amount: 0,
userData: userData
});
++i;
}
}
swaps[0].amount = amount;
}
SwapKind kind;
uint256 amountToApprove;
if (swapType == SwapType.EXACT_IN) {
kind = SwapKind.GIVEN_IN;
amountToApprove = amount;
limits[0] = toInt256(amount);
limits[pathLength] = -toInt256(limit);
} else {
kind = SwapKind.GIVEN_OUT;
amountToApprove = limit;
limits[0] = -toInt256(amount);
limits[pathLength] = toInt256(limit);
}
IERC20(assetIn).forceApprove(address(balancerVault), amountToApprove);
return
abs(
balancerVault.batchSwap(
kind,
swaps,
assets,
FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(recipient),
toInternalBalance: false
}),
limits,
deadline
)[pathLength]
);
}
function kyberSwap(
address assetIn,
uint256 amountIn,
uint256 minOut,
bytes memory payload
) internal returns (uint256) {
IERC20(assetIn).forceApprove(address(kyberRouter), amountIn);
(bool success, bytes memory result) = kyberRouter.call(payload);
if (!success) _revertBytes(result);
(uint256 returnAmount , ) = abi.decode(result, (uint256, uint256));
if (returnAmount < minOut) revert SwapAction__kyberSwap_slippageFailed();
return returnAmount;
}
function uniV3Swap(
SwapType swapType,
address assetIn,
uint256 amount,
uint256 limit,
address recipient,
uint256 deadline,
bytes memory args
) internal returns (uint256) {
if (swapType == SwapType.EXACT_IN) {
IERC20(assetIn).forceApprove(address(uniRouter), amount);
return
uniRouter.exactInput(
ExactInputParams({
path: args,
recipient: recipient,
amountIn: amount,
amountOutMinimum: limit,
deadline: deadline
})
);
} else {
IERC20(assetIn).forceApprove(address(uniRouter), limit);
return
uniRouter.exactOutput(
ExactOutputParams({
path: args,
recipient: recipient,
amountOut: amount,
amountInMaximum: limit,
deadline: deadline
})
);
}
}
function pendleJoin(address recipient, uint256 minOut, bytes memory data) internal returns (uint256 netLpOut) {
(
address market,
ApproxParams memory guessPtReceivedFromSy,
TokenInput memory input,
LimitOrderData memory limit
) = abi.decode(data, (address, ApproxParams, TokenInput, LimitOrderData));
if (input.tokenIn != address(0)) {
input.netTokenIn = IERC20(input.tokenIn).balanceOf(address(this));
IERC20(input.tokenIn).forceApprove(address(pendleRouter), input.netTokenIn);
}
(netLpOut, , ) = pendleRouter.addLiquiditySingleToken(
recipient,
market,
minOut,
guessPtReceivedFromSy,
input,
limit
);
}
function pendleExit(address recipient, uint256 minOut, bytes memory data) internal returns (uint256 retAmount) {
(address market, uint256 netLpIn, address tokenOut) = abi.decode(data, (address, uint256, address));
(IStandardizedYield SY, IPPrincipalToken PT, IPYieldToken YT) = IPMarket(market).readTokens();
if (recipient != address(this)) {
IPMarket(market).transferFrom(recipient, market, netLpIn);
} else {
IPMarket(market).transfer(market, netLpIn);
}
uint256 netSyToRedeem;
if (PT.isExpired()) {
(uint256 netSyRemoved, ) = IPMarket(market).burn(address(SY), address(YT), netLpIn);
uint256 netSyFromPt = YT.redeemPY(address(SY));
netSyToRedeem = netSyRemoved + netSyFromPt;
} else {
(uint256 netSyRemoved, uint256 netPtRemoved) = IPMarket(market).burn(address(SY), market, netLpIn);
bytes memory empty;
(uint256 netSySwappedOut, ) = IPMarket(market).swapExactPtForSy(address(SY), netPtRemoved, empty);
netSyToRedeem = netSyRemoved + netSySwappedOut;
}
return SY.redeem(recipient, netSyToRedeem, tokenOut, minOut, true);
}
function tranchessJoin(SwapParams memory swapParams) internal returns (uint256 retAmount) {
(address lpToken, uint256 baseDelta, uint256 quoteDelta, uint256 version) = abi.decode(
swapParams.args,
(address, uint256, uint256, uint256)
);
address baseAddress = IStableSwap(ILiquidityGauge(lpToken).stableSwap()).baseAddress();
address quoteAddress = IStableSwap(ILiquidityGauge(lpToken).stableSwap()).quoteAddress();
if (baseDelta != 0) {
IERC20(baseAddress).forceApprove(address(tranchessRouter), baseDelta);
}
if (quoteDelta != 0) {
IERC20(quoteAddress).forceApprove(address(tranchessRouter), quoteDelta);
}
tranchessRouter.addLiquidity(
baseAddress,
quoteAddress,
baseDelta,
quoteDelta,
swapParams.limit,
version,
swapParams.deadline
);
retAmount = IERC20(lpToken).balanceOf(address(this));
if (swapParams.recipient != address(this)) {
IERC20(lpToken).safeTransfer(swapParams.recipient, retAmount);
}
}
function tranchessExit(address recipient, uint256 minOut, bytes memory data) internal returns (uint256 retAmount) {
(uint256 version, address lpToken, uint256 lpIn) = abi.decode(data, (uint256, address, uint256));
IStableSwap stableSwap = IStableSwap(ILiquidityGauge(lpToken).stableSwap());
retAmount = stableSwap.removeQuoteLiquidity(version, lpIn, minOut);
if (recipient != address(this)) {
IERC20(stableSwap.quoteAddress()).safeTransfer(recipient, retAmount);
}
}
function spectra(SwapParams memory swapParams) internal returns (uint256 retAmount) {
(bytes memory commands, bytes[] memory inputs, address tokenOut, uint256 deadline) = abi.decode(
swapParams.args,
(bytes, bytes[], address, uint256)
);
uint256 balBefore = IERC20(tokenOut).balanceOf(swapParams.recipient);
(address tokenIn, uint256 amountIn) = abi.decode(inputs[0], (address, uint256));
IERC20(tokenIn).forceApprove(address(spectraRouter), amountIn);
spectraRouter.execute(commands, inputs, deadline);
retAmount = IERC20(tokenOut).balanceOf(swapParams.recipient) - balBefore;
}
function getSwapToken(SwapParams calldata swapParams) public pure returns (address token) {
if (swapParams.swapProtocol == SwapProtocol.BALANCER) {
(, address[] memory primarySwapPath) = abi.decode(swapParams.args, (bytes32[], address[]));
if (swapParams.swapType == SwapType.EXACT_OUT) {
token = primarySwapPath[0];
} else {
token = primarySwapPath[primarySwapPath.length - 1];
}
} else if (swapParams.swapProtocol == SwapProtocol.UNIV3) {
token = decodeLastToken(swapParams.args);
} else {
revert SwapAction__swap_notSupported();
}
}
function _revertBytes(bytes memory errMsg) internal pure {
if (errMsg.length != 0) {
assembly {
revert(add(32, errMsg), mload(errMsg))
}
}
revert SwapAction__revertBytes_emptyRevertBytes();
}
}
文件 51 的 52:TransferAction.sol
pragma solidity ^0.8.19;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ISignatureTransfer} from "permit2/interfaces/ISignatureTransfer.sol";
enum ApprovalType {
STANDARD,
PERMIT,
PERMIT2
}
struct PermitParams {
ApprovalType approvalType;
uint256 approvalAmount;
uint256 nonce;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
abstract contract TransferAction {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Permit;
address public constant permit2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
function _transferFrom(
address token,
address from,
address to,
uint256 amount,
PermitParams memory params
) internal {
if (params.approvalType == ApprovalType.PERMIT2) {
ISignatureTransfer(permit2).permitTransferFrom(
ISignatureTransfer.PermitTransferFrom({
permitted: ISignatureTransfer.TokenPermissions({token: token, amount: params.approvalAmount}),
nonce: params.nonce,
deadline: params.deadline
}),
ISignatureTransfer.SignatureTransferDetails({to: to, requestedAmount: amount}),
from,
bytes.concat(params.r, params.s, bytes1(params.v))
);
} else if (params.approvalType == ApprovalType.PERMIT) {
IERC20Permit(token).safePermit(
from,
to,
params.approvalAmount,
params.deadline,
params.v,
params.r,
params.s
);
IERC20(token).safeTransferFrom(from, to, amount);
} else {
IERC20(token).safeTransferFrom(from, to, amount);
}
}
}
文件 52 的 52:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
import "./IERC20Permit.sol";
{
"compilationTarget": {
"src/proxy/PositionActionTranchess.sol": "PositionActionTranchess"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": [
":@1inch/=lib/core-v3/node_modules/@1inch/",
":@aave/core-v3/=lib/aave-address-book/lib/aave-v3-core/",
":@aave/periphery-v3/=lib/aave-address-book/lib/aave-v3-periphery/",
":@chainlink/=lib/core-v3/node_modules/@chainlink/",
":@gearbox-protocol/core-v2/contracts/=lib/core-v2/contracts/",
":@gearbox-protocol/core-v3/contracts/=lib/core-v3/contracts/",
":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":@prb/test/=lib/prb-proxy/lib/prb-test/src/",
":aave-address-book/=lib/aave-address-book/src/",
":aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/",
":aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/",
":core-v2/=lib/core-v2/contracts/",
":core-v3/=lib/core-v3/contracts/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
":forge-std/=lib/forge-std/src/",
":hardhat-deploy/=node_modules/hardhat-deploy/",
":hardhat/=node_modules/hardhat/",
":layerzerolabs/=lib/layerzerolabs/contracts/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":pendle/=lib/pendle/contracts/",
":permit2/=lib/permit2/src/",
":prb-proxy/=lib/prb-proxy/src/",
":prb-test/=lib/prb-proxy/lib/prb-test/src/",
":solmate/=lib/permit2/lib/solmate/",
":tranchess/=lib/contract-core/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"flashlender_","type":"address"},{"internalType":"address","name":"swapAction_","type":"address"},{"internalType":"address","name":"poolAction_","type":"address"},{"internalType":"address","name":"vaultRegistry_","type":"address"},{"internalType":"address","name":"weth_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Action__revertBytes_emptyRevertBytes","type":"error"},{"inputs":[],"name":"Math__toInt256_overflow","type":"error"},{"inputs":[],"name":"PositionAction__borrow_InvalidAuxSwap","type":"error"},{"inputs":[],"name":"PositionAction__constructor_InvalidParam","type":"error"},{"inputs":[],"name":"PositionAction__decreaseLever_invalidAuxSwap","type":"error"},{"inputs":[],"name":"PositionAction__decreaseLever_invalidClosePositionPrimarySwap","type":"error"},{"inputs":[],"name":"PositionAction__decreaseLever_invalidPrimarySwap","type":"error"},{"inputs":[],"name":"PositionAction__decreaseLever_invalidResidualRecipient","type":"error"},{"inputs":[],"name":"PositionAction__deposit_InvalidAuxSwap","type":"error"},{"inputs":[],"name":"PositionAction__increaseLever_invalidAuxSwap","type":"error"},{"inputs":[],"name":"PositionAction__increaseLever_invalidPrimarySwap","type":"error"},{"inputs":[],"name":"PositionAction__onCreditFlashLoan__invalidSender","type":"error"},{"inputs":[],"name":"PositionAction__onFlashLoan__invalidInitiator","type":"error"},{"inputs":[],"name":"PositionAction__onFlashLoan__invalidSender","type":"error"},{"inputs":[],"name":"PositionAction__onlyDelegatecall","type":"error"},{"inputs":[],"name":"PositionAction__repay_InvalidAuxSwap","type":"error"},{"inputs":[],"name":"PositionAction__unregisteredVault","type":"error"},{"inputs":[],"name":"CALLBACK_SUCCESS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CALLBACK_SUCCESS_CREDIT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"creditor","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"}],"internalType":"struct CreditParams","name":"creditParams","type":"tuple"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"primarySwap","type":"tuple"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"components":[{"internalType":"enum Protocol","name":"protocol","type":"uint8"},{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct PoolActionParams","name":"auxAction","type":"tuple"}],"internalType":"struct LeverParams","name":"leverParams","type":"tuple"},{"internalType":"uint256","name":"subCollateral","type":"uint256"},{"internalType":"address","name":"residualRecipient","type":"address"}],"name":"decreaseLever","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"address","name":"targetToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"collateralizer","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"internalType":"struct CollateralParams","name":"collateralParams","type":"tuple"},{"components":[{"internalType":"enum ApprovalType","name":"approvalType","type":"uint8"},{"internalType":"uint256","name":"approvalAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"address","name":"targetToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"collateralizer","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"internalType":"struct CollateralParams","name":"collateralParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"creditor","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"}],"internalType":"struct CreditParams","name":"creditParams","type":"tuple"},{"components":[{"internalType":"enum ApprovalType","name":"approvalType","type":"uint8"},{"internalType":"uint256","name":"approvalAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"depositAndBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashlender","outputs":[{"internalType":"contract IFlashlender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"primarySwap","type":"tuple"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"components":[{"internalType":"enum Protocol","name":"protocol","type":"uint8"},{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct PoolActionParams","name":"auxAction","type":"tuple"}],"internalType":"struct LeverParams","name":"leverParams","type":"tuple"},{"internalType":"address","name":"upFrontToken","type":"address"},{"internalType":"uint256","name":"upFrontAmount","type":"uint256"},{"internalType":"address","name":"collateralizer","type":"address"},{"components":[{"internalType":"enum ApprovalType","name":"approvalType","type":"uint8"},{"internalType":"uint256","name":"approvalAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"increaseLever","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"},{"internalType":"bool[]","name":"delegateCall","type":"bool[]"}],"name":"multisend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onCreditFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"permit2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IPoolV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolAction","outputs":[{"internalType":"contract PoolAction","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"creditor","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"}],"internalType":"struct CreditParams","name":"creditParams","type":"tuple"},{"components":[{"internalType":"enum ApprovalType","name":"approvalType","type":"uint8"},{"internalType":"uint256","name":"approvalAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"self","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapAction","outputs":[{"internalType":"contract SwapAction","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultRegistry","outputs":[{"internalType":"contract IVaultRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"address","name":"targetToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"collateralizer","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"internalType":"struct CollateralParams","name":"collateralParams","type":"tuple"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"position","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"components":[{"internalType":"address","name":"targetToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"collateralizer","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"internalType":"struct CollateralParams","name":"collateralParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"creditor","type":"address"},{"components":[{"internalType":"enum SwapProtocol","name":"swapProtocol","type":"uint8"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"address","name":"assetIn","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"residualRecipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct SwapParams","name":"auxSwap","type":"tuple"}],"internalType":"struct CreditParams","name":"creditParams","type":"tuple"},{"components":[{"internalType":"enum ApprovalType","name":"approvalType","type":"uint8"},{"internalType":"uint256","name":"approvalAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"withdrawAndRepay","outputs":[],"stateMutability":"nonpayable","type":"function"}]