Skip to content

Commit

Permalink
Merge branch 'main' into feat/blue-sdk-viem-deployless-reads
Browse files Browse the repository at this point in the history
  • Loading branch information
oumar-fall committed Oct 9, 2024
2 parents 9e13814 + 8f982e2 commit 6c5a7e7
Show file tree
Hide file tree
Showing 27 changed files with 14,215 additions and 345 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/npm-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
if [ -n "${{ inputs.custom_version }}" ]; then
yarn lerna version ${{ inputs.custom_version }} --y --force-publish
yarn lerna version ${{ inputs.custom_version }} --y --force-publish --no-git-tag-version
yarn run publish --y --dist-tag unstable
else
yarn lerna version ${{ inputs.version }} --no-private --no-changelog --conventional-commits --y
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
"publish": "lerna publish from-git"
},
"devDependencies": {
"@biomejs/biome": "1.8.3",
"@lerna-lite/cli": "^3.9.1",
"@lerna-lite/publish": "^3.8.0",
"@biomejs/biome": "^1.8.3",
"@lerna-lite/cli": "3.9.1",
"@lerna-lite/publish": "3.9.2",
"@lerna-lite/version": "^3.7.1",
"husky": "^9.0.11",
"typescript": "^5.6.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@ import {
import {
LiquidationEncoder,
apiSdk,
fetchBestSwap,
getPendleRedeemCallData,
getPendleSwapCallData,
pendleMarkets,
pendleTokens,
mainnetAddresses,
pendle,
swap,
} from "@morpho-org/blue-sdk-ethers-liquidation";
import { Time } from "@morpho-org/morpho-ts";

Expand Down Expand Up @@ -82,6 +80,8 @@ export const check = async (

const ethPriceUsd = safeParseNumber(wethPriceUsd, 18);

const pendleTokens = await pendle.getPendleTokens(chainId);

return Promise.all(
(positions ?? []).map(async (position) => {
if (position.market.collateralAsset == null) return;
Expand Down Expand Up @@ -170,101 +170,80 @@ export const check = async (
let dstAmount = 0n;
// Handle Pendle Tokens
// To retrieve the tokens, we need to call the Pendle API to get the swap calldata
if (pendleTokens[chainId].has(market.config.collateralToken)) {
const pendleMarketData =
pendleMarkets[chainId][market.config.collateralToken];
const maturity = pendleMarketData?.maturity;
if (!maturity) {
throw Error("Pendle market not found");
({ srcAmount, srcToken } = await encoder.handlePendleTokens(
chainId,
market.config.collateralToken,
seizedAssets,
pendleTokens,
));

switch (true) {
// In case of Usual tokens, there aren't much liquidity outside of curve, so we use it instead of 1inch/paraswap
// Process USD0/USD0++ collateral liquidation with specific process (using curve)
case market.config.collateralToken ===
mainnetAddresses["usd0usd0++"] &&
chainId === ChainId.EthMainnet:
dstAmount = await encoder.curveSwapUsd0Usd0PPForUsdc(
srcAmount,
accrualPosition.market.toBorrowAssets(
accrualPosition.market.getLiquidationRepaidShares(
seizedAssets,
),
),
executorAddress,
);
break;
// Process USD0++ colalteral liquidation with specific process (using curve)
case market.config.collateralToken ===
mainnetAddresses["usd0++"] &&
chainId === ChainId.EthMainnet: {
dstAmount = await encoder.swapUSD0PPToUSDC(
srcAmount,
accrualPosition.market.toBorrowAssets(
accrualPosition.market.getLiquidationRepaidShares(
seizedAssets,
),
),
executorAddress,
);
break;
}

srcAmount = seizedAssets;
srcToken = pendleMarketData.underlyingTokenAddress;
if (maturity < new Date()) {
// Pendle market is expired, we can directly redeem the collateral
// If called before YT's expiry, both PT & YT of equal amounts are needed and will be burned. Else, only PT is needed and will be burned.
const redeemCallData = await getPendleRedeemCallData(
// Default case, use 1inch/paraswap for other collaterals
default: {
const bestSwap = await swap.fetchBestSwap({
chainId,
{
receiver: executorAddress,
slippage: 0.04,
yt: pendleMarketData.yieldTokenAddress,
amountIn: seizedAssets.toString(),
tokenOut: pendleMarketData.underlyingTokenAddress,
enableAggregator: true,
},
);

encoder
.erc20Approve(srcToken, redeemCallData.tx.to, MaxUint256)
.erc20Approve(
market.config.collateralToken,
redeemCallData.tx.to,
MaxUint256,
)
.pushCall(
redeemCallData.tx.to,
redeemCallData.tx.value ? redeemCallData.tx.value : 0n,
redeemCallData.tx.data,
src: srcToken,
dst: market.config.loanToken,
amount: srcAmount,
from: executorAddress,
slippage,
includeTokensInfo: false,
includeProtocols: false,
includeGas: false,
allowPartialFill: false,
disableEstimate: true,
usePermit2: false,
});
if (!bestSwap)
throw Error(
"could not fetch swap from both 1inch and paraswap",
);
} else {
// Pendle market is not expired, we need to swap the collateral token (PT) to the underlying token
const swapCallData = await getPendleSwapCallData(
chainId,
pendleMarketData.address,
{
receiver: executorAddress,
slippage: 0.04,
tokenIn: market.config.collateralToken,
tokenOut: pendleMarketData.underlyingTokenAddress,
amountIn: seizedAssets.toString(),
},
);
dstAmount = toBigInt(bestSwap.dstAmount);

if (
dstAmount < repaidAssets.wadMulDown(BigInt.WAD + slippage)
)
return;
encoder
.erc20Approve(srcToken, swapCallData.tx.to, MaxUint256)
.erc20Approve(
market.config.collateralToken,
swapCallData.tx.to,
MaxUint256,
)
.erc20Approve(srcToken, bestSwap.tx.to, srcAmount)
.pushCall(
swapCallData.tx.to,
swapCallData.tx.value ? swapCallData.tx.value : 0n,
swapCallData.tx.data,
bestSwap.tx.to,
bestSwap.tx.value,
bestSwap.tx.data,
);
srcAmount = BigInt(swapCallData.data.amountOut);
break;
}
}
const bestSwap = await fetchBestSwap({
chainId,
src: srcToken,
dst: market.config.loanToken,
amount: srcAmount,
from: executorAddress,
slippage,
includeTokensInfo: false,
includeProtocols: false,
includeGas: false,
allowPartialFill: false,
disableEstimate: true,
usePermit2: false,
});

if (!bestSwap)
throw Error(
"could not fetch swap from both 1inch and paraswap",
);
dstAmount = toBigInt(bestSwap.dstAmount);

if (dstAmount < repaidAssets.wadMulDown(BigInt.WAD + slippage))
return;
encoder
.erc20Approve(srcToken, bestSwap.tx.to, srcAmount)
.pushCall(
bestSwap.tx.to,
bestSwap.tx.value,
bestSwap.tx.data,
);

// Handle ERC20Wrapper collateral tokens.
if (
Expand Down
3 changes: 3 additions & 0 deletions packages/blue-sdk-ethers-liquidation/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const config: HardhatUserConfig = {
},
},
allowBlocksWithSameTimestamp: true,
// Config tweak to be able to easily impersonate accounts without big ETH balance
gasPrice: 10,
initialBaseFeePerGas: 10,
},
},
solidity: {
Expand Down
4 changes: 3 additions & 1 deletion packages/blue-sdk-ethers-liquidation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"scripts": {
"prepublish": "yarn build",
"build": "tsc --build tsconfig.build.json",
"test": "hardhat test",
"build-contract-types": "yarn typechain --target ethers-v6 --out-dir src/contracts/curve \"src/abi/*.json\"",
"test-jest": "jest",
"test-hardhat": "hardhat test",
"codegen": "graphql-codegen --config codegen.ts && prettier -w src/api/"
},
"dependencies": {
Expand Down
Loading

0 comments on commit 6c5a7e7

Please sign in to comment.