Skip to content

Commit 6f8a0bb

Browse files
author
Sachin
authored
fix(DeltaNeutralBasisTradingStrategy): Rebalance when position multiplier < 1e18 (#37)
* Add test to rebalance when position multiplier < 1e18; should fail * Fetch collateral units to send in rebalance; Failing tests should pass * Update comments explaining the fix * Update version to 0.0.11-basis.0 * bump package to 0.0.12
1 parent 837f581 commit 6f8a0bb

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

contracts/extensions/DeltaNeutralBasisTradingStrategyExtension.sol

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,14 @@ contract DeltaNeutralBasisTradingStrategyExtension is BaseExtension {
863863
if (baseRebalanceUnits < 0) {
864864
_withdraw(oppositeBoundUnits);
865865

866-
_executeDexTrade(baseRebalanceUnits.abs(), oppositeBoundUnits, true);
866+
// `_withdraw` sets position units to oppositeBoundUnits. The SetToken converts the real units, in this case oppositeBoundUnits,
867+
// to virtual units and stores the virtual units. Converting the stored virtual units back to real units will return oppositeBoundUnits
868+
// when position multiplier == 1e18 and oppositeBoundUnits - 1 when position mulitplier < 1e18. Hence, trying to trade
869+
// oppositeBoundUnits worth of collateral when position unit < 1e18 would revert with "Unit cant be greater than existing".
870+
// To avoid the revert, we fetch the latest position unit and pass it to the trade function.
871+
uint256 collateralSendUnits = strategy.setToken.getDefaultPositionRealUnit(address(collateralToken)).toUint256();
872+
873+
_executeDexTrade(baseRebalanceUnits.abs(), collateralSendUnits, true);
867874
} else {
868875
_executeDexTrade(baseRebalanceUnits.abs(), oppositeBoundUnits, false);
869876
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@setprotocol/set-v2-strategies",
3-
"version": "0.0.11",
3+
"version": "0.0.12",
44
"description": "",
55
"main": "dist",
66
"types": "dist/types",

test/extensions/deltaNeutralBasisTradingStrategyExtension.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,31 @@ describe("DeltaNeutralBasisTradingStrategyExtension", () => {
11481148
});
11491149
});
11501150

1151+
describe("when rebalance interval has not elapsed but is below min LR & position multiplier < 1e18", async () => {
1152+
beforeEach(async () => {
1153+
await perpV2Setup.setBaseTokenOraclePrice(perpV2Setup.vETH, usdc(900));
1154+
await perpV2PriceFeedMock.setPrice(BigNumber.from(900).mul(10 ** 8));
1155+
1156+
// pass time to accrue streaming fee
1157+
await increaseTimeAsync(ONE_DAY_IN_SECONDS.mul(7));
1158+
1159+
// collect fees to push position multiplier lower than 1e18
1160+
systemSetup.streamingFeeModule.connect(owner.wallet).accrueFee(setToken.address);
1161+
});
1162+
1163+
it("should verify initial testing conditions", async () => {
1164+
const currentLeverageRatio = await leverageStrategyExtension.getCurrentLeverageRatio();
1165+
const positionMultiplier = await setToken.positionMultiplier();
1166+
1167+
expect(positionMultiplier).to.be.lt(ether(1));
1168+
expect(currentLeverageRatio.abs()).to.be.lt(methodology.minLeverageRatio.abs());
1169+
});
1170+
1171+
it("should be able to rebalance", async () => {
1172+
await expect(subject()).to.not.be.reverted;
1173+
});
1174+
});
1175+
11511176
describe("when rebalance interval has not elapsed below min leverage ratio and greater than max trade size", async () => {
11521177
let newExchangeSettings: PerpV2BasisExchangeSettings;
11531178

0 commit comments

Comments
 (0)