Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(flash-swap): support liquidating vaults with underlying as collateral #64

Merged
merged 16 commits into from
Nov 5, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
f222278
feat(flash-swap): implement liquidating underlying as collateral
scorpion9979 Nov 2, 2021
ef7a6d3
feat(flash-swap): add tests for underlying as collateral
scorpion9979 Nov 3, 2021
254bafb
refactor(flash-swap): expect no profit + better error naming
scorpion9979 Nov 3, 2021
4e3f8cb
feat(tasks): add deploy task for underlying as collaeral flash-swap
scorpion9979 Nov 3, 2021
59db094
feat(flash-swap): repay USDC liquidation 0.3% Uniswap fee from bot wa…
scorpion9979 Nov 3, 2021
c238f40
feat(flash-swap): add test to increase coverage
scorpion9979 Nov 3, 2021
ffda179
refactor: move common logic in "HifiFlashUniswapV2.sol"
PaulRBerg Nov 4, 2021
b02aac3
refactor(flash-swap): "HifiFlashUniswapV2" into "CollateralFlashUnisw…
PaulRBerg Nov 4, 2021
5a2e0dc
refactor(flash-swap): use only "underlying" in var names in "Underlyi…
PaulRBerg Nov 4, 2021
e1ed460
test(flash-swap): refactor variable names in "UnderlyingFlashUniswapV…
PaulRBerg Nov 4, 2021
601f296
ci: fix task names in flash swap deployers
PaulRBerg Nov 4, 2021
4da7d20
chore(flash-swap): order variables alphabetically
PaulRBerg Nov 4, 2021
613df07
fix(flash-swap): properly compare "repayUnderlyingAmount" to "seizedU…
PaulRBerg Nov 4, 2021
d86fc14
fix(flash-swap): transfer profit instead of subsidized amount
PaulRBerg Nov 5, 2021
190e0ec
test(flash-swap): repay underlying equal to seized underlying
scorpion9979 Nov 5, 2021
5ced780
test(flash-swap): flash borrow other token when token order is changed
PaulRBerg Nov 5, 2021
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
7 changes: 3 additions & 4 deletions packages/flash-swap/contracts/uniswap-v2/FlashUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ library FlashUtils {
);
}

/// @dev Liquidates the borrower by transferring the underlying to the BalanceSheet. By doing this, the
/// liquidator receives collateral at a discount.
/// @dev Liquidates the borrower, receiving collateral at a discount.
function liquidateBorrowInternal(
IBalanceSheetV1 balanceSheet,
address borrower,
Expand All @@ -46,8 +45,8 @@ library FlashUtils {

// If the hypothetical repay amount is bigger than the debt amount, this could be a single-collateral multi-bond
// vault. Otherwise, it could be a multi-collateral single-bond vault. However, it is difficult to generalize
// for the multi-collateral and multi-bond situation. The repay amount could be either bigger, smaller, or even
// equal to the debt amount depending on the collateral and debt amount distribution.
// for the multi-collateral and multi-bond situation. The repay amount could be greater, smaller, or equal
// to the debt amount depending on the collateral and debt amount distribution.
uint256 debtAmount = balanceSheet.getDebtAmount(borrower, bond);
uint256 repayAmount = hypotheticalRepayAmount > debtAmount ? debtAmount : hypotheticalRepayAmount;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ interface IUnderlyingFlashUniswapV2 is IUniswapV2Callee {
address indexed bond,
uint256 underlyingAmount,
uint256 seizedUnderlyingAmount,
uint256 repayUnderlyingAmount
uint256 repayUnderlyingAmount,
uint256 profitUnderlyingAmount,
uint256 subsidizedUnderlyingAmount
);

/// CONSTANT FUNCTIONS ///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ contract UnderlyingFlashUniswapV2 is IUnderlyingFlashUniswapV2 {
address borrower;
uint256 mintedHTokenAmount;
IErc20 otherToken;
uint256 profitUnderlyingAmount;
uint256 repayUnderlyingAmount;
uint256 seizedUnderlyingAmount;
uint256 shortfallUnderlyingAmount;
uint256 subsidizedUnderlyingAmount;
address subsidizer;
uint256 surplusUnderlyingAmount;
IErc20 underlying;
uint256 underlyingAmount;
}
Expand Down Expand Up @@ -159,14 +159,14 @@ contract UnderlyingFlashUniswapV2 is IUnderlyingFlashUniswapV2 {
// the seized underlying amount.
if (vars.repayUnderlyingAmount > vars.seizedUnderlyingAmount) {
unchecked {
vars.shortfallUnderlyingAmount = vars.repayUnderlyingAmount - vars.seizedUnderlyingAmount;
vars.subsidizedUnderlyingAmount = vars.repayUnderlyingAmount - vars.seizedUnderlyingAmount;
}
vars.underlying.safeTransferFrom(vars.subsidizer, address(this), vars.shortfallUnderlyingAmount);
vars.underlying.safeTransferFrom(vars.subsidizer, address(this), vars.subsidizedUnderlyingAmount);
} else if (vars.seizedUnderlyingAmount > vars.repayUnderlyingAmount) {
unchecked {
vars.surplusUnderlyingAmount = vars.seizedUnderlyingAmount - vars.repayUnderlyingAmount;
vars.profitUnderlyingAmount = vars.seizedUnderlyingAmount - vars.repayUnderlyingAmount;
}
vars.underlying.safeTransfer(sender, vars.shortfallUnderlyingAmount);
vars.underlying.safeTransfer(sender, vars.profitUnderlyingAmount);
}

// Pay back the loan.
Expand All @@ -179,7 +179,9 @@ contract UnderlyingFlashUniswapV2 is IUnderlyingFlashUniswapV2 {
address(vars.bond),
vars.underlyingAmount,
vars.seizedUnderlyingAmount,
vars.repayUnderlyingAmount
vars.repayUnderlyingAmount,
vars.subsidizedUnderlyingAmount,
vars.profitUnderlyingAmount
);
}
}
51 changes: 44 additions & 7 deletions packages/flash-swap/src/types/IUnderlyingFlashUniswapV2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ interface IUnderlyingFlashUniswapV2Interface extends ethers.utils.Interface {
): Result;

