Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions packages/router/contracts/adapters/PendlePtToAssetAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ contract PendlePtToAssetAdapter is IMarginlyAdapter, Ownable2Step {
uint256 private constant MAX_ITERATIONS = 10;

mapping(address => mapping(address => PendleMarketData)) public getMarketData;
uint256 private callbackAmountIn;

event NewPair(address indexed ptToken, address indexed asset, address pendleMarket, uint8 slippage);

Expand Down Expand Up @@ -120,7 +121,10 @@ contract PendlePtToAssetAdapter is IMarginlyAdapter, Ownable2Step {
} else {
// this clause is realized when pt tokens is output
// we need to mint SY from Asset and send to pendle
_pendleMintSy(marketData, msg.sender, uint256(-syToAccount), data);
(, uint256 amountIn) = _pendleMintSy(marketData, msg.sender, uint256(-syToAccount), data);
if (data.isExactOutput) {
callbackAmountIn = amountIn;
}
}
}

Expand Down Expand Up @@ -203,10 +207,16 @@ contract PendlePtToAssetAdapter is IMarginlyAdapter, Ownable2Step {
SafeERC20.safeTransfer(marketData.asset, recipient, amountOut);
} else {
// Sy to Pt -> in callback mint Sy from Asset and send to pendleMarket
(amountIn, ) = marketData.market.swapSyForExactPt(recipient, amountOut, abi.encode(swapCallbackData));
marketData.market.swapSyForExactPt(recipient, amountOut, abi.encode(swapCallbackData));
amountIn = _getAmountIn();
}
}

function _getAmountIn() private returns (uint256 amountIn) {
amountIn = callbackAmountIn;
delete callbackAmountIn;
}

function _swapExactInputPostMaturity(
PendleMarketData memory marketData,
address recipient,
Expand Down Expand Up @@ -310,19 +320,19 @@ contract PendlePtToAssetAdapter is IMarginlyAdapter, Ownable2Step {
address recipient,
uint256 syAmount,
CallbackData memory data
) private returns (uint256 syMinted) {
) private returns (uint256 syMinted, uint256 actualAssetIn) {
// Calculate amount of asset needed to mint syAmount
uint256 estimatedAssetIn = _syToAssetUpForDeposit(marketData, syAmount);
actualAssetIn = _syToAssetUpForDeposit(marketData, syAmount);

if (data.isExactOutput) {
//transfer estimatedAssetIn of Asset to adapter
IMarginlyRouter(data.router).adapterCallback(address(this), estimatedAssetIn, data.adapterCallbackData);
IMarginlyRouter(data.router).adapterCallback(address(this), actualAssetIn, data.adapterCallbackData);
}
SafeERC20.forceApprove(marketData.asset, address(marketData.sy), estimatedAssetIn);
SafeERC20.forceApprove(marketData.asset, address(marketData.sy), actualAssetIn);
syMinted = IStandardizedYield(marketData.sy).deposit(
address(this),
address(marketData.asset),
estimatedAssetIn,
actualAssetIn,
syAmount
);

Expand Down
104 changes: 93 additions & 11 deletions packages/router/test/int/PendleCurveNgAdapterEBTC.eth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
PendleCurveNgAdapter,
PendleCurveNgAdapter__factory,
} from '../../typechain-types';
import { constructSwap, Dex, showGasUsage, SWAP_ONE, resetFork } from '../shared/utils';
import { constructSwap, Dex, showGasUsage, SWAP_ONE, resetFork, assertSwapEvent } from '../shared/utils';
import { EthAddress } from '@marginly/common';
import { formatUnits, parseUnits } from 'ethers/lib/utils';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
Expand Down Expand Up @@ -124,6 +124,18 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
const WBTCBalanceAfter = await WBTC.balanceOf(user.address);
console.log(`WBTCBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceBefore.sub(WBTCBalanceAfter)).to.be.lessThanOrEqual(WBTCSwapAmount);

await assertSwapEvent(
{
isExactInput: true,
tokenIn: WBTC.address,
tokenOut: ptToken.address,
amountIn: WBTCSwapAmount,
amountOut: ptBalanceAfter.sub(ptBalanceBefore),
},
router,
tx
);
});

it('WBTC to PT-eBTC exact output', async () => {
Expand Down Expand Up @@ -152,6 +164,18 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
console.log(`WBTCBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceBefore).to.be.greaterThan(WBTCBalanceAfter);

await assertSwapEvent(
{
isExactInput: false,
tokenIn: WBTC.address,
tokenOut: ptToken.address,
amountIn: WBTCBalanceBefore.sub(WBTCBalanceAfter),
amountOut: ptBalanceAfter.sub(ptBalanceBefore),
},
router,
tx
);

const ebtcOnAdapter = await ebtc.balanceOf(pendleCurveAdapter.address);
console.log(`ebtc stays on adapter: ${formatUnits(ebtcOnAdapter, await ebtc.decimals())} ${await ebtc.symbol()}`);
});
Expand Down Expand Up @@ -182,6 +206,18 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
console.log(`WBTCBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceBefore).to.be.greaterThan(WBTCBalanceAfter);

await assertSwapEvent(
{
isExactInput: false,
tokenIn: WBTC.address,
tokenOut: ptToken.address,
amountIn: WBTCBalanceBefore.sub(WBTCBalanceAfter),
amountOut: ptBalanceAfter.sub(ptBalanceBefore),
},
router,
tx
);

const ebtcOnAdapter = await ebtc.balanceOf(pendleCurveAdapter.address);
console.log(`ebtc stays on adapter: ${formatUnits(ebtcOnAdapter, await ebtc.decimals())} ${await ebtc.symbol()}`);
});
Expand All @@ -191,10 +227,8 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
console.log(
`ptBalanceBefore: ${formatUnits(ptBalanceBefore, await ptToken.decimals())} ${await ptToken.symbol()}`
);
const sUSDeBalanceBefore = await WBTC.balanceOf(user.address);
console.log(
`WBTCBalanceBefore: ${formatUnits(sUSDeBalanceBefore, await WBTC.decimals())} ${await WBTC.symbol()}`
);
const WBTCBalanceBefore = await WBTC.balanceOf(user.address);
console.log(`WBTCBalanceBefore: ${formatUnits(WBTCBalanceBefore, await WBTC.decimals())} ${await WBTC.symbol()}`);
const swapCalldata = constructSwap([Dex.PendleCurve], [SWAP_ONE]);
const ptIn = parseUnits('0.1', 8);
await ptToken.connect(user).approve(router.address, ptIn);
Expand All @@ -204,9 +238,21 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
const ptBalanceAfter = await ptToken.balanceOf(user.address);
console.log(`ptBalanceAfter: ${formatUnits(ptBalanceAfter, await ptToken.decimals())} ${await ptToken.symbol()}`);
expect(ptBalanceBefore.sub(ptBalanceAfter)).to.be.eq(ptIn);
const sUsdeBalanceAfter = await WBTC.balanceOf(user.address);
console.log(`WBTCBalanceAfter: ${formatUnits(sUsdeBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(sUsdeBalanceAfter).to.be.greaterThan(sUSDeBalanceBefore);
const WBTCBalanceAfter = await WBTC.balanceOf(user.address);
console.log(`WBTCBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceAfter).to.be.greaterThan(WBTCBalanceBefore);

await assertSwapEvent(
{
isExactInput: true,
tokenIn: ptToken.address,
tokenOut: WBTC.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: WBTCBalanceAfter.sub(WBTCBalanceBefore),
},
router,
tx
);
});

it('PT-eBTC to WBTC exact output', async () => {
Expand Down Expand Up @@ -236,6 +282,18 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
console.log(
`WBTCBalanceOnAdapter: ${formatUnits(WBTCBalanceOnAdapter, await WBTC.decimals())} ${await WBTC.symbol()}`
);

await assertSwapEvent(
{
isExactInput: false,
tokenIn: ptToken.address,
tokenOut: WBTC.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: WBTCBalanceAfter.sub(WBTCBalanceBefore),
},
router,
tx
);
});
});

Expand Down Expand Up @@ -344,16 +402,28 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
const WBTCBalanceAfter = await WBTC.balanceOf(user.address);
console.log(`WBTCBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceAfter).to.be.greaterThan(WBTCBalanceBefore);

await assertSwapEvent(
{
isExactInput: true,
tokenIn: ptToken.address,
tokenOut: WBTC.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: WBTCBalanceAfter.sub(WBTCBalanceBefore),
},
router,
tx
);
});

it('PT-eBTC to WBTC exact output', async () => {
const ptBalanceBefore = await ptToken.balanceOf(user.address);
console.log(
`ptBalanceBefore: ${formatUnits(ptBalanceBefore, await ptToken.decimals())} ${await ptToken.symbol()}`
);
const sUsdeBalanceBefore = await WBTC.balanceOf(user.address);
const WBTCBalanceBefore = await WBTC.balanceOf(user.address);
console.log(
`sUsdeBalanceBefore: ${formatUnits(sUsdeBalanceBefore, await WBTC.decimals())} ${await WBTC.symbol()}`
`WBTCBalanceBefore: ${formatUnits(WBTCBalanceBefore, await WBTC.decimals())} ${await WBTC.symbol()}`
);

const swapCalldata = constructSwap([Dex.PendleCurve], [SWAP_ONE]);
Expand All @@ -370,7 +440,19 @@ describe('PendleCurveAdapter PT-eBTC - WBTC', () => {
expect(ptBalanceBefore).to.be.greaterThan(ptBalanceAfter);
const WBTCBalanceAfter = await WBTC.balanceOf(user.address);
console.log(`sUsdeBalanceAfter: ${formatUnits(WBTCBalanceAfter, await WBTC.decimals())} ${await WBTC.symbol()}`);
expect(WBTCBalanceAfter.sub(sUsdeBalanceBefore)).to.be.eq(WBTCOut);
expect(WBTCBalanceAfter.sub(WBTCBalanceBefore)).to.be.eq(WBTCOut);

await assertSwapEvent(
{
isExactInput: false,
tokenIn: ptToken.address,
tokenOut: WBTC.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: WBTCBalanceAfter.sub(WBTCBalanceBefore),
},
router,
tx
);
});
});
});
74 changes: 73 additions & 1 deletion packages/router/test/int/PendleCurveNgAdapterEthena.eth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
PendleCurveNgAdapter,
PendleCurveNgAdapter__factory,
} from '../../typechain-types';
import { constructSwap, Dex, resetFork, showBalance, showGasUsage, SWAP_ONE } from '../shared/utils';
import { assertSwapEvent, constructSwap, Dex, resetFork, showBalance, showGasUsage, SWAP_ONE } from '../shared/utils';
import { EthAddress } from '@marginly/common';
import { formatUnits, parseUnits } from 'ethers/lib/utils';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
Expand Down Expand Up @@ -139,6 +139,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {
expect(usdcBalanceBefore).to.be.greaterThan(usdcBalanceAfter);

await showBalance(usde, pendleCurveAdapter.address, 'usde stays on adapter: ');

await assertSwapEvent(
{
isExactInput: false,
tokenIn: usdc.address,
tokenOut: ptToken.address,
amountIn: usdcBalanceBefore.sub(usdcBalanceAfter),
amountOut: ptBalanceAfter.sub(ptBalanceBefore),
},
router,
tx
);
});

it('USDC to pt-USDe exact output, small amount', async () => {
Expand All @@ -162,6 +174,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {
expect(usdcBalanceBefore).to.be.greaterThan(usdcBalanceAfter);

await showBalance(usde, pendleCurveAdapter.address, 'usde stays on adapter: ');

await assertSwapEvent(
{
isExactInput: false,
tokenIn: usdc.address,
tokenOut: ptToken.address,
amountIn: usdcBalanceBefore.sub(usdcBalanceAfter),
amountOut: ptBalanceAfter.sub(ptBalanceBefore),
},
router,
tx
);
});

it('pt-USDe to USDC exact input', async () => {
Expand All @@ -179,6 +203,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {

const usdcBalanceAfter = await showBalance(usdc, user.address, 'usdc balance After:');
expect(usdcBalanceAfter).to.be.greaterThan(usdcBalanceBefore);

await assertSwapEvent(
{
isExactInput: true,
tokenIn: ptToken.address,
tokenOut: usdc.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: usdcBalanceAfter.sub(usdcBalanceBefore),
},
router,
tx
);
});

it('pt-USDe to USDC exact output', async () => {
Expand All @@ -201,6 +237,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {
expect(usdcBalanceAfter.sub(usdcBalanceBefore)).to.be.eq(usdcOut);

await showBalance(usdc, pendleCurveAdapter.address, 'USDC stays on adapter: ');

await assertSwapEvent(
{
isExactInput: false,
tokenIn: ptToken.address,
tokenOut: usdc.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: usdcBalanceAfter.sub(usdcBalanceBefore),
},
router,
tx
);
});
});

Expand Down Expand Up @@ -292,6 +340,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {

const usdcBalanceAfter = await showBalance(usdc, user.address, 'usdc balance After:');
expect(usdcBalanceAfter).to.be.greaterThan(usdcBalanceBefore);

await assertSwapEvent(
{
isExactInput: true,
tokenIn: ptToken.address,
tokenOut: usdc.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: usdcBalanceAfter.sub(usdcBalanceBefore),
},
router,
tx
);
});

it('pt-USDe to USDC exact output', async () => {
Expand All @@ -312,6 +372,18 @@ describe('PendleCurveAdapter PT-usde - usdc', () => {

const usdcBalanceAfter = await showBalance(usdc, user.address, 'usdc balance After:');
expect(usdcBalanceAfter.sub(usdcBalanceBefore)).to.be.eq(usdcOut);

await assertSwapEvent(
{
isExactInput: false,
tokenIn: ptToken.address,
tokenOut: usdc.address,
amountIn: ptBalanceBefore.sub(ptBalanceAfter),
amountOut: usdcBalanceAfter.sub(usdcBalanceBefore),
},
router,
tx
);
});
});
});
Loading