Skip to content

Commit 1642d5f

Browse files
authored
feat(MorphoLeverageStrategyExtension): Add method to exit collateral position after disengaging (#191)
1 parent 4aa6d43 commit 1642d5f

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

contracts/adapters/MorphoLeverageStrategyExtension.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ contract MorphoLeverageStrategyExtension is BaseExtension {
191191
event ExchangeRemoved(
192192
string _exchangeName
193193
);
194+
event CollateralWithdrawn();
194195

195196
/* ============ Modifiers ============ */
196197

@@ -459,6 +460,16 @@ contract MorphoLeverageStrategyExtension is BaseExtension {
459460
);
460461
}
461462

463+
/**
464+
* OPERATOR ONLY: Withdraw all collateral from morpho
465+
*
466+
* Note: Can only be executed after fully deleveraging / disengaging the strategy. Will revert otherwise.
467+
*/
468+
function exitCollateralPosition() external onlyOperator {
469+
_exitCollateralPosition();
470+
emit CollateralWithdrawn();
471+
}
472+
462473
/**
463474
* OPERATOR ONLY: Set methodology settings and check new settings are valid. Note: Need to pass in existing parameters if only changing a few settings. Must not be
464475
* in a rebalance.
@@ -773,6 +784,17 @@ contract MorphoLeverageStrategyExtension is BaseExtension {
773784
invokeManager(address(strategy.leverageModule), enterPositionCallData);
774785
}
775786

787+
function _exitCollateralPosition()
788+
internal
789+
{
790+
bytes memory exitPositionCallData = abi.encodeWithSignature(
791+
"exitCollateralPosition(address)",
792+
address(strategy.setToken)
793+
);
794+
795+
invokeManager(address(strategy.leverageModule), exitPositionCallData);
796+
}
797+
776798
/**
777799
* Calculate notional rebalance quantity, whether to chunk rebalance based on max trade size and max borrow and invoke lever on MorphoLeverageModule
778800
*

external/abi/set/MorphoLeverageModule.json

Lines changed: 26 additions & 12 deletions
Large diffs are not rendered by default.

test/integration/ethereum/morphoLeverageStrategyExtension.spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ if (process.env.INTEGRATIONTEST) {
270270
const [, borrowShares, collateral] = await morpho.position(marketId, setToken.address);
271271
const collateralTokenBalance = await wsteth.balanceOf(setToken.address);
272272
const collateralTotalBalance = collateralTokenBalance.add(collateral);
273-
const [, , totalBorrowAssets, totalBorrowShares, , ] = await morpho.market(marketId);
273+
const [, , totalBorrowAssets, totalBorrowShares, ,] = await morpho.market(marketId);
274274
const borrowAssets = sharesToAssetsUp(borrowShares, totalBorrowAssets, totalBorrowShares);
275275
return { collateralTotalBalance, borrowAssets };
276276
}
@@ -3622,6 +3622,22 @@ if (process.env.INTEGRATIONTEST) {
36223622
expect(BigNumber.from(newSecondPosition.unit)).to.gt(ZERO);
36233623
expect(newSecondPosition.module).to.eq(ADDRESS_ZERO);
36243624
});
3625+
3626+
it("can run exitCollateralPosition afterwards", async () => {
3627+
await subject();
3628+
3629+
const [, , collateralBefore] = await morpho.position(marketId, setToken.address);
3630+
await leverageStrategyExtension.exitCollateralPosition();
3631+
const [, , collateralAfter] = await morpho.position(marketId, setToken.address);
3632+
expect(await wsteth.balanceOf(setToken.address)).to.eq(collateralBefore);
3633+
expect(collateralAfter).to.eq(ZERO);
3634+
});
3635+
3636+
it("can't run exitCollateralPosition without disengaging", async () => {
3637+
await expect(leverageStrategyExtension.exitCollateralPosition()).to.be.revertedWith(
3638+
"Borrow balance must be 0",
3639+
);
3640+
});
36253641
},
36263642
);
36273643
});

0 commit comments

Comments
 (0)