events: {
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256)": EventFragment;
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256,uint256,uint256)": EventFragment;
};

getEvent(
Expand All @@ -89,13 +89,24 @@ interface IUnderlyingFlashUniswapV2Interface extends ethers.utils.Interface {
}

export type FlashSwapUnderlyingAndLiquidateBorrowEvent = TypedEvent<
[string, string, string, BigNumber, BigNumber, BigNumber] & {
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
] & {
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;

Expand Down Expand Up @@ -234,22 +245,35 @@ export class IUnderlyingFlashUniswapV2 extends BaseContract {
};

filters: {
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256)"(
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256,uint256,uint256)"(
liquidator?: string | null,
borrower?: string | null,
bond?: string | null,
underlyingAmount?: null,
seizedUnderlyingAmount?: null,
repayUnderlyingAmount?: null
repayUnderlyingAmount?: null,
profitUnderlyingAmount?: null,
subsidizedUnderlyingAmount?: null
): TypedEventFilter<
[string, string, string, BigNumber, BigNumber, BigNumber],
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
],
{
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;

Expand All @@ -259,16 +283,29 @@ export class IUnderlyingFlashUniswapV2 extends BaseContract {
bond?: string | null,
underlyingAmount?: null,
seizedUnderlyingAmount?: null,
repayUnderlyingAmount?: null
repayUnderlyingAmount?: null,
profitUnderlyingAmount?: null,
subsidizedUnderlyingAmount?: null
): TypedEventFilter<
[string, string, string, BigNumber, BigNumber, BigNumber],
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
],
{
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;
};
Expand Down
51 changes: 44 additions & 7 deletions packages/flash-swap/src/types/UnderlyingFlashUniswapV2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ interface UnderlyingFlashUniswapV2Interface extends ethers.utils.Interface {
): Result;

events: {
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256)": EventFragment;
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256,uint256,uint256)": EventFragment;
};

getEvent(
Expand All @@ -89,13 +89,24 @@ interface UnderlyingFlashUniswapV2Interface extends ethers.utils.Interface {
}

export type FlashSwapUnderlyingAndLiquidateBorrowEvent = TypedEvent<
[string, string, string, BigNumber, BigNumber, BigNumber] & {
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
] & {
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;

Expand Down Expand Up @@ -234,22 +245,35 @@ export class UnderlyingFlashUniswapV2 extends BaseContract {
};

filters: {
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256)"(
"FlashSwapUnderlyingAndLiquidateBorrow(address,address,address,uint256,uint256,uint256,uint256,uint256)"(
liquidator?: string | null,
borrower?: string | null,
bond?: string | null,
underlyingAmount?: null,
seizedUnderlyingAmount?: null,
repayUnderlyingAmount?: null
repayUnderlyingAmount?: null,
profitUnderlyingAmount?: null,
subsidizedUnderlyingAmount?: null
): TypedEventFilter<
[string, string, string, BigNumber, BigNumber, BigNumber],
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
],
{
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;

Expand All @@ -259,16 +283,29 @@ export class UnderlyingFlashUniswapV2 extends BaseContract {
bond?: string | null,
underlyingAmount?: null,
seizedUnderlyingAmount?: null,
repayUnderlyingAmount?: null
repayUnderlyingAmount?: null,
profitUnderlyingAmount?: null,
subsidizedUnderlyingAmount?: null
): TypedEventFilter<
[string, string, string, BigNumber, BigNumber, BigNumber],
[
string,
string,
string,
BigNumber,
BigNumber,
BigNumber,
BigNumber,
BigNumber
],
{
liquidator: string;
borrower: string;
bond: string;
underlyingAmount: BigNumber;
seizedUnderlyingAmount: BigNumber;
repayUnderlyingAmount: BigNumber;
profitUnderlyingAmount: BigNumber;
subsidizedUnderlyingAmount: BigNumber;
}
>;
};
Expand Down
Loading