编译器
0.8.19+commit.7dd6d404
文件 1 的 17:AdapterBase.sol
pragma solidity 0.8.19;
import {AssetHelpers} from "../../../../../../utils/0.8.19/AssetHelpers.sol";
import {IIntegrationAdapter} from "../../../IIntegrationAdapter.sol";
import {IntegrationSelectors} from "../IntegrationSelectors.sol";
abstract contract AdapterBase is IIntegrationAdapter, IntegrationSelectors, AssetHelpers {
address internal immutable INTEGRATION_MANAGER;
modifier postActionIncomingAssetsTransferHandler(address _vaultProxy, bytes memory _assetData) {
_;
(,, address[] memory incomingAssets) = __decodeAssetData(_assetData);
__pushFullAssetBalances(_vaultProxy, incomingAssets);
}
modifier postActionSpendAssetsTransferHandler(address _vaultProxy, bytes memory _assetData) {
_;
(address[] memory spendAssets,,) = __decodeAssetData(_assetData);
__pushFullAssetBalances(_vaultProxy, spendAssets);
}
modifier onlyIntegrationManager() {
require(msg.sender == INTEGRATION_MANAGER, "Only the IntegrationManager can call this function");
_;
}
constructor(address _integrationManager) {
INTEGRATION_MANAGER = _integrationManager;
}
function __decodeAssetData(bytes memory _assetData)
internal
pure
returns (address[] memory spendAssets_, uint256[] memory spendAssetAmounts_, address[] memory incomingAssets_)
{
return abi.decode(_assetData, (address[], uint256[], address[]));
}
function getIntegrationManager() external view returns (address integrationManager_) {
return INTEGRATION_MANAGER;
}
}
文件 2 的 17: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);
}
}
}
文件 3 的 17:AssetHelpers.sol
pragma solidity 0.8.19;
import {IERC20} from "../../external-interfaces/IERC20.sol";
import {WrappedSafeERC20 as SafeERC20} from "../../utils/0.8.19/open-zeppelin/WrappedSafeERC20.sol";
abstract contract AssetHelpers {
using SafeERC20 for IERC20;
function __aggregateAssetAmounts(address[] memory _rawAssets, uint256[] memory _rawAmounts)
internal
pure
returns (address[] memory aggregatedAssets_, uint256[] memory aggregatedAmounts_)
{
if (_rawAssets.length == 0) {
return (aggregatedAssets_, aggregatedAmounts_);
}
uint256 aggregatedAssetCount = 1;
for (uint256 i = 1; i < _rawAssets.length; i++) {
bool contains;
for (uint256 j; j < i; j++) {
if (_rawAssets[i] == _rawAssets[j]) {
contains = true;
break;
}
}
if (!contains) {
aggregatedAssetCount++;
}
}
aggregatedAssets_ = new address[](aggregatedAssetCount);
aggregatedAmounts_ = new uint256[](aggregatedAssetCount);
uint256 aggregatedAssetIndex;
for (uint256 i; i < _rawAssets.length; i++) {
bool contains;
for (uint256 j; j < aggregatedAssetIndex; j++) {
if (_rawAssets[i] == aggregatedAssets_[j]) {
contains = true;
aggregatedAmounts_[j] += _rawAmounts[i];
break;
}
}
if (!contains) {
aggregatedAssets_[aggregatedAssetIndex] = _rawAssets[i];
aggregatedAmounts_[aggregatedAssetIndex] = _rawAmounts[i];
aggregatedAssetIndex++;
}
}
return (aggregatedAssets_, aggregatedAmounts_);
}
function __approveAssetMaxAsNeeded(address _asset, address _target, uint256 _neededAmount) internal {
uint256 allowance = IERC20(_asset).allowance(address(this), _target);
if (allowance < _neededAmount) {
if (allowance > 0) {
IERC20(_asset).safeApprove(_target, 0);
}
IERC20(_asset).safeApprove(_target, type(uint256).max);
}
}
function __pushFullAssetBalance(address _target, address _asset) internal returns (uint256 amountTransferred_) {
amountTransferred_ = IERC20(_asset).balanceOf(address(this));
if (amountTransferred_ > 0) {
IERC20(_asset).safeTransfer(_target, amountTransferred_);
}
return amountTransferred_;
}
function __pushFullAssetBalances(address _target, address[] memory _assets)
internal
returns (uint256[] memory amountsTransferred_)
{
amountsTransferred_ = new uint256[](_assets.length);
for (uint256 i; i < _assets.length; i++) {
IERC20 assetContract = IERC20(_assets[i]);
amountsTransferred_[i] = assetContract.balanceOf(address(this));
if (amountsTransferred_[i] > 0) {
assetContract.safeTransfer(_target, amountsTransferred_[i]);
}
}
return amountsTransferred_;
}
}
文件 4 的 17: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);
}
文件 5 的 17:IIntegrationAdapter.sol
pragma solidity >=0.6.0 <0.9.0;
import {IIntegrationManager} from "./IIntegrationManager.sol";
interface IIntegrationAdapter {
function parseAssetsForAction(address _vaultProxy, bytes4 _selector, bytes calldata _encodedCallArgs)
external
view
returns (
IIntegrationManager.SpendAssetsHandleType spendAssetsHandleType_,
address[] memory spendAssets_,
uint256[] memory spendAssetAmounts_,
address[] memory incomingAssets_,
uint256[] memory minIncomingAssetAmounts_
);
}
文件 6 的 17:IIntegrationManager.sol
pragma solidity >=0.6.0 <0.9.0;
interface IIntegrationManager {
enum SpendAssetsHandleType {
None,
Approve,
Transfer
}
function getPolicyManager() external view returns (address policyManager_);
}
文件 7 的 17:IPendleV2Adapter.sol
pragma solidity >=0.6.0 <0.9.0;
import {IPendleV2Market} from "../../../../../../external-interfaces/IPendleV2Market.sol";
import {IPendleV2Router} from "../../../../../../external-interfaces/IPendleV2Router.sol";
interface IPendleV2Adapter {
enum Action {
BuyPrincipalToken,
SellPrincipalToken,
AddLiquidity,
RemoveLiquidity
}
struct AddLiquidityActionArgs {
IPendleV2Market market;
address depositTokenAddress;
uint256 depositTokenAmount;
IPendleV2Router.ApproxParams guessPtReceived;
uint256 minLpAmount;
}
struct BuyPrincipalTokenActionArgs {
IPendleV2Market market;
address depositTokenAddress;
uint256 depositTokenAmount;
IPendleV2Router.ApproxParams guessPtOut;
uint256 minPtAmount;
}
struct RemoveLiquidityActionArgs {
IPendleV2Market market;
address withdrawalTokenAddress;
uint256 lpAmount;
uint256 minSyOut;
uint256 minWithdrawalTokenAmount;
}
struct SellPrincipalTokenActionArgs {
IPendleV2Market market;
address withdrawalTokenAddress;
uint256 ptAmount;
uint256 minWithdrawalTokenAmount;
}
}
文件 8 的 17:IPendleV2Market.sol
import {IPendleV2PrincipalToken} from "./IPendleV2PrincipalToken.sol";
import {IPendleV2StandardizedYield} from "./IPendleV2StandardizedYield.sol";
pragma solidity >=0.6.0 <0.9.0;
interface IPendleV2Market {
function factory() external view returns (address factoryAddress_);
function getRewardTokens() external view returns (address[] memory rewardTokenAddresses_);
function readTokens()
external
view
returns (IPendleV2StandardizedYield sy_, IPendleV2PrincipalToken pt_, address yt_);
function redeemRewards(address _user) external returns (uint256[] memory rewardAmounts_);
}
文件 9 的 17:IPendleV2PrincipalToken.sol
pragma solidity >=0.6.0 <0.9.0;
interface IPendleV2PrincipalToken {
function SY() external view returns (address syTokenAddress_);
function isExpired() external view returns (bool isExpired_);
}
文件 10 的 17:IPendleV2Router.sol
pragma solidity >=0.6.0 <0.9.0;
interface IPendleV2Router {
struct ApproxParams {
uint256 guessMin;
uint256 guessMax;
uint256 guessOffchain;
uint256 maxIteration;
uint256 eps;
}
struct FillOrderParams {
Order order;
bytes signature;
uint256 makingAmount;
}
struct LimitOrderData {
address limitRouter;
uint256 epsSkipMarket;
FillOrderParams[] normalFills;
FillOrderParams[] flashFills;
bytes optData;
}
struct Order {
uint256 salt;
uint256 expiry;
uint256 nonce;
OrderType orderType;
address token;
address YT;
address maker;
address receiver;
uint256 makingAmount;
uint256 lnImpliedRate;
uint256 failSafeRate;
bytes permit;
}
enum OrderType {
SY_FOR_PT,
PT_FOR_SY,
SY_FOR_YT,
YT_FOR_SY
}
function addLiquiditySingleSy(
address _receiver,
address _market,
uint256 _netSyIn,
uint256 _minLpOut,
ApproxParams calldata _guessPtReceivedFromSy,
LimitOrderData calldata _limit
) external returns (uint256 netLpOut_, uint256 netSyFee_);
function removeLiquiditySingleSy(
address _receiver,
address _market,
uint256 _netLpToRemove,
uint256 _minSyOut,
LimitOrderData calldata _limit
) external returns (uint256 netSyOut_, uint256 netSyFee_);
function swapExactSyForPt(
address _receiver,
address _market,
uint256 _exactSyIn,
uint256 _minPtOut,
ApproxParams calldata _guessPtOut,
LimitOrderData calldata _limit
) external returns (uint256 netPtOut_, uint256 netSyFee_);
function swapExactPtForSy(
address _receiver,
address _market,
uint256 _exactPtIn,
uint256 _minSyOut,
LimitOrderData calldata _limit
) external returns (uint256 netSyOut_, uint256 netSyFee_);
function redeemPyToSy(address _receiver, address _YT, uint256 _netPyIn, uint256 _minSyOut)
external
returns (uint256 netSyOut_);
}
文件 11 的 17:IPendleV2StandardizedYield.sol
pragma solidity >=0.6.0 <0.9.0;
interface IPendleV2StandardizedYield {
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 yieldToken() external view returns (address yieldTokenAddress_);
}
文件 12 的 17:IWETH.sol
pragma solidity >=0.6.0 <0.9.0;
interface IWETH {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 13 的 17:IntegrationSelectors.sol
pragma solidity >=0.6.0 <0.9.0;
abstract contract IntegrationSelectors {
bytes4 internal constant ACTION_SELECTOR = bytes4(keccak256("action(address,bytes,bytes)"));
bytes4 internal constant TAKE_MULTIPLE_ORDERS_SELECTOR =
bytes4(keccak256("takeMultipleOrders(address,bytes,bytes)"));
bytes4 internal constant TAKE_ORDER_SELECTOR = bytes4(keccak256("takeOrder(address,bytes,bytes)"));
bytes4 internal constant LEND_SELECTOR = bytes4(keccak256("lend(address,bytes,bytes)"));
bytes4 internal constant REDEEM_SELECTOR = bytes4(keccak256("redeem(address,bytes,bytes)"));
bytes4 internal constant STAKE_SELECTOR = bytes4(keccak256("stake(address,bytes,bytes)"));
bytes4 internal constant UNSTAKE_SELECTOR = bytes4(keccak256("unstake(address,bytes,bytes)"));
bytes4 internal constant CLAIM_REWARDS_SELECTOR = bytes4(keccak256("claimRewards(address,bytes,bytes)"));
bytes4 internal constant LEND_AND_STAKE_SELECTOR = bytes4(keccak256("lendAndStake(address,bytes,bytes)"));
bytes4 internal constant UNSTAKE_AND_REDEEM_SELECTOR = bytes4(keccak256("unstakeAndRedeem(address,bytes,bytes)"));
bytes4 internal constant WRAP_SELECTOR = bytes4(keccak256("wrap(address,bytes,bytes)"));
bytes4 internal constant UNWRAP_SELECTOR = bytes4(keccak256("unwrap(address,bytes,bytes)"));
bytes4 internal constant TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,bytes,bytes)"));
}
文件 14 的 17:PendleV2Adapter.sol
pragma solidity 0.8.19;
import {IPendleV2PrincipalToken} from "../../../../../external-interfaces/IPendleV2PrincipalToken.sol";
import {IPendleV2Router} from "../../../../../external-interfaces/IPendleV2Router.sol";
import {IPendleV2StandardizedYield} from "../../../../../external-interfaces/IPendleV2StandardizedYield.sol";
import {IWETH} from "../../../../../external-interfaces/IWETH.sol";
import {IIntegrationManager} from "../../IIntegrationManager.sol";
import {AdapterBase} from "../utils/0.8.19/AdapterBase.sol";
import {IPendleV2Adapter} from "./interfaces/IPendleV2Adapter.sol";
contract PendleV2Adapter is IPendleV2Adapter, AdapterBase {
address private constant NATIVE_ASSET_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address private constant PENDLE_NATIVE_ASSET_ADDRESS = address(0);
IPendleV2Router private immutable PENDLE_ROUTER;
IWETH private immutable WRAPPED_NATIVE_ASSET;
error PendleV2Adapter__InvalidAction();
constructor(address _integrationManager, address _pendleRouterAddress, address _wrappedNativeAssetAddress)
AdapterBase(_integrationManager)
{
PENDLE_ROUTER = IPendleV2Router(_pendleRouterAddress);
WRAPPED_NATIVE_ASSET = IWETH(_wrappedNativeAssetAddress);
}
receive() external payable {}
function action(address _vaultProxyAddress, bytes calldata _actionData, bytes calldata)
external
onlyIntegrationManager
{
(IPendleV2Adapter.Action actionId, bytes memory encodedActionArgs) = abi.decode(_actionData, (Action, bytes));
if (actionId == Action.BuyPrincipalToken) {
__buyPrincipalToken({
_vaultProxyAddress: _vaultProxyAddress,
_actionArgs: abi.decode(encodedActionArgs, (BuyPrincipalTokenActionArgs))
});
} else if (actionId == Action.SellPrincipalToken) {
__sellPrincipalToken({
_vaultProxyAddress: _vaultProxyAddress,
_actionArgs: abi.decode(encodedActionArgs, (SellPrincipalTokenActionArgs))
});
} else if (actionId == Action.AddLiquidity) {
__addLiquidity({
_vaultProxyAddress: _vaultProxyAddress,
_actionArgs: abi.decode(encodedActionArgs, (AddLiquidityActionArgs))
});
} else if (actionId == Action.RemoveLiquidity) {
__removeLiquidity({
_vaultProxyAddress: _vaultProxyAddress,
_actionArgs: abi.decode(encodedActionArgs, (RemoveLiquidityActionArgs))
});
} else {
revert PendleV2Adapter__InvalidAction();
}
}
function __addLiquidity(address _vaultProxyAddress, AddLiquidityActionArgs memory _actionArgs) private {
(IPendleV2StandardizedYield syToken,,) = _actionArgs.market.readTokens();
uint256 syTokenAmount = __mintSYToken({
_syToken: syToken,
_minSyTokenAmount: 0,
_depositTokenAddressInput: _actionArgs.depositTokenAddress,
_depositTokenAmount: _actionArgs.depositTokenAmount,
_receiver: address(this)
});
__approveAssetMaxAsNeeded({
_asset: address(syToken),
_target: address(PENDLE_ROUTER),
_neededAmount: syTokenAmount
});
IPendleV2Router.LimitOrderData memory limit;
PENDLE_ROUTER.addLiquiditySingleSy({
_receiver: _vaultProxyAddress,
_market: address(_actionArgs.market),
_netSyIn: syTokenAmount,
_minLpOut: _actionArgs.minLpAmount,
_guessPtReceivedFromSy: _actionArgs.guessPtReceived,
_limit: limit
});
}
function __buyPrincipalToken(address _vaultProxyAddress, BuyPrincipalTokenActionArgs memory _actionArgs) private {
(IPendleV2StandardizedYield syToken,,) = _actionArgs.market.readTokens();
uint256 syTokenAmount = __mintSYToken({
_syToken: syToken,
_minSyTokenAmount: 0,
_depositTokenAddressInput: _actionArgs.depositTokenAddress,
_depositTokenAmount: _actionArgs.depositTokenAmount,
_receiver: address(this)
});
__approveAssetMaxAsNeeded({
_asset: address(syToken),
_target: address(PENDLE_ROUTER),
_neededAmount: syTokenAmount
});
IPendleV2Router.LimitOrderData memory limit;
PENDLE_ROUTER.swapExactSyForPt({
_receiver: _vaultProxyAddress,
_market: address(_actionArgs.market),
_exactSyIn: syTokenAmount,
_minPtOut: _actionArgs.minPtAmount,
_guessPtOut: _actionArgs.guessPtOut,
_limit: limit
});
}
function __removeLiquidity(address _vaultProxyAddress, RemoveLiquidityActionArgs memory _actionArgs) private {
__approveAssetMaxAsNeeded({
_asset: address(_actionArgs.market),
_target: address(PENDLE_ROUTER),
_neededAmount: _actionArgs.lpAmount
});
IPendleV2Router.LimitOrderData memory limit;
(uint256 syTokenAmount,) = PENDLE_ROUTER.removeLiquiditySingleSy({
_receiver: address(this),
_market: address(_actionArgs.market),
_netLpToRemove: _actionArgs.lpAmount,
_minSyOut: _actionArgs.minSyOut,
_limit: limit
});
(IPendleV2StandardizedYield syToken,,) = _actionArgs.market.readTokens();
__redeemSYToken({
_syToken: syToken,
_syTokenAmount: syTokenAmount,
_withdrawalTokenAddressInput: _actionArgs.withdrawalTokenAddress,
_minWithdrawalTokenAmount: _actionArgs.minWithdrawalTokenAmount,
_receiver: _vaultProxyAddress
});
}
function __sellPrincipalToken(address _vaultProxyAddress, SellPrincipalTokenActionArgs memory _actionArgs)
private
{
(IPendleV2StandardizedYield syToken, IPendleV2PrincipalToken principalToken, address yieldTokenAddress) =
_actionArgs.market.readTokens();
__approveAssetMaxAsNeeded({
_asset: address(principalToken),
_target: address(PENDLE_ROUTER),
_neededAmount: _actionArgs.ptAmount
});
uint256 netSyOut;
if (principalToken.isExpired()) {
netSyOut = PENDLE_ROUTER.redeemPyToSy({
_receiver: address(this),
_YT: yieldTokenAddress,
_netPyIn: _actionArgs.ptAmount,
_minSyOut: 0
});
} else {
IPendleV2Router.LimitOrderData memory limit;
(netSyOut,) = PENDLE_ROUTER.swapExactPtForSy({
_receiver: address(this),
_market: address(_actionArgs.market),
_exactPtIn: _actionArgs.ptAmount,
_minSyOut: 0,
_limit: limit
});
}
__redeemSYToken({
_syToken: syToken,
_syTokenAmount: netSyOut,
_withdrawalTokenAddressInput: _actionArgs.withdrawalTokenAddress,
_minWithdrawalTokenAmount: _actionArgs.minWithdrawalTokenAmount,
_receiver: _vaultProxyAddress
});
}
function parseAssetsForAction(address, bytes4 _selector, bytes calldata _actionData)
external
view
override
returns (
IIntegrationManager.SpendAssetsHandleType spendAssetsHandleType_,
address[] memory spendAssets_,
uint256[] memory spendAssetAmounts_,
address[] memory incomingAssets_,
uint256[] memory minIncomingAssetAmounts_
)
{
if (_selector != ACTION_SELECTOR) revert PendleV2Adapter__InvalidAction();
spendAssets_ = new address[](1);
spendAssetAmounts_ = new uint256[](1);
incomingAssets_ = new address[](1);
minIncomingAssetAmounts_ = new uint256[](1);
(IPendleV2Adapter.Action actionId, bytes memory encodedActionArgs) = abi.decode(_actionData, (Action, bytes));
if (actionId == Action.BuyPrincipalToken) {
BuyPrincipalTokenActionArgs memory actionArgs = abi.decode(encodedActionArgs, (BuyPrincipalTokenActionArgs));
(, IPendleV2PrincipalToken principalToken,) = actionArgs.market.readTokens();
spendAssets_[0] = __parseAssetInputForEnzyme(actionArgs.depositTokenAddress);
spendAssetAmounts_[0] = actionArgs.depositTokenAmount;
incomingAssets_[0] = address(principalToken);
minIncomingAssetAmounts_[0] = actionArgs.minPtAmount;
} else if (actionId == Action.SellPrincipalToken) {
SellPrincipalTokenActionArgs memory actionArgs =
abi.decode(encodedActionArgs, (SellPrincipalTokenActionArgs));
(, IPendleV2PrincipalToken principalToken,) = actionArgs.market.readTokens();
spendAssets_[0] = address(principalToken);
spendAssetAmounts_[0] = actionArgs.ptAmount;
incomingAssets_[0] = __parseAssetInputForEnzyme(actionArgs.withdrawalTokenAddress);
minIncomingAssetAmounts_[0] = actionArgs.minWithdrawalTokenAmount;
} else if (actionId == Action.AddLiquidity) {
AddLiquidityActionArgs memory actionArgs = abi.decode(encodedActionArgs, (AddLiquidityActionArgs));
spendAssets_[0] = __parseAssetInputForEnzyme(actionArgs.depositTokenAddress);
spendAssetAmounts_[0] = actionArgs.depositTokenAmount;
incomingAssets_[0] = address(actionArgs.market);
minIncomingAssetAmounts_[0] = actionArgs.minLpAmount;
} else if (actionId == Action.RemoveLiquidity) {
RemoveLiquidityActionArgs memory actionArgs = abi.decode(encodedActionArgs, (RemoveLiquidityActionArgs));
spendAssets_[0] = address(actionArgs.market);
spendAssetAmounts_[0] = actionArgs.lpAmount;
incomingAssets_[0] = __parseAssetInputForEnzyme(actionArgs.withdrawalTokenAddress);
minIncomingAssetAmounts_[0] = actionArgs.minWithdrawalTokenAmount;
}
return (
IIntegrationManager.SpendAssetsHandleType.Transfer,
spendAssets_,
spendAssetAmounts_,
incomingAssets_,
minIncomingAssetAmounts_
);
}
function __mintSYToken(
IPendleV2StandardizedYield _syToken,
uint256 _minSyTokenAmount,
address _depositTokenAddressInput,
uint256 _depositTokenAmount,
address _receiver
) private returns (uint256 syTokenAmount_) {
uint256 nativeAssetDepositValue;
address pendleDepositTokenAddress = __parseAssetInputForPendle(_depositTokenAddressInput);
if (pendleDepositTokenAddress == PENDLE_NATIVE_ASSET_ADDRESS) {
WRAPPED_NATIVE_ASSET.withdraw(_depositTokenAmount);
nativeAssetDepositValue = _depositTokenAmount;
} else {
__approveAssetMaxAsNeeded({
_asset: pendleDepositTokenAddress,
_target: address(_syToken),
_neededAmount: _depositTokenAmount
});
}
syTokenAmount_ = _syToken.deposit{value: nativeAssetDepositValue}({
_receiver: _receiver,
_tokenIn: pendleDepositTokenAddress,
_amountTokenToDeposit: _depositTokenAmount,
_minSharesOut: _minSyTokenAmount
});
return syTokenAmount_;
}
function __parseAssetInputForEnzyme(address _assetAddress) private view returns (address parsedAssetAddress_) {
return _assetAddress == NATIVE_ASSET_ADDRESS ? address(WRAPPED_NATIVE_ASSET) : _assetAddress;
}
function __parseAssetInputForPendle(address _assetAddress) private pure returns (address parsedAssetAddress_) {
return _assetAddress == NATIVE_ASSET_ADDRESS ? PENDLE_NATIVE_ASSET_ADDRESS : _assetAddress;
}
function __redeemSYToken(
IPendleV2StandardizedYield _syToken,
uint256 _syTokenAmount,
address _withdrawalTokenAddressInput,
uint256 _minWithdrawalTokenAmount,
address _receiver
) private {
_syToken.redeem({
_receiver: _receiver,
_amountSharesToRedeem: _syTokenAmount,
_tokenOut: __parseAssetInputForPendle(_withdrawalTokenAddressInput),
_minTokenOut: _minWithdrawalTokenAmount,
_burnFromInternalBalance: false
});
}
}
文件 15 的 17:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 16 的 17:WrappedSafeERC20.sol
pragma solidity 0.8.19;
import {IERC20 as OpenZeppelinIERC20} from "openzeppelin-solc-0.8/token/ERC20/IERC20.sol";
import {SafeERC20 as OpenZeppelinSafeERC20} from "openzeppelin-solc-0.8/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "../../../external-interfaces/IERC20.sol";
library WrappedSafeERC20 {
function safeApprove(IERC20 _token, address _spender, uint256 _value) internal {
OpenZeppelinSafeERC20.safeApprove({token: __castToken(_token), spender: _spender, value: _value});
}
function safeDecreaseAllowance(IERC20 _token, address _spender, uint256 _value) internal {
OpenZeppelinSafeERC20.safeDecreaseAllowance({token: __castToken(_token), spender: _spender, value: _value});
}
function safeIncreaseAllowance(IERC20 _token, address _spender, uint256 _value) internal {
OpenZeppelinSafeERC20.safeIncreaseAllowance({token: __castToken(_token), spender: _spender, value: _value});
}
function safeTransfer(IERC20 _token, address _to, uint256 _value) internal {
OpenZeppelinSafeERC20.safeTransfer({token: __castToken(_token), to: _to, value: _value});
}
function safeTransferFrom(IERC20 _token, address _from, address _to, uint256 _value) internal {
OpenZeppelinSafeERC20.safeTransferFrom({token: __castToken(_token), from: _from, to: _to, value: _value});
}
function __castToken(IERC20 _token) private pure returns (OpenZeppelinIERC20 token_) {
return OpenZeppelinIERC20(address(_token));
}
}
文件 17 的 17:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/release/extensions/integration-manager/integrations/adapters/PendleV2Adapter.sol": "PendleV2Adapter"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": false,
"bytecodeHash": "none"
},
"optimizer": {
"details": {
"constantOptimizer": true,
"cse": true,
"deduplicate": true,
"inliner": true,
"jumpdestRemover": true,
"orderLiterals": true,
"peephole": true,
"yul": false
},
"runs": 200
},
"remappings": [
":@openzeppelin/contracts/=lib/openzeppelin-solc-0.6/contracts/",
":@uniswap/v3-core/=lib/uniswap-v3-core/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":morpho-blue/=lib/morpho-blue/src/libraries/",
":openzeppelin-solc-0.6/=lib/openzeppelin-solc-0.6/contracts/",
":openzeppelin-solc-0.7/=lib/openzeppelin-solc-0.7/contracts/",
":openzeppelin-solc-0.8/=lib/openzeppelin-solc-0.8/contracts/",
":uniswap-v3-core-0.8/=lib/uniswap-v3-core-0.8/",
":uniswap-v3-core/=lib/uniswap-v3-core/",
":uniswap-v3-periphery/=lib/uniswap-v3-periphery/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"_integrationManager","type":"address"},{"internalType":"address","name":"_pendleRouterAddress","type":"address"},{"internalType":"address","name":"_wrappedNativeAssetAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"PendleV2Adapter__InvalidAction","type":"error"},{"inputs":[{"internalType":"address","name":"_vaultProxyAddress","type":"address"},{"internalType":"bytes","name":"_actionData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"action","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getIntegrationManager","outputs":[{"internalType":"address","name":"integrationManager_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes4","name":"_selector","type":"bytes4"},{"internalType":"bytes","name":"_actionData","type":"bytes"}],"name":"parseAssetsForAction","outputs":[{"internalType":"enum IIntegrationManager.SpendAssetsHandleType","name":"spendAssetsHandleType_","type":"uint8"},{"internalType":"address[]","name":"spendAssets_","type":"address[]"},{"internalType":"uint256[]","name":"spendAssetAmounts_","type":"uint256[]"},{"internalType":"address[]","name":"incomingAssets_","type":"address[]"},{"internalType":"uint256[]","name":"minIncomingAssetAmounts_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]