Skip to content

Commit f215147

Browse files
author
Sachin
authored
fix(PerpV2BasisTradingModule): Expose getter to fetch updated settled funding (#244)
* Make getUpdatedSettledFunding public; Add javadcos * Add unit tests for getUpdatedSettledFunding
1 parent c67d48b commit f215147

File tree

2 files changed

+152
-18
lines changed

2 files changed

+152
-18
lines changed

contracts/protocol/modules/v2/PerpV2BasisTradingModule.sol

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ contract PerpV2BasisTradingModule is PerpV2LeverageModuleV2 {
429429

430430
if (positions[_setToken].length > 0) {
431431

432-
uint256 updatedSettledFunding = _getUpdatedSettledFunding(_setToken);
432+
uint256 updatedSettledFunding = getUpdatedSettledFunding(_setToken);
433433

434434
int256 newExternalPositionUnit = _executePositionTrades(_setToken, _setTokenQuantity, false, true);
435435

@@ -439,31 +439,18 @@ contract PerpV2BasisTradingModule is PerpV2LeverageModuleV2 {
439439
return _formatAdjustments(_setToken, newExternalPositionUnitNetFees);
440440
}
441441

442-
/* ============ Internal Functions ============ */
443-
444-
/**
445-
* @dev Updates tracked settled funding. Once funding is settled to `owedRealizedPnl` on Perpetual protocol, it is difficult to
446-
* extract out the funding value again on-chain. This function is called in an external function and is used to track and store
447-
* pending funding payment that is about to be settled due to subsequent logic in the external function.
448-
*
449-
* @param _setToken Instance of SetToken
450-
* @return uint256 Returns the updated settled funding value
451-
*/
452-
function _updateSettledFunding(ISetToken _setToken) internal returns (uint256) {
453-
uint256 newSettledFunding = _getUpdatedSettledFunding(_setToken);
454-
settledFunding[_setToken] = newSettledFunding;
455-
return newSettledFunding;
456-
}
457-
458442
/**
459443
* @dev Adds pending funding payment to tracked settled funding. Returns updated settled funding value.
460444
*
461445
* NOTE: Tracked settled funding value can not be less than zero, hence it is reset to zero if pending funding
462446
* payment is negative and |pending funding payment| >= |settledFunding[_setToken]|.
463447
*
448+
* NOTE: Returned updated settled funding value is correct only for the current block since pending funding payment
449+
* updates every block.
450+
*
464451
* @param _setToken Instance of SetToken
465452
*/
466-
function _getUpdatedSettledFunding(ISetToken _setToken) internal view returns (uint256) {
453+
function getUpdatedSettledFunding(ISetToken _setToken) public view returns (uint256) {
467454
// NOTE: pendingFundingPayments are represented as in the Perp system as "funding owed"
468455
// e.g a positive number is a debt which gets subtracted from owedRealizedPnl on settlement.
469456
// We are flipping its sign here to reflect its settlement value.
@@ -480,6 +467,22 @@ contract PerpV2BasisTradingModule is PerpV2LeverageModuleV2 {
480467
return 0;
481468
}
482469

470+
/* ============ Internal Functions ============ */
471+
472+
/**
473+
* @dev Updates tracked settled funding. Once funding is settled to `owedRealizedPnl` on Perpetual protocol, it is difficult to
474+
* extract out the funding value again on-chain. This function is called in an external function and is used to track and store
475+
* pending funding payment that is about to be settled due to subsequent logic in the external function.
476+
*
477+
* @param _setToken Instance of SetToken
478+
* @return uint256 Returns the updated settled funding value
479+
*/
480+
function _updateSettledFunding(ISetToken _setToken) internal returns (uint256) {
481+
uint256 newSettledFunding = getUpdatedSettledFunding(_setToken);
482+
settledFunding[_setToken] = newSettledFunding;
483+
return newSettledFunding;
484+
}
485+
483486
/**
484487
* @dev Calculates manager and protocol fees on withdrawn funding amount and transfers them to
485488
* their respective recipients (in USDC).

test/protocol/modules/v2/perpV2BasisTradingModule.spec.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,137 @@ describe("PerpV2BasisTradingModule", () => {
19161916
});
19171917
});
19181918

1919+
describe("#getUpdatedSettledFunding", async () => {
1920+
let setToken: SetToken;
1921+
let subjectSetToken: Address;
1922+
1923+
const initializeContracts = async () => {
1924+
const depositQuantity = usdcUnits(10);
1925+
1926+
setToken = await issueSetsAndDepositToPerp(depositQuantity, true);
1927+
1928+
await perpBasisTradingModule.connect(owner.wallet).trade(
1929+
setToken.address,
1930+
vETH.address,
1931+
ether(0.5),
1932+
ether(5.15)
1933+
);
1934+
1935+
// Move oracle price up and wait one day
1936+
await perpSetup.setBaseTokenOraclePrice(vETH, usdcUnits(10.2));
1937+
await increaseTimeAsync(ONE_DAY_IN_SECONDS);
1938+
1939+
await perpBasisTradingModule.connect(owner.wallet).tradeAndTrackFunding(
1940+
setToken.address,
1941+
vETH.address,
1942+
ether(0.5),
1943+
ether(5.15),
1944+
);
1945+
};
1946+
1947+
const initializeSubjectVariables = async () => {
1948+
subjectSetToken = setToken.address;
1949+
};
1950+
1951+
cacheBeforeEach(initializeContracts);
1952+
beforeEach(initializeSubjectVariables);
1953+
1954+
async function subject(): Promise<BigNumber> {
1955+
return await perpBasisTradingModule.getUpdatedSettledFunding(subjectSetToken);
1956+
}
1957+
1958+
describe("when pending funding payment is zero", async () => {
1959+
it("should return current settled funding", async () => {
1960+
const settledFundingBefore = await perpBasisTradingModule.settledFunding(subjectSetToken);
1961+
const updatedSettledFunding = await subject();
1962+
1963+
expect(settledFundingBefore).to.be.gt(ZERO);
1964+
expect(updatedSettledFunding).to.eq(settledFundingBefore);
1965+
});
1966+
});
1967+
1968+
describe("when pending funding payment is positive", async () => {
1969+
beforeEach(async () => {
1970+
// Move oracle price up and wait one day
1971+
await perpSetup.setBaseTokenOraclePrice(vETH, usdcUnits(10.5));
1972+
await increaseTimeAsync(ONE_DAY_IN_SECONDS);
1973+
});
1974+
1975+
it("should return correct updated settled funding", async () => {
1976+
const settledFundingBefore = await perpBasisTradingModule.settledFunding(subjectSetToken);
1977+
const pendingFundingPayment = (await perpSetup.exchange.getAllPendingFundingPayment(subjectSetToken)).mul(-1);
1978+
const expectedSettledFunding = settledFundingBefore.add(pendingFundingPayment);
1979+
1980+
const updatedSettledFunding = await subject();
1981+
1982+
expect(pendingFundingPayment).to.be.gt(ZERO);
1983+
expect(updatedSettledFunding).to.be.gt(settledFundingBefore);
1984+
expect(updatedSettledFunding).to.eq(expectedSettledFunding);
1985+
});
1986+
});
1987+
1988+
describe("when pending funding payment is negative", async () => {
1989+
describe("when absolute settled funding is less than absolute negative funding", async () => {
1990+
beforeEach(async () => {
1991+
// Move oracle price down and wait one day
1992+
await perpSetup.setBaseTokenOraclePrice(vETH, usdcUnits(9.5));
1993+
await increaseTimeAsync(ONE_DAY_IN_SECONDS);
1994+
});
1995+
1996+
it("verify testing conditions", async () => {
1997+
const settledFundingBefore = await perpBasisTradingModule.settledFunding(subjectSetToken);
1998+
const pendingFundingBefore = await perpSetup.exchange.getAllPendingFundingPayment(subjectSetToken);
1999+
2000+
expect(pendingFundingBefore.abs()).to.be.gt(settledFundingBefore);
2001+
});
2002+
2003+
it("should return correct updated settled funding (zero)", async () => {
2004+
const updatedSettledFunding = await subject();
2005+
expect(updatedSettledFunding).to.eq(ZERO);
2006+
});
2007+
});
2008+
2009+
describe("when absolute settled funding is greater then absolute negative pending funding", async () => {
2010+
beforeEach(async () => {
2011+
// Move oracle price up and wait one day
2012+
await perpSetup.setBaseTokenOraclePrice(vETH, usdcUnits(11));
2013+
await increaseTimeAsync(ONE_DAY_IN_SECONDS);
2014+
2015+
// Trade to accrue pending funding to tracked settled funding
2016+
await perpBasisTradingModule.connect(owner.wallet).tradeAndTrackFunding(
2017+
setToken.address,
2018+
vETH.address,
2019+
ether(1),
2020+
ether(10.15)
2021+
);
2022+
2023+
// Move oracle price down and wait one day
2024+
await perpSetup.setBaseTokenOraclePrice(vETH, usdcUnits(9.8));
2025+
await increaseTimeAsync(ONE_DAY_IN_SECONDS);
2026+
});
2027+
2028+
it("verify testing conditions", async () => {
2029+
const settledFundingBefore = await perpBasisTradingModule.settledFunding(subjectSetToken);
2030+
const pendingFundingBefore = await perpSetup.exchange.getAllPendingFundingPayment(subjectSetToken);
2031+
2032+
expect(settledFundingBefore.abs()).to.be.gt(pendingFundingBefore.abs());
2033+
});
2034+
2035+
it("should return correct updated settled funding", async () => {
2036+
const settledFundingBefore = await perpBasisTradingModule.settledFunding(subjectSetToken);
2037+
const pendingFundingPayment = (await perpSetup.exchange.getAllPendingFundingPayment(subjectSetToken)).mul(-1);
2038+
const expectedSettledFunding = settledFundingBefore.add(pendingFundingPayment);
2039+
2040+
const updatedSettledFunding = await subject();
2041+
2042+
expect(pendingFundingPayment).to.be.lt(ZERO);
2043+
expect(updatedSettledFunding).to.be.lt(settledFundingBefore);
2044+
expect(updatedSettledFunding).to.eq(expectedSettledFunding);
2045+
});
2046+
});
2047+
});
2048+
});
2049+
19192050
describe("#updateFeeRecipient", async () => {
19202051
let setToken: SetToken;
19212052
let isInitialized: boolean;

0 commit comments

Comments
 (0)