OrderBookV2
OrderBookV2
Order book for Domination Finance perpetual exchange.
Allows users to create/edit/cancel orders with triggers. Once
conditions are met for a user's order to be executed, an order bot
will call executeOrder
to change a position on their behalf.
Addresses
Chain | Address |
---|---|
Arbitrum Sepolia | 0xde7E8B39578676d9c1dFE397a88B15b1340a968D |
Zircuit | 0x093E71778e837465366690855f5B1360b62181AE |
Functions
constructor
constructor(
uint256 _minExecutionFee,
contract IDomFiPerp _domFiPerp,
contract IDomFiVault _domFiVault,
contract IPriceFeed _oracle,
contract IFeeCalculator _feeCalculator,
contract IFeeReferral _feeReferral
) public
setOracle
Update the stored price feed. Admin only.
function setOracle(contract IPriceFeed _oracle) external
setFeeCalculator
Update the stored IFeeCalculator. Admin only.
function setFeeCalculator(contract IFeeCalculator _feeCalculator) external
setMinExecutionFee
Update the minimum execution fee. Admin only.
function setMinExecutionFee(uint256 _minExecutionFee) external
setAdmin
Update the contract administrator. Governance only.
function setAdmin(address _admin) external
getOrderId
Compute the global order ID for an order. Order may not exist yet.
function getOrderId(address account, OrderLabel orderLabel) public view returns (OrderId)
Parameters
Name | Type | Description |
---|---|---|
account | address | The owner of the order. |
orderLabel | OrderLabel | The user-defined label of the order. |
Return Values
Name | Type | Description |
---|---|---|
[0] | OrderId | OrderId Globally-unique order ID |
executeOrders
Execute a batch of orders. Emit ExecuteOrderError
or ExecuteOrderFailure for any that fail. See
executeOrder()
.
function executeOrders(OrderId[] _orderIndices, address payable _feeReceiver) external
Parameters
Name | Type | Description |
---|---|---|
_orderIndices | OrderId[] | List of OrderIds to execute |
_feeReceiver | address payable | Desired order.executionFee recipient for all orders |
cancelOrders
Cancel one or more orders and return collateral to their owners.
function cancelOrders(OrderId[] _orderIndices) external
Parameters
Name | Type | Description |
---|---|---|
_orderIndices | OrderId[] | OrderIds to cancel. Log an error for each order that fails to cancel. |
createOrders
Create one or more orders for msg.sender
. Caller must either
approve the total order.collateralSubmitted
to OrderBook or include
sufficient approval in _signature
. Caller must also submit the total
order.executionFee
, in network tokens, with this function call. Any
extra network tokens submitted beyond that amount are lost.
function createOrders(
struct OrderBookV2.OrderParams[] _orderParams,
struct OrderBookV2.Signature _signature
) external payable
Parameters
Name | Type | Description |
---|---|---|
_orderParams | struct OrderBookV2.OrderParams[] | OrderParams for each order. |
_signature | struct OrderBookV2.Signature | Optional EIP-2612 Signature. |
checkValidUnresolved
Before editing an order, must check that
- it has a
submittedAt
(i.e., it's not all 0s) - it hasn't been marked executed/canceled/expired
function checkValidUnresolved(struct OrderBookV2.Order order) internal view
checkValidCondition
Revert if a Condition is malformed. Conditions must contain the relevant field(s) for their Metric and no others.
function checkValidCondition(
struct OrderBookV2.Condition trigger,
uint256 triggerIndex,
struct OrderBookV2.Action[] actions
) internal view
zeroes are allowed for target values
Parameters
Name | Type | Description |
---|---|---|
trigger | struct OrderBookV2.Condition | Condition to check |
triggerIndex | uint256 | index of this trigger (to bubble up in errors) |
actions | struct OrderBookV2.Action[] | list of actions |
storeActions
Store order actions, reverting if any are malformed. Actions must contain the relevant field(s) for their ActionType and no others. When updating an order, new Actions must be the same types as the old.
function storeActions(
struct OrderBookV2.Action[] actionStorage,
struct OrderBookV2.Action[] newActions,
uint256 triggerLength,
OrderLabel orderLabel,
bool pushNewActions
) internal
zeroes are allowed since DomFiPerp allows it. You probably shouldn't try to change a position by 0 though.
Parameters
Name | Type | Description |
---|---|---|
actionStorage | struct OrderBookV2.Action[] | storage location for these action. |
newActions | struct OrderBookV2.Action[] | new actions to create or update in storage |
triggerLength | uint256 | length of trigger list |
orderLabel | OrderLabel | label of the parent order. CANCEL_ORDER actions cannot target their own order |
pushNewActions | bool | if we are filling blank data or updating an order |
_getDecreaseMarginFromAction
get margin & positionId params to call perp.decreasePreview
function _getDecreaseMarginFromAction(
address user,
struct OrderBookV2.Action action
) internal view returns (
uint256 closeMargin,
PositionId positionId
)
Parameters
Name | Type | Description |
---|---|---|
user | address | address of account |
action | struct OrderBookV2.Action | storage action (DECREASE_SIZE) |
checkValidTrigger
Revert if the supplied trigger is invalid; if it
- contains a cycle
- references nonexistent triggers or conditions
function checkValidTrigger(
struct OrderBookV2.Trigger[] triggers,
uint256 root,
uint256 parent,
uint256 leafArrayLength
) internal
For now, we just traverse it. This will fail with an out of gas error if it contains a cycle. We should probably handle the stack ourselves, which would also allow us to check that each Condition has been visited. Unused Conditions don't break a trigger set, but they are almost certainly mistakes.
Parameters
Name | Type | Description |
---|---|---|
triggers | struct OrderBookV2.Trigger[] | Stored triggers to check |
root | uint256 | Starting index |
parent | uint256 | Node which lead to root |
leafArrayLength | uint256 | length of order.conditions |
conditionSatisfied
Evaluate the specified Condition.
function conditionSatisfied(
struct OrderBookV2.Condition condition,
struct OrderBookV2.Action[] actions,
uint256 triggerIndex,
address owner
) internal returns (
bool executable
)
Parameters
Name | Type | Description |
---|---|---|
condition | struct OrderBookV2.Condition | Condition to evaluate |
actions | struct OrderBookV2.Action[] | List of actions for reference by REALIZED_PNL_RATE and EXECUTION_PRICE conditions |
triggerIndex | uint256 | condition 's index within order.conditions ; for logging. |
owner | address |
Return Values
Name | Type | Description |
---|---|---|
executable | bool | True if this trigger is active; false if not |
checkActiveTrigger
Return boolean combination of recursive checkActiveTrigger
calls, or conditionSatisfied
for a leaf,
for the specified Trigger.
function checkActiveTrigger(
struct OrderBookV2.Trigger[] triggers,
struct OrderBookV2.Condition[] conditions,
struct OrderBookV2.Action[] actions,
uint256 root,
address owner
) internal returns (
bool executable
)
Parameters
Name | Type | Description |
---|---|---|
triggers | struct OrderBookV2.Trigger[] | List of Triggers |
conditions | struct OrderBookV2.Condition[] | List of Conditions, which leaf indices point to |
actions | struct OrderBookV2.Action[] | List of Actions passed to checkActiveTrigger |
root | uint256 | Check triggers[root] |
owner | address |
Return Values
Name | Type | Description |
---|---|---|
executable | bool | True if root Trigger has triggered; false if it has not. |
cancelOrder
Cancel an order, refunding any submitted collateral and execution fee to the owner. Unless the caller is the order's owner, reverts if the order's cancelation trigger is not active.
function cancelOrder(OrderId _orderId, address proxySender) external
Parameters
Name | Type | Description |
---|---|---|
_orderId | OrderId | Global ID of order to cancel |
proxySender | address | If this is a recursive call, the address of the external caller. Otherwise ignored. |
_cancelOrder
Cancel a single order.
function _cancelOrder(OrderId _orderId, address collateralRecipient, address sender) internal
Parameters
Name | Type | Description |
---|---|---|
_orderId | OrderId | Global ID of order to cancel |
collateralRecipient | address | Address to receive collateral refund |
sender | address | The ultimate originator of this call. If it's the owner, skip checking the cancelation trigger. |
updateOrder
Tweak parameters of a pending order belonging to the sender. Any
network tokens sent increase the order's stored executionFee
.
function updateOrder(
OrderLabel orderLabel,
uint256 _newSubmittedCollateral,
struct OrderBookV2.Action[] _newActions,
struct OrderBookV2.Condition[] _newConditions,
struct OrderBookV2.Trigger[] _newTriggers,
bytes _userData,
struct OrderBookV2.Signature _signature
) external payable
Parameters
Name | Type | Description |
---|---|---|
orderLabel | OrderLabel | User-defined label of the order to modify. |
_newSubmittedCollateral | uint256 | New total for collateral submitted |
_newActions | struct OrderBookV2.Action[] | Updated list of actions. Cannot add new ones or change their types. If additional collateral will be required, must approve() it beforehand or fill out _signature . |
_newConditions | struct OrderBookV2.Condition[] | Updated list of conditions. Cannot add new ones or change their types. |
_newTriggers | struct OrderBookV2.Trigger[] | Updated trigger dependency logic. Cannot change length. |
_userData | bytes | Updated user data, for use in off-chain tagging |
_signature | struct OrderBookV2.Signature | Optional signature for additional collateral |
executeOrder
Execute each Action in an Order (unless action.skipIf
commands
otherwise), return any excess collateral to the order's owner, and mark
the order as executed. See executeOrders()
.
function executeOrder(OrderId _orderId, address payable _feeReceiver) public
Reverts if:
- the order has already been canceled or executed
- the order does not exist
- the order is not ready to execute (
EXECUTION_TRIGGER
untriggered) - evaluation of
EXECUTION_TRIGGER
or anyskipIf
Trigger fails - execution of any action fails
Parameters
Name | Type | Description |
---|---|---|
_orderId | OrderId | Global OrderId of the order to execute |
_feeReceiver | address payable | Desired recipient of order.executionFee |
canExecute
function canExecute(OrderId orderIndex) external returns (bool executable)
canCancel
function canCancel(OrderId orderIndex) external returns (bool executable)
checkInsufficientCollateral
Revert if an order definitely lacks enough collateral to execute.
Orders which pass this check still might not execute, since we can't
know the results of DECREASE_SIZE, or whether a skipIf
action will
skip, before execution.
function checkInsufficientCollateral(struct OrderBookV2.Order order) internal view
This could be integrated into the other per-action loops, but it's easier to reuse and reason about if it's separate. We check trade fees at the current rate, so orders which depend on a future decrease in trade fees will revert. Sorry.
Parameters
Name | Type | Description |
---|---|---|
order | struct OrderBookV2.Order | Order with actions and collateralSubmitted to check |
getOrder
Finds an order by its global order ID.
function getOrder(OrderId orderId) external view returns (struct OrderBookV2.Order order)
Use order.submittedAt != 0
to determine if the order exists.
Parameters
Name | Type | Description |
---|---|---|
orderId | OrderId | The global order ID. |
Return Values
Name | Type | Description |
---|---|---|
order | struct OrderBookV2.Order | The order if one was submitted with the provided global order ID. Otherwise, an empty order is returned. |
getOrderStatus
Determine the OrderStatus of a submitted order.
function getOrderStatus(OrderId orderId) internal view returns (enum OrderBookV2.OrderStatus status)
Parameters
Name | Type | Description |
---|---|---|
orderId | OrderId | The global order ID. |
Return Values
Name | Type | Description |
---|---|---|
status | enum OrderBookV2.OrderStatus | The status of the order or OrderStatus.UNINITIALIZED if it doesn't exist. |
onlyAdmin
function onlyAdmin() internal view
Events
CreateOrder
event CreateOrder(address account, OrderId orderId, struct OrderBookV2.Order order)
CancelOrder
event CancelOrder(address account, OrderId orderId, struct OrderBookV2.Order order)
CancelOrderError
event CancelOrderError(OrderId orderId, string executionError)
CancelOrderFailure
event CancelOrderFailure(OrderId orderId, bytes lowLevelData)
UpdateOrder
event UpdateOrder(address account, OrderId orderId, struct OrderBookV2.Order newOrder)
ExecuteOrder
event ExecuteOrder(address account, OrderId orderId, struct OrderBookV2.Order order)
ExecuteAction
event ExecuteAction(address account, OrderId orderId, uint256 actionIndex, struct OrderBookV2.Action action)
ExecuteOrderError
event ExecuteOrderError(OrderId orderId, string executionError)
ExecuteOrderFailure
event ExecuteOrderFailure(OrderId orderId, bytes lowLevelData)
UpdateMinExecutionFee
event UpdateMinExecutionFee(uint256 minExecutionFee)
UpdateAdmin
event UpdateAdmin(address admin)
Errors
ContractOnly
error ContractOnly()
AdminOnly
error AdminOnly()
OrderOwnerOnly
error OrderOwnerOnly()
ArrayLengthMismatch
error ArrayLengthMismatch()
ActionLengthMismatch
error ActionLengthMismatch()
ConditionLengthMismatch
error ConditionLengthMismatch()
TriggerLengthMismatch
error TriggerLengthMismatch()
OrderLabelMissing
error OrderLabelMissing(uint256 argIndex)
OrderLabelUsed
error OrderLabelUsed(uint256 argIndex)
ExecutionFeeBelowMinimum
error ExecutionFeeBelowMinimum(uint256 argIndex)
ExecutionFeeInsufficient
error ExecutionFeeInsufficient(uint256 argIndex)
InsufficientCollateralSupplied
Execution of this order is guaranteed to fail unless you submit it with more collateral.
error InsufficientCollateralSupplied(
uint256 failingActionIndex,
uint256 collateralAtActionIndex,
uint256 collateralRequiredByAction
)
Parameters
Name | Type | Description |
---|---|---|
failingActionIndex | uint256 | |
collateralAtActionIndex | uint256 | collateral available to this action during execution |
collateralRequiredByAction | uint256 | collateral this action would need to succeed |
PositionIdMissing
error PositionIdMissing()
IrrelevantConditionDetails
error IrrelevantConditionDetails(uint256 triggerIndex)
MissingConditionDetails
error MissingConditionDetails(uint256 triggerIndex)
InvalidConditionDetails
error InvalidConditionDetails(uint256 triggerIndex)
InvalidConditionType
error InvalidConditionType()
OutOfCollateral
error OutOfCollateral(uint256 actionIndex)
IrrelevantActionDetails
error IrrelevantActionDetails(uint256 actionIndex)
MissingActionDetails
error MissingActionDetails(uint256 actionIndex)
ActionTypeMismatch
error ActionTypeMismatch(uint256 actionIndex)
InvalidActionSkipIf
error InvalidActionSkipIf(uint256 actionIndex)
IrrelevantTriggerDetails
error IrrelevantTriggerDetails(uint256 triggerIndex)
InvalidTriggerDetails
error InvalidTriggerDetails(uint256 triggerIndex)
UninitializedOrder
error UninitializedOrder()
UninitializedPosition
Attempted to decrease a position, or preview doing so, but the
position did not exist. Consider using a POSITION_EXISTS
trigger or
skipIf
if you want to do something else.
error UninitializedPosition()
OrderCanceled
error OrderCanceled()
OrderExecuted
Order could not be canceled because it's already been executed
error OrderExecuted()
OrderExpired
error OrderExpired()
TriggerUnmet
error TriggerUnmet()
AddressUnset
error AddressUnset()
EmptyTriggers
error EmptyTriggers()
EmptyConditions
error EmptyConditions()
InvalidOrderNumber
error InvalidOrderNumber()
InvalidOrderLabel
error InvalidOrderLabel()
NoCancelationTrigger
This order has only one Trigger
. The first Trigger
represents the execution criteria and the second represents the
cancelation criteria.
If you were trying to make an order that can never be canceled, set the
second Trigger
with an impossible trigger like TIME
<= 0.
If you want to make an order with the exact same cancelation and
execution criteria, make the second Trigger
a duplicate of the
first. Such an order will execute or cancel based on the whims of bot
operators.
error NoCancelationTrigger()
OrderUnexpired
error OrderUnexpired()
Variables
DONT_SKIP
Actions with skipIf==DONT_SKIP
won't skip
uint256 DONT_SKIP = type(uint256).max;
SKIP
Actions with skipIf==SKIP
skip without evaluating
uint256 SKIP = type(uint256).max - 1;
EXECUTION_TRIGGER
The first entry in order.triggers
says whether it is executable.
uint256 EXECUTION_TRIGGER = 0;
CANCELATION_TRIGGER
The second entry in order.triggers
says whether it can be canceled.
uint256 CANCELATION_TRIGGER = 1;
domFiVault
IDomFiVault
used for DEPOSIT
and WITHDRAW
actions.
domFiPerp
IDomFiPerp
used for position triggers and actions.
feeReferral
IFeeReferral
used for SET_REFERRER
actions.
collateralToken
Collateral token collected by orders; used for positions and vault deposits.
admin
Administrator permitted to update stored addresses and parameters of this contract. Updatable by governance.
oracle
IPriceFeed
used for price triggers.
feeCalculator
IFeeCalculator
used to calculate total cost of INCREASE_SIZE
actions.
minExecutionFee
The minimum execution fee, below which order submissions will be rejected with ExecutionFeeBelowMinimum.
Types
Metric
The type of a Condition
Values
Name | Description |
---|---|
INVALID | Revert if encountered. Guards against accidental 0x00 |
PRICE | Compare price of a product vs a specified price |
PNL_RATE | Compare PnL of a position vs a specified % |
TIME | Compare current time to a specified timestamp |
FUNDING_RATE | Compare funding rate of a product to a specified APY |
REALIZED_PNL_RATE | Compare PnL of a decrease to a specified % |
EXECUTION_PRICE | Compare execution price of an increase/decrease to a specified price |
ORDER_STATUS | Compare status of an order to an OrderStatus |
POSITION_EXISTS |
enum Metric {
INVALID,
PRICE,
PNL_RATE,
TIME,
FUNDING_RATE,
REALIZED_PNL_RATE,
EXECUTION_PRICE,
ORDER_STATUS,
POSITION_EXISTS
}
OrderStatus
The status of an order.
Values
Name | Description |
---|---|
UNINITIALIZED | The order has not yet been created. |
PENDING | The order has been submitted and is pending. |
EXECUTED | The order has been executed. |
CANCELED | The order has been cancelled. |
enum OrderStatus {
UNINITIALIZED,
PENDING,
EXECUTED,
CANCELED
}
Comparator
Whether a condition should activate below or above a value
Metric.ORDER_STATUS
and POSITION_EXISTS
interpret any
trigger condition as EQ, since order/position statuses aren't ordinal.
Values
Name | Description |
---|---|
LTE | Activate if the current value is <= the target value |
GTE | Activate if the current value is >= the target value |
enum Comparator {
LTE,
GTE
}
Condition
An on-chain condition, which provides a TRUE/FALSE value to one or more Triggers
Fields
Name | Type | Description |
---|---|---|
metric | enum OrderBookV2.Metric | The type of comparison to make |
comparator | enum OrderBookV2.Comparator | should trigger >= or <= threshold? |
targetValue | bytes32 | A target value, to be compared with conditions on chain. Interpreted based on metric :
|
dataSource | bytes32 | The source of an on-chain value to compare with the target. Interpreted based on metric :
|
struct Condition {
enum OrderBookV2.Metric metric;
enum OrderBookV2.Comparator comparator;
bytes32 targetValue;
bytes32 dataSource;
}
Operator
The type of an Trigger
Values
Name | Description |
---|---|
OR | Operator: combines Triggers OR(left, right) |
AND | Operator: combines Triggers AND(left, right) |
NOT | Operator: modifies Trigger NOT(left) |
LEAF | Leaf: returns true if the underlying Condition has triggered |
enum Operator {
OR,
AND,
NOT,
LEAF
}
Trigger
Either a boolean combination of 1-2 other Triggers, or one Condition. Each order has one Trigger for execution, and one that triggers automatic cancelation.
Fields
Name | Type | Description |
---|---|---|
operator | enum OrderBookV2.Operator | The type of this Trigger: boolean operator or leaf |
leftTriggerIndex | uint256 | For operators, the "left" child Trigger |
rightTriggerIndex | uint256 | For operators, the "right" child. 0 for NOT |
leafIndex | uint256 | If this is a LEAF, the index of the underlying Condition |
struct Trigger {
enum OrderBookV2.Operator operator;
uint256 leftTriggerIndex;
uint256 rightTriggerIndex;
uint256 leafIndex;
}
ActionType
The type of an Action
Values
Name | Description |
---|---|
INCREASE_SIZE | call DomFiPerp.increasePosition |
DECREASE_SIZE | call DomFiPerp.decreasePositionWithId |
ADD_MARGIN | call DomFiPerp.increasePosition with 0 leverage |
REMOVE_MARGIN | call DomFiPerp.removeMargin |
DEPOSIT | call DomFiVault.deposit |
WITHDRAW | call DomFiVault.withdraw |
SET_REFERRER | call FeeReferral.setReferrer |
CANCEL_ORDER | cancel another order |
enum ActionType {
INCREASE_SIZE,
DECREASE_SIZE,
ADD_MARGIN,
REMOVE_MARGIN,
DEPOSIT,
WITHDRAW,
SET_REFERRER,
CANCEL_ORDER
}
Action
One of a series of actions taken during execution of an order. Each Action instance must contain only the relevant fields for its type.
Fields
Name | Type | Description |
---|---|---|
actionType | enum OrderBookV2.ActionType | See OrderBook.ActionType |
primaryTarget | bytes32 | This slot is:
|
fixedMargin | uint256 | This slot is:
|
marginFraction | FPUnsigned | This slot is:
|
productId | bytes32 | Required for INCREASE_SIZE only, since we might be creating a new position |
isLong | bool | Required for INCREASE_SIZE only, since we might be creating a new position |
leverage | FPUnsigned | This slot is:
|
skipIf | uint256 | Either SKIP , DONT_SKIP , or an index in Order.triggers. If skipIf specifies a Trigger and it's active, this action will be skipped. |
struct Action {
enum OrderBookV2.ActionType actionType;
bytes32 primaryTarget;
uint256 fixedMargin;
FPUnsigned marginFraction;
bytes32 productId;
bool isLong;
FPUnsigned leverage;
uint256 skipIf;
}
Order
A user order on the exchange.
Fields
Name | Type | Description |
---|---|---|
owner | address payable | The creator and beneficiary of this order. |
label | OrderLabel | Identifying label of this order. Unique per user. |
executionFee | uint256 | Amount of network token reimbursed to order executor |
collateralSubmitted | uint256 | User-provided collateral available to actions |
submittedAt | uint64 | Unix timestamp, in seconds, of last update. |
canceledAt | uint64 | Unix timestamp, in seconds, of cancelation. 0 if not yet canceled. |
executedAt | uint64 | Unix timestamp, in seconds, of execution. 0 if not yet executed. |
triggers | struct OrderBookV2.Trigger[] | A list of Triggers. The first in the list represents the execution criteria; when it triggers anybody can execute the order. The second represents the cancelation criteria; when it triggers anybody can cancel the order. |
conditions | struct OrderBookV2.Condition[] | A list of Conditions referenced by triggers . |
actions | struct OrderBookV2.Action[] | A list of Actions that will be taken when the order executes. |
userData | bytes | User-specified data to attach to the order. |
struct Order {
address payable owner;
OrderLabel label;
uint256 executionFee;
uint256 collateralSubmitted;
uint64 submittedAt;
uint64 canceledAt;
uint64 executedAt;
struct OrderBookV2.Trigger[] triggers;
struct OrderBookV2.Condition[] conditions;
struct OrderBookV2.Action[] actions;
bytes userData;
}
Signature
a signature for use with EIP-2612
struct Signature {
uint256 amount;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
OrderParams
Parameters to create an order. The same thing as Order,
except it does not include owner
(set to msg.sender
) or any of the
timestamp fields (which users cannot modify directly).
struct OrderParams {
OrderLabel label;
uint256 executionFee;
uint256 collateralSubmitted;
struct OrderBookV2.Trigger[] triggers;
struct OrderBookV2.Condition[] conditions;
struct OrderBookV2.Action[] actions;
bytes userData;
}
OrderId
bytes32
globally-unique ID of an order. See getOrderId
.
OrderLabel
bytes16
arbitrary user label for an order.