Skip to content

Commit 72243db

Browse files
authored
fix(FlashMintHyETH): Add Pendle exchangeRate() increment handling (#175)
* add inflation factor to pendle market data * update FlashMintHyETH integration tests
1 parent e0cf003 commit 72243db

File tree

3 files changed

+74
-48
lines changed

3 files changed

+74
-48
lines changed

contracts/exchangeIssuance/FlashMintHyETH.sol

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ contract FlashMintHyETH is Ownable, ReentrancyGuard {
5151
IPendlePrincipalToken pt;
5252
IPendleStandardizedYield sy;
5353
address underlying;
54+
uint256 exchangeRateFactor;
5455
}
5556
/* ============ Constants ============= */
5657

@@ -314,15 +315,22 @@ contract FlashMintHyETH is Ownable, ReentrancyGuard {
314315
* @param _sy Address of the corresponding Standardized Yield Token
315316
* @param _underlying Address of the underlying token to redeem to
316317
* @param _market Address of the Pendle Market to use for swapping between pt and sy
318+
* @param _exchangeRateFactor Factor to multiply the exchange rate when supplying to Pendle Market
317319
*/
318320
function setPendleMarket(
319321
IPendlePrincipalToken _pt,
320322
IPendleStandardizedYield _sy,
321323
address _underlying,
322-
IPendleMarketV3 _market
324+
IPendleMarketV3 _market,
325+
uint256 _exchangeRateFactor
323326
) external onlyOwner {
324327
pendleMarkets[_pt] = _market;
325-
pendleMarketData[_market] = PendleMarketData({ pt: _pt, sy: _sy, underlying: _underlying });
328+
pendleMarketData[_market] = PendleMarketData({
329+
pt: _pt,
330+
sy: _sy,
331+
underlying: _underlying,
332+
exchangeRateFactor: _exchangeRateFactor
333+
});
326334
}
327335

328336
/**
@@ -340,7 +348,15 @@ contract FlashMintHyETH is Ownable, ReentrancyGuard {
340348
marketData.pt.transfer(msg.sender, ptAmount);
341349
} else if (_syToAccount < 0) {
342350
uint256 syAmount = uint256(-_syToAccount);
343-
uint256 ethAmount = syAmount.mul(marketData.sy.exchangeRate()).div(1e18);
351+
352+
// Withdraw necessary ETH, if deposit size is enough to move the oracle, then the exchange rate will not be
353+
// valid for computing the amount of ETH to withdraw, so increase by exchangeRateFactor
354+
uint256 ethAmount = syAmount.mul(marketData.sy.exchangeRate()).div(1 ether);
355+
uint256 syAmountPreview = marketData.sy.previewDeposit(address(0), ethAmount);
356+
if (syAmountPreview < syAmount) {
357+
ethAmount = ethAmount * marketData.exchangeRateFactor / 1 ether;
358+
}
359+
344360
marketData.sy.deposit{ value: ethAmount }(msg.sender, address(0), ethAmount, 0);
345361
} else {
346362
revert("Invalid callback");

test/integration/ethereum/addresses.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export const PRODUCTION_ADDRESSES = {
2929
pendleEEth0624: "0xc69Ad9baB1dEE23F4605a82b3354F8E40d1E5966",
3030
pendleRsEth0624: "0xB05cABCd99cf9a73b19805edefC5f67CA5d1895E",
3131
pendleRswEth0624: "0x5cb12D56F5346a016DBBA8CA90635d82e6D1bcEa",
32+
pendleEzEth1226: "0xf7906F274c174A52d444175729E3fa98f9bde285",
33+
pendleEEth0926: "0x1c085195437738d73d75DC64bC5A3E098b7f93b1",
34+
pendleEEth1226: "0x6ee2b5E19ECBa773a352E5B21415Dc419A700d1d",
35+
ezEth: "0xbf5495Efe5DB9ce00f80364C8B423567e58d2110",
3236
weEth: "0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee",
3337
rsEth: "0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7",
3438
rswEth: "0xFAe103DC9cf190eD75350761e95403b7b8aFa6c0",
@@ -69,6 +73,9 @@ export const PRODUCTION_ADDRESSES = {
6973
eEth0624: "0xF32e58F92e60f4b0A37A69b95d642A471365EAe8",
7074
rsEth0624: "0x4f43c77872db6ba177c270986cd30c3381af37ee",
7175
rswEth0624: "0xa9355a5d306c67027c54de0e5a72df76befa5694",
76+
ezEth1226: "0xD8F12bCDE578c653014F27379a6114F67F0e445f",
77+
eEth0926: "0xC8eDd52D0502Aa8b4D5C77361D4B3D300e8fC81c",
78+
eEth1226: "0x7d372819240D14fB477f17b964f95F33BeB4c704",
7279
},
7380
},
7481
},

test/integration/ethereum/flashMintHyETH.spec.ts

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ if (process.env.INTEGRATIONTEST) {
5959
let debtIssuanceModule: IDebtIssuanceModule;
6060

6161
// const collateralTokenAddress = addresses.tokens.stEth;
62-
setBlockNumber(19740000, true);
62+
setBlockNumber(20030042, true);
6363

6464
before(async () => {
6565
[owner] = await getAccounts();
@@ -130,9 +130,9 @@ if (process.env.INTEGRATIONTEST) {
130130
let setToken: SetToken;
131131
const components = [
132132
addresses.tokens.instadappEthV2,
133-
addresses.tokens.pendleEEth0624,
134-
addresses.tokens.pendleRsEth0624,
135-
addresses.tokens.pendleRswEth0624,
133+
addresses.tokens.pendleEzEth1226,
134+
addresses.tokens.pendleEEth0926,
135+
addresses.tokens.pendleEEth1226,
136136
addresses.tokens.acrossWethLP,
137137
addresses.tokens.USDC,
138138
];
@@ -212,77 +212,80 @@ if (process.env.INTEGRATIONTEST) {
212212
exchange: 4,
213213
});
214214

215-
const eEthPendleToken = IPendlePrincipalToken__factory.connect(
216-
addresses.tokens.pendleEEth0624,
215+
const ezEth1226PendleToken = IPendlePrincipalToken__factory.connect(
216+
addresses.tokens.pendleEzEth1226,
217217
owner.wallet,
218218
);
219219
await flashMintHyETH.approveSetToken(setToken.address);
220-
const eEthSyToken = await eEthPendleToken.SY();
220+
const ezEth1226SyToken = await ezEth1226PendleToken.SY();
221221
await flashMintHyETH.approveToken(
222-
eEthSyToken,
223-
addresses.dexes.pendle.markets.eEth0624,
222+
ezEth1226SyToken,
223+
addresses.dexes.pendle.markets.ezEth1226,
224224
MAX_UINT_256,
225225
);
226226
await flashMintHyETH.setPendleMarket(
227-
addresses.tokens.pendleEEth0624,
228-
eEthSyToken,
229-
addresses.tokens.weEth,
230-
addresses.dexes.pendle.markets.eEth0624,
227+
addresses.tokens.pendleEzEth1226,
228+
ezEth1226SyToken,
229+
addresses.tokens.ezEth,
230+
addresses.dexes.pendle.markets.ezEth1226,
231+
ethers.utils.parseEther("1.0005"),
231232
);
232-
// weETH -> weth pool: https://etherscan.io/address/0x7a415b19932c0105c82fdb6b720bb01b0cc2cae3
233-
await flashMintHyETH.setSwapData(addresses.tokens.weEth, ADDRESS_ZERO, {
234-
path: [addresses.tokens.weEth, addresses.tokens.weth],
235-
fees: [500],
233+
// ezETH -> weth pool: https://etherscan.io/address/0xbe80225f09645f172b079394312220637c440a63#code
234+
await flashMintHyETH.setSwapData(addresses.tokens.ezEth, ADDRESS_ZERO, {
235+
path: [addresses.tokens.ezEth, addresses.tokens.weth],
236+
fees: [100],
236237
pool: ADDRESS_ZERO,
237238
exchange: 3,
238239
});
239240

240-
const rsEthPendleToken = IPendlePrincipalToken__factory.connect(
241-
addresses.tokens.pendleRsEth0624,
241+
const pendleEEth0926PendleToken = IPendlePrincipalToken__factory.connect(
242+
addresses.tokens.pendleEEth0926,
242243
owner.wallet,
243244
);
244245
await flashMintHyETH.approveSetToken(setToken.address);
245-
const rsEthSyToken = await rsEthPendleToken.SY();
246+
const pendleEEth0926SyToken = await pendleEEth0926PendleToken.SY();
246247
await flashMintHyETH.approveToken(
247-
rsEthSyToken,
248-
addresses.dexes.pendle.markets.rsEth0624,
248+
pendleEEth0926SyToken,
249+
addresses.dexes.pendle.markets.eEth0926,
249250
MAX_UINT_256,
250251
);
251252
await flashMintHyETH.setPendleMarket(
252-
addresses.tokens.pendleRsEth0624,
253-
rsEthSyToken,
254-
addresses.tokens.rsEth,
255-
addresses.dexes.pendle.markets.rsEth0624,
253+
addresses.tokens.pendleEEth0926,
254+
pendleEEth0926SyToken,
255+
addresses.tokens.weEth,
256+
addresses.dexes.pendle.markets.eEth0926,
257+
ethers.utils.parseEther("1.0005"),
256258
);
257-
// rsEth -> weth pool: https://etherscan.io/address/0x059615ebf32c946aaab3d44491f78e4f8e97e1d3
258-
await flashMintHyETH.setSwapData(addresses.tokens.rsEth, ADDRESS_ZERO, {
259-
path: [addresses.tokens.rsEth, addresses.tokens.weth],
259+
// weETH -> weth pool: https://etherscan.io/address/0x7a415b19932c0105c82fdb6b720bb01b0cc2cae3
260+
await flashMintHyETH.setSwapData(addresses.tokens.weEth, ADDRESS_ZERO, {
261+
path: [addresses.tokens.weEth, addresses.tokens.weth],
260262
fees: [500],
261263
pool: ADDRESS_ZERO,
262264
exchange: 3,
263265
});
264266

265-
const rswEthPendleToken = IPendlePrincipalToken__factory.connect(
266-
addresses.tokens.pendleRswEth0624,
267+
const pendleEEth1226PendleToken = IPendlePrincipalToken__factory.connect(
268+
addresses.tokens.pendleEEth1226,
267269
owner.wallet,
268270
);
269271
await flashMintHyETH.approveSetToken(setToken.address);
270-
const rswEthSyToken = await rswEthPendleToken.SY();
272+
const pendleEEth1226SyToken = await pendleEEth1226PendleToken.SY();
271273
await flashMintHyETH.approveToken(
272-
rswEthSyToken,
273-
addresses.dexes.pendle.markets.rswEth0624,
274+
pendleEEth1226SyToken,
275+
addresses.dexes.pendle.markets.eEth1226,
274276
MAX_UINT_256,
275277
);
276278
await flashMintHyETH.setPendleMarket(
277-
addresses.tokens.pendleRswEth0624,
278-
rswEthSyToken,
279-
addresses.tokens.rswEth,
280-
addresses.dexes.pendle.markets.rswEth0624,
279+
addresses.tokens.pendleEEth1226,
280+
pendleEEth1226SyToken,
281+
addresses.tokens.weEth,
282+
addresses.dexes.pendle.markets.eEth1226,
283+
ethers.utils.parseEther("1.0005"),
281284
);
282-
// rswEth -> weth pool: https://etherscan.io/address/0xe62627326d7794e20bb7261b24985294de1579fe
283-
await flashMintHyETH.setSwapData(addresses.tokens.rswEth, ADDRESS_ZERO, {
284-
path: [addresses.tokens.rswEth, addresses.tokens.weth],
285-
fees: [3000],
285+
// weETH -> weth pool: https://etherscan.io/address/0x7a415b19932c0105c82fdb6b720bb01b0cc2cae3
286+
await flashMintHyETH.setSwapData(addresses.tokens.weEth, ADDRESS_ZERO, {
287+
path: [addresses.tokens.weEth, addresses.tokens.weth],
288+
fees: [500],
286289
pool: ADDRESS_ZERO,
287290
exchange: 3,
288291
});
@@ -293,9 +296,9 @@ if (process.env.INTEGRATIONTEST) {
293296

294297
["eth", "weth", "USDC"].forEach((inputTokenName: keyof typeof addresses.tokens | "eth") => {
295298
describe(`When inputToken is ${inputTokenName}`, () => {
296-
const ethIn = ether(1.01);
297-
const maxAmountIn = inputTokenName == "USDC" ? usdc(3300) : ethIn;
298-
const setTokenAmount = ether(1);
299+
const ethIn = ether(1001);
300+
const maxAmountIn = inputTokenName == "USDC" ? usdc(4000000) : ethIn;
301+
const setTokenAmount = ether(1000);
299302
let inputToken: IERC20 | IWETH;
300303
let swapDataInputTokenToEth: SwapData;
301304
let swapDataEthToInputToken: SwapData;

0 commit comments

Comments
 (0)