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

Remove absolute position update #512

Merged
merged 35 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
46a8952
remove absolute position update, add maker delta update and updated c…
prateekdefi Dec 11, 2024
2781eea
update multiInvoker contracts
prateekdefi Dec 11, 2024
388dcb7
update vault contracts
prateekdefi Dec 11, 2024
a362d40
update test marketHelpers
prateekdefi Dec 11, 2024
50da105
fix maker referral fee
prateekdefi Dec 11, 2024
e830d03
fix multiInvoker integration tests
prateekdefi Dec 11, 2024
a509791
fix collateral accounts integration tests
prateekdefi Dec 11, 2024
f390103
fix trigger orders integration tests
prateekdefi Dec 11, 2024
574cc30
fix vault integration tests
prateekdefi Dec 11, 2024
74e1564
fix oracle integration tests
prateekdefi Dec 11, 2024
bd95dea
update workflow to run tests on CI
prateekdefi Dec 11, 2024
255fb28
add close with referrer method
prateekdefi Dec 12, 2024
5570684
update tests with new close method
prateekdefi Dec 12, 2024
7efa228
fix some core integration tests
prateekdefi Dec 12, 2024
71db5bf
Merge branch 'prateek/pe-1629-remove-magic-values' into prateek/pe-16…
prateekdefi Dec 16, 2024
722ede7
disable CI
prateekdefi Dec 16, 2024
9191e0e
update comment and remove absolute order
prateekdefi Dec 16, 2024
3404c09
update tests with delta update
prateekdefi Dec 17, 2024
2675308
Merge branch 'prateek/pe-1629-remove-magic-values' into prateek/pe-16…
prateekdefi Dec 17, 2024
58c2f0b
update workflow to run tests on CI
prateekdefi Dec 17, 2024
7fb6985
update contracts with new delta update
prateekdefi Dec 17, 2024
3856ad8
fix oracle and vault tests
prateekdefi Dec 18, 2024
09cb5cb
fix trigger order close position
prateekdefi Dec 18, 2024
4774f86
fix core integration tests
prateekdefi Dec 18, 2024
5713d01
fix core unit tests
prateekdefi Dec 20, 2024
81650f0
PR feedback
prateekdefi Dec 24, 2024
6f00446
Merge branch 'v2.4' into prateek/pe-1630-remove-absolute-position-update
prateekdefi Dec 24, 2024
6564682
fix insurance fund tests
prateekdefi Dec 24, 2024
f3b02b1
PR feedback
prateekdefi Dec 30, 2024
3cd9189
Merge branch 'v2.4' into prateek/pe-1630-remove-absolute-position-update
prateekdefi Jan 6, 2025
0878a92
fix tests
prateekdefi Jan 6, 2025
84f256c
rename position
prateekdefi Jan 8, 2025
62c630c
update workflow
prateekdefi Jan 8, 2025
b5bb7d5
Merge branch 'v2.4' into prateek/pe-1630-remove-absolute-position-update
prateekdefi Jan 9, 2025
941770a
fix 'stack too deep'
prateekdefi Jan 9, 2025
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
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
branches:
- main
- v2.4
- prateek/pe-1629-remove-magic-values
workflow_dispatch:

env:
Expand Down
71 changes: 29 additions & 42 deletions packages/core/contracts/Market.sol
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,32 @@ contract Market is IMarket, Instance, ReentrancyGuard {
Fixed6 amount,
Fixed6 collateral,
address referrer
) external nonReentrant whenNotPaused {
) external {
update(account, amount, Fixed6Lib.ZERO, collateral, referrer);
}

/// @notice Updates the account's position and collateral
/// @param account The account to operate on
/// @param taker The taker delta amount of the order (positive for long, negative for short)
/// @param maker The maker delta amount of the order
/// @param collateral The collateral delta of the order (positive for deposit, negative for withdrawal)
/// @param referrer The referrer of the order
function update(
address account,
Fixed6 taker,
Fixed6 maker,
prateekdefi marked this conversation as resolved.
Show resolved Hide resolved
Fixed6 collateral,
address referrer
) public nonReentrant whenNotPaused {
(Context memory context, UpdateContext memory updateContext) =
_loadForUpdate(account, address(0), referrer, address(0), UFixed6Lib.ZERO, UFixed6Lib.ZERO);

// create new order & guarantee
Order memory newOrder = OrderLib.from(
context.currentTimestamp,
updateContext.currentPositionLocal,
amount,
taker,
maker,
collateral,
updateContext.orderReferralFee
);
Expand All @@ -199,68 +216,37 @@ contract Market is IMarket, Instance, ReentrancyGuard {
_updateAndStore(context, updateContext, newOrder, newGuarantee, referrer, address(0));
}

/// @notice Updates the account's position and collateral
/// @notice Closes the account's position
/// @param account The account to operate on
/// @param newMaker The new maker position for the account
/// @param newMaker The new long position for the account
/// @param newMaker The new short position for the account
/// @param collateral The collateral amount to add or remove from the account
/// @param protect Whether to put the account into a protected status for liquidations
function update(
address account,
UFixed6 newMaker,
UFixed6 newLong,
UFixed6 newShort,
Fixed6 collateral,
bool protect
) external {
update(account, newMaker, newLong, newShort, collateral, protect, address(0));
function close(address account, bool protect) external {
close(account, protect, address(0));
}

/// @notice Updates the account's position and collateral
/// @notice Closes the account's position
/// @param account The account to operate on
/// @param newMaker The new maker position for the account
/// @param newLong The new long position for the account
/// @param newShort The new short position for the account
/// @param collateral The collateral amount to add or remove from the account
/// @param protect Whether to put the account into a protected status for liquidations
/// @param referrer The referrer of the order
function update(
address account,
UFixed6 newMaker,
UFixed6 newLong,
UFixed6 newShort,
Fixed6 collateral,
bool protect,
address referrer
) public nonReentrant whenNotPaused {
function close(address account, bool protect, address referrer) public nonReentrant whenNotPaused {
prateekdefi marked this conversation as resolved.
Show resolved Hide resolved
(Context memory context, UpdateContext memory updateContext) =
_loadForUpdate(account, address(0), referrer, address(0), UFixed6Lib.ZERO, UFixed6Lib.ZERO);

// create new order & guarantee
Order memory newOrder = OrderLib.from(
context.currentTimestamp,
updateContext.currentPositionLocal,
collateral,
newMaker,
newLong,
newShort,
Fixed6Lib.ZERO,
UFixed6Lib.ZERO,
UFixed6Lib.ZERO,
UFixed6Lib.ZERO,
protect,
updateContext.orderReferralFee
);
Guarantee memory newGuarantee; // no guarantee is created for a market order

// process update
_updateAndStore(context, updateContext, newOrder, newGuarantee, referrer, address(0));
}

/// @notice Closes the account's position
/// @param account The account to operate on
/// @param protect Whether to put the account into a protected status for liquidations
function close(address account, bool protect) external {
update(account, UFixed6Lib.ZERO, UFixed6Lib.ZERO, UFixed6Lib.ZERO, Fixed6Lib.ZERO, protect, address(0));
}

/// @notice Updates the beneficiary of the market
/// @param newBeneficiary The new beneficiary address
function updateBeneficiary(address newBeneficiary) external onlyOwner {
Expand Down Expand Up @@ -612,6 +598,7 @@ contract Market is IMarket, Instance, ReentrancyGuard {
updateContext.currentPositionLocal,
amount,
Fixed6Lib.ZERO,
Fixed6Lib.ZERO,
updateContext.orderReferralFee
);
Guarantee memory newGuarantee = GuaranteeLib.from(
Expand Down
4 changes: 2 additions & 2 deletions packages/core/contracts/interfaces/IMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ interface IMarket is IInstance {
function settle(address account) external;
function update(address account, Intent calldata intent, bytes memory signature) external;
function update(address account, Fixed6 amount, Fixed6 collateral, address referrer) external;
function update(address account, UFixed6 newMaker, UFixed6 newLong, UFixed6 newShort, Fixed6 collateral, bool protect) external;
function update(address account, UFixed6 newMaker, UFixed6 newLong, UFixed6 newShort, Fixed6 collateral, bool protect, address referrer) external;
function update(address account, Fixed6 taker, Fixed6 maker, Fixed6 collateral, address referrer) external;
function close(address account, bool protect) external;
function close(address account, bool protect, address referrer) external;
function parameter() external view returns (MarketParameter memory);
function riskParameter() external view returns (RiskParameter memory);
function updateBeneficiary(address newBeneficiary) external;
Expand Down
8 changes: 4 additions & 4 deletions packages/core/contracts/test/MockToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ import { IMarket } from "../interfaces/IMarket.sol";

contract MockToken is ERC20 {

enum Function{ SETTLE, UPDATE, UPDATE_MAKER, UPDATE_INTENT }
enum Function{ SETTLE, UPDATE, UPDATE_INTENT, CLOSE }

Function private functionToCall;

constructor() ERC20("MockToken", "MTOKEN") {}

function transferFrom(address, address, uint256) public override returns (bool) {
// call method of market contract for reentrancy
if (functionToCall == Function.UPDATE_MAKER) {
IMarket(msg.sender).update(address(0), UFixed6Lib.from(0), UFixed6Lib.from(0), UFixed6Lib.from(0), Fixed6Lib.from(0), false);
} else if (functionToCall == Function.UPDATE) {
if (functionToCall == Function.UPDATE) {
IMarket(msg.sender).update(address(0), Fixed6Lib.from(0), Fixed6Lib.from(0), address(0));
} else if (functionToCall == Function.UPDATE_INTENT) {
Intent memory intent;
IMarket(msg.sender).update(address(0), intent, "");
} else if (functionToCall == Function.SETTLE){
IMarket(msg.sender).settle(address(0));
} else if (functionToCall == Function.CLOSE) {
IMarket(msg.sender).close(address(0), false);
}

return true;
Expand Down
24 changes: 15 additions & 9 deletions packages/core/contracts/types/Order.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,32 +83,38 @@ library OrderLib {
/// @notice Creates a new order from the an intent order request
prateekdefi marked this conversation as resolved.
Show resolved Hide resolved
/// @param timestamp The current timestamp
/// @param position The current position
/// @param amount The magnitude and direction of the order
/// @param takerAmount The magnitude and direction of taker position
/// @param makerAmount The magnitude and direction of maker position
/// @param collateral The change in the collateral
/// @param referralFee The referral fee
/// @return newOrder The resulting order
function from(
uint256 timestamp,
Position memory position,
Fixed6 amount,
Fixed6 takerAmount,
prateekdefi marked this conversation as resolved.
Show resolved Hide resolved
Fixed6 makerAmount,
Fixed6 collateral,
UFixed6 referralFee
) internal pure returns (Order memory newOrder) {
newOrder.timestamp = timestamp;
newOrder.collateral = collateral;
newOrder.orders = amount.isZero() ? 0 : 1;
newOrder.takerReferral = amount.abs().mul(referralFee);
newOrder.orders = makerAmount.isZero() && takerAmount.isZero() ? 0 : 1;
newOrder.makerReferral = makerAmount.abs().mul(referralFee);
newOrder.takerReferral = takerAmount.abs().mul(referralFee);

// If the order is not counter to the current position, it is opening
if (amount.sign() == 0 || position.skew().sign() == 0 || position.skew().sign() == amount.sign()) {
newOrder.longPos = amount.max(Fixed6Lib.ZERO).abs();
newOrder.shortPos = amount.min(Fixed6Lib.ZERO).abs();
if (takerAmount.sign() == 0 || position.skew().sign() == 0 || position.skew().sign() == takerAmount.sign()) {
newOrder.longPos = takerAmount.max(Fixed6Lib.ZERO).abs();
newOrder.shortPos = takerAmount.min(Fixed6Lib.ZERO).abs();

// If the order is counter to the current position, it is closing
} else {
newOrder.shortNeg = amount.max(Fixed6Lib.ZERO).abs();
newOrder.longNeg = amount.min(Fixed6Lib.ZERO).abs();
newOrder.shortNeg = takerAmount.max(Fixed6Lib.ZERO).abs();
newOrder.longNeg = takerAmount.min(Fixed6Lib.ZERO).abs();
}

newOrder.makerPos = makerAmount.max(Fixed6Lib.ZERO).abs();
newOrder.makerNeg = makerAmount.min(Fixed6Lib.ZERO).abs();
prateekdefi marked this conversation as resolved.
Show resolved Hide resolved
}

/// @notice Creates a new order from the current position and an update request
Expand Down
32 changes: 13 additions & 19 deletions packages/core/test/integration/core/closedProduct.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from 'chai'
import 'hardhat'
import { BigNumber, constants } from 'ethers'
const { AddressZero } = constants

Check warning on line 4 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'AddressZero' is assigned a value but never used

import { InstanceVars, deployProtocol, createMarket, settle } from '../helpers/setupHelpers'
import { Market } from '../../../types/generated'
Expand All @@ -21,13 +21,13 @@
it('closes the market', async () => {
const POSITION = parse6decimal('10')
const COLLATERAL = parse6decimal('1000')
const { owner, user, dsu, chainlink, beneficiaryB } = instanceVars

Check warning on line 24 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'beneficiaryB' is assigned a value but never used

const market = await createMarket(instanceVars)
await dsu.connect(user).approve(market.address, COLLATERAL.mul(1e12))
await market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, POSITION, 0, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](user.address, 0, POSITION, COLLATERAL, constants.AddressZero)

expect((await market.parameter()).closed).to.be.false

Expand All @@ -49,17 +49,17 @@
const COLLATERAL = parse6decimal('1000')

beforeEach(async () => {
const { user, userB, dsu, beneficiaryB } = instanceVars

Check warning on line 52 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'beneficiaryB' is assigned a value but never used

market = await createMarket(instanceVars)
await dsu.connect(user).approve(market.address, COLLATERAL.mul(1e12))
await dsu.connect(userB).approve(market.address, COLLATERAL.mul(1e12))
await market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, POSITION, 0, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](user.address, 0, POSITION, COLLATERAL, constants.AddressZero)
await market
.connect(userB)
['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, POSITION, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](userB.address, POSITION, 0, COLLATERAL, constants.AddressZero)
const parameters = { ...(await market.parameter()) }
parameters.closed = true
await market.updateParameter(parameters)
Expand All @@ -73,7 +73,7 @@
await expect(
market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, 0, POSITION, 0, 0, false),
['update(address,int256,int256,int256,address)'](user.address, POSITION, 0, 0, constants.AddressZero),
).to.be.revertedWithCustomError(market, 'MarketClosedError')
})

Expand All @@ -82,28 +82,24 @@

await chainlink.next()

await expect(
await market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, 0, 0, 0, 0, false),
).to.not.be.reverted
await expect(await market.connect(user)['close(address,bool)'](user.address, false)).to.not.be.reverted
})
})

it('zeroes PnL and fees', async () => {
const POSITION = parse6decimal('10')
const COLLATERAL = parse6decimal('1000')
const { user, userB, chainlink, dsu, beneficiaryB } = instanceVars

Check warning on line 92 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'beneficiaryB' is assigned a value but never used

const market = await createMarket(instanceVars)
await dsu.connect(user).approve(market.address, COLLATERAL.mul(1e12))
await dsu.connect(userB).approve(market.address, COLLATERAL.mul(1e12))
await market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, POSITION, 0, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](user.address, 0, POSITION, COLLATERAL, constants.AddressZero)
await market
.connect(userB)
['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, POSITION, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](userB.address, POSITION, 0, COLLATERAL, constants.AddressZero)

await chainlink.next()
await chainlink.next()
Expand All @@ -122,9 +118,9 @@
await chainlink.nextWithPriceModification(price => price.mul(4))
await chainlink.nextWithPriceModification(price => price.mul(4))

const LIQUIDATION_FEE = BigNumber.from('1000000000')

Check warning on line 121 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'LIQUIDATION_FEE' is assigned a value but never used
await market.connect(user)['update(address,uint256,uint256,uint256,int256,bool)'](user.address, 0, 0, 0, 0, true)
await market.connect(userB)['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, 0, 0, 0, true)
await market.connect(user)['close(address,bool)'](user.address, true)
await market.connect(userB)['close(address,bool)'](userB.address, true)

expect((await market.locals(user.address)).collateral).to.equal(userCollateralBefore)
expect((await market.locals(userB.address)).collateral).to.equal(userBCollateralBefore)
Expand All @@ -136,23 +132,21 @@
it('handles closing during liquidations', async () => {
const POSITION = parse6decimal('10')
const COLLATERAL = parse6decimal('1000')
const { user, userB, chainlink, dsu, beneficiaryB } = instanceVars

Check warning on line 135 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'beneficiaryB' is assigned a value but never used

const market = await createMarket(instanceVars)
await dsu.connect(user).approve(market.address, COLLATERAL.mul(1e12))
await dsu.connect(userB).approve(market.address, COLLATERAL.mul(1e12))
await market
.connect(user)
['update(address,uint256,uint256,uint256,int256,bool)'](user.address, POSITION, 0, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](user.address, 0, POSITION, COLLATERAL, constants.AddressZero)
await market
.connect(userB)
['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, POSITION, 0, COLLATERAL, false)
['update(address,int256,int256,int256,address)'](userB.address, POSITION, 0, COLLATERAL, constants.AddressZero)

await chainlink.next()
await chainlink.nextWithPriceModification(price => price.mul(2))
await expect(
market.connect(userB)['update(address,uint256,uint256,uint256,int256,bool)'](user.address, 0, 0, 0, 0, true),
).to.not.be.reverted
await expect(market.connect(userB)['close(address,bool)'](user.address, true)).to.not.be.reverted
expect((await market.pendingOrders(user.address, 2)).protection).to.eq(1)
const parameters = { ...(await market.parameter()) }
parameters.closed = true
Expand All @@ -173,9 +167,9 @@
await chainlink.nextWithPriceModification(price => price.mul(4))
await chainlink.nextWithPriceModification(price => price.mul(4))

const LIQUIDATION_FEE = BigNumber.from('1000000000')

Check warning on line 170 in packages/core/test/integration/core/closedProduct.test.ts

View workflow job for this annotation

GitHub Actions / Lint

'LIQUIDATION_FEE' is assigned a value but never used
await settle(market, user)
await market.connect(userB)['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, 0, 0, 0, true)
await market.connect(userB)['close(address,bool)'](userB.address, true)

expect((await market.locals(user.address)).collateral).to.equal(userCollateralBefore)
expect((await market.locals(userB.address)).collateral).to.equal(userBCollateralBefore)
Expand Down
Loading
Loading