Skip to content

Commit

Permalink
unify orders interface
Browse files Browse the repository at this point in the history
  • Loading branch information
mn13 committed Dec 28, 2024
1 parent fa1a427 commit d334e4c
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 66 deletions.
8 changes: 5 additions & 3 deletions solidity/orders/script/CreateOrder.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@ contract CreateOrder is Script {
expectedRejectExpression: string(expectedRejectExpression)
});
CommonTypes.Coin[] memory maxKeychainFees = new CommonTypes.Coin[](0);
Types.OrderData memory orderData = Types.OrderData({
Types.BasicOrderData memory orderData = Types.BasicOrderData({
thresholdPrice: thresholdPrice,
priceCondition: priceCondition,
pricePair: pricePair,
pricePair: pricePair
});
Types.CommonExecutionData memory commonExecutionData = Types.CommonExecutionData({
creatorDefinedTxFields: creatorDefinedTxFields,
signRequestData: signRequestData
});
Expand All @@ -66,7 +68,7 @@ contract CreateOrder is Script {
mockSlinkyPrecompile.setPrice(pricePair.base, pricePair.quote, thresholdPrice);
vm.etch(IWARDEN_PRECOMPILE_ADDRESS, address(wPrecompile).code);
vm.startBroadcast(broadcaster);
FACTORY.createOrder(orderData, maxKeychainFees, OrderType.Basic, salt);
FACTORY.createOrder(abi.encode(orderData), commonExecutionData, maxKeychainFees, OrderType.Basic, salt);

vm.stopBroadcast();
}
Expand Down
40 changes: 27 additions & 13 deletions solidity/orders/src/AdvancedOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ pragma solidity >=0.8.25 <0.9.0;

import { GetPriceResponse, ISlinky, ISLINKY_PRECOMPILE_ADDRESS } from "precompile-slinky/ISlinky.sol";
import { IAsync, IASYNC_PRECOMPILE_ADDRESS } from "precompile-async/IAsync.sol";
import { Types as CommonTypes } from "precompile-common/Types.sol";
import { AbstractOrder } from "./AbstractOrder.sol";
import { Caller, ExecutionData, IExecution } from "./IExecution.sol";
import { Registry } from "./Registry.sol";
import { Types } from "./Types.sol";

error ConditionNotMet();
error ExecutedError();
error Unauthorized();

event Executed();

contract AdvancedOrder is AbstractOrder, IExecution {
Types.OrderData public orderData;
Types.AdvancedOrderData public orderData;
Types.CommonExecutionData public commonExecutionData;

ISlinky private immutable SLINKY_PRECOMPILE;
IAsync private immutable ASYNC_PRECOMPILE;
Expand All @@ -20,12 +30,13 @@ contract AdvancedOrder is AbstractOrder, IExecution {
uint256 private _validUntil;

constructor(
Types.OrderData memory _orderData,
Types.AdvancedOrderData memory _orderData,
Types.CommonExecutionData memory _executionData,
CommonTypes.Coin[] memory maxKeychainFees,
address scheduler,
address registry
)
AbstractOrder(_orderData.signRequestData, _orderData.creatorDefinedTxFields, scheduler, registry)
AbstractOrder(_executionData.signRequestData, _executionData.creatorDefinedTxFields, scheduler, registry)
{
SLINKY_PRECOMPILE = ISlinky(ISLINKY_PRECOMPILE_ADDRESS);
SLINKY_PRECOMPILE.getPrice(_orderData.pricePair.base, _orderData.pricePair.quote);
Expand All @@ -39,13 +50,14 @@ contract AdvancedOrder is AbstractOrder, IExecution {
}

orderData = _orderData;
commonExecutionData = _executionData;
_scheduler = scheduler;
_callers.push(Caller.Scheduler);
_validUntil = block.timestamp + 24 hours;
}

function canExecute() external view override returns (bool) {
if(block.timestamp > _validUntil) {
function canExecute() public view override returns (bool) {
if (block.timestamp > _validUntil) {
return false;
}
// TODO:
Expand All @@ -69,7 +81,11 @@ contract AdvancedOrder is AbstractOrder, IExecution {
uint256,
uint256 maxPriorityFeePerGas,
uint256 maxFeePerGas
) external override returns (bool, bytes32) {
)
external
override
returns (bool, bytes32)
{
if (msg.sender != _scheduler) {
revert Unauthorized();
}
Expand All @@ -84,14 +100,14 @@ contract AdvancedOrder is AbstractOrder, IExecution {

bytes[] memory emptyAccessList = new bytes[](0);
(bytes memory unsignedTx, bytes32 txHash) = this.encodeUnsignedEIP1559(
nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, orderData.creatorDefinedTxFields
nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, commonExecutionData.creatorDefinedTxFields
);

_unsignedTx = unsignedTx;

bytes memory signRequestInput = abi.encodePacked(txHash);

_executed = this.createSignRequest(orderData.signRequestData, signRequestInput, _coins);
_executed = this.createSignRequest(commonExecutionData.signRequestData, signRequestInput, _coins);

if (_executed) {
emit Executed();
Expand All @@ -102,20 +118,18 @@ contract AdvancedOrder is AbstractOrder, IExecution {
REGISTRY.addTransaction(tx.origin, txHash);

return (_executed, txHash);

}

function callers() external view override returns (Caller[] memory callersList) {
return _callers;
}

function isExecuted() external view override returns (bool) {
function isExecuted() public view override returns (bool) {
return _executed;
}


function executionData() external view returns (ExecutionData memory data) {
data = this.buildExecutionData(orderData.creatorDefinedTxFields);
data = this.buildExecutionData(commonExecutionData.creatorDefinedTxFields);
}

function getTx() external view returns (bytes memory transaction) {
Expand All @@ -125,4 +139,4 @@ contract AdvancedOrder is AbstractOrder, IExecution {

transaction = _unsignedTx;
}
}
}
15 changes: 9 additions & 6 deletions solidity/orders/src/BasicOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ error InvalidThresholdPrice();
event Executed();

contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {
Types.OrderData public orderData;
Types.BasicOrderData public orderData;
Types.CommonExecutionData public commonExecutionData;

ISlinky private immutable SLINKY_PRECOMPILE;
Registry private immutable REGISTRY;
Expand All @@ -30,12 +31,13 @@ contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {

// solhint-disable-next-line
constructor(
Types.OrderData memory _orderData,
Types.BasicOrderData memory _orderData,
Types.CommonExecutionData memory _executionData,
CommonTypes.Coin[] memory maxKeychainFees,
address scheduler,
address registry
)
AbstractOrder(_orderData.signRequestData, _orderData.creatorDefinedTxFields, scheduler, registry)
AbstractOrder(_executionData.signRequestData, _executionData.creatorDefinedTxFields, scheduler, registry)
{
if (_orderData.thresholdPrice == 0) {
revert InvalidThresholdPrice();
Expand All @@ -51,6 +53,7 @@ contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {
}

orderData = _orderData;
commonExecutionData = _executionData;
_scheduler = scheduler;
_callers.push(Caller.Scheduler);
}
Expand Down Expand Up @@ -93,14 +96,14 @@ contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {

bytes[] memory emptyAccessList = new bytes[](0);
(bytes memory unsignedTx, bytes32 txHash) = this.encodeUnsignedEIP1559(
nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, orderData.creatorDefinedTxFields
nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, commonExecutionData.creatorDefinedTxFields
);

_unsignedTx = unsignedTx;

bytes memory signRequestInput = abi.encodePacked(txHash);

_executed = this.createSignRequest(orderData.signRequestData, signRequestInput, _coins);
_executed = this.createSignRequest(commonExecutionData.signRequestData, signRequestInput, _coins);

if (_executed) {
emit Executed();
Expand All @@ -122,7 +125,7 @@ contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {
}

function executionData() external view returns (ExecutionData memory data) {
data = this.buildExecutionData(orderData.creatorDefinedTxFields);
data = this.buildExecutionData(commonExecutionData.creatorDefinedTxFields);
}

function getTx() external view returns (bytes memory transaction) {
Expand Down
73 changes: 61 additions & 12 deletions solidity/orders/src/OrderFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Types } from "./Types.sol";
import { Types as CommonTypes } from "precompile-common/Types.sol";
import { BasicOrder } from "./BasicOrder.sol";
import { AdvancedOrder } from "./AdvancedOrder.sol";
import { Registry } from "./Registry.sol";
import { Create3 } from "@0xsequence/create3/contracts/Create3.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
Expand Down Expand Up @@ -75,7 +76,8 @@ contract OrderFactory is Ownable, ReentrancyGuard {
* @return order The address of the newly created order
*/
function createOrder(
Types.OrderData calldata _orderData,
bytes calldata _orderData,
Types.CommonExecutionData calldata _executionData,
CommonTypes.Coin[] calldata maxKeychainFees,
OrderType orderType,
bytes32 salt
Expand All @@ -98,9 +100,11 @@ contract OrderFactory is Ownable, ReentrancyGuard {
emit SaltUsed(guardedSalt, origin);

if (orderType == OrderType.Basic) {
return _createBasicOrder(guardedSalt, _orderData, maxKeychainFees, scheduler);
Types.BasicOrderData memory basicOrderData = abi.decode(_orderData, (Types.BasicOrderData));
return _createBasicOrder(guardedSalt, basicOrderData, _executionData, maxKeychainFees, scheduler);
} else if (orderType == OrderType.Advanced) {
return _createAdvancedOrder(guardedSalt, _orderData, maxKeychainFees);
Types.AdvancedOrderData memory advancedOrderData = abi.decode(_orderData, (Types.AdvancedOrderData));
return _createAdvancedOrder(guardedSalt, advancedOrderData, _executionData, maxKeychainFees, scheduler);
} else {
revert UnsupportedOrder();
}
Expand All @@ -123,20 +127,22 @@ contract OrderFactory is Ownable, ReentrancyGuard {
* @notice Internal function to create a BasicOrder using CREATE3
* @param salt The unique salt provided by the frontend
* @param _orderData The data required to create the order
* @param _executionData The data required for order execution
* @param maxKeychainFees The maximum fees allowed
* @param _scheduler The scheduler address
* @return The address of the newly created BasicOrder
*/
function _createBasicOrder(
bytes32 salt,
Types.OrderData calldata _orderData,
Types.BasicOrderData memory _orderData,
Types.CommonExecutionData calldata _executionData,
CommonTypes.Coin[] calldata maxKeychainFees,
address _scheduler
)
internal
returns (address)
{
bytes memory bytecode = getBasicOrderBytecode(_orderData, maxKeychainFees, _scheduler);
bytes memory bytecode = getBasicOrderBytecode(_orderData, _executionData, maxKeychainFees, _scheduler);

address orderAddress = Create3.create3(salt, bytecode);

Expand All @@ -155,26 +161,68 @@ contract OrderFactory is Ownable, ReentrancyGuard {
}

function _createAdvancedOrder(
bytes32,
Types.OrderData calldata,
CommonTypes.Coin[] calldata
bytes32 salt,
Types.AdvancedOrderData memory _orderData,
Types.CommonExecutionData calldata _executionData,
CommonTypes.Coin[] calldata maxKeychainFees,
address _scheduler
)
internal
pure
returns (address)
{
revert Unimplemented();
bytes memory bytecode = getAdvancedOrderBytecode(_orderData, _executionData, maxKeychainFees, _scheduler);

address orderAddress = Create3.create3(salt, bytecode);

address expectedAddress = Create3.addressOf(salt);
if (orderAddress == address(0) || orderAddress != expectedAddress) {
revert OrderDeploymentFailed(salt);
}

orders[orderAddress] = msg.sender;

REGISTRY.register(orderAddress);

emit OrderCreated(msg.sender, OrderType.Advanced, orderAddress);

return orderAddress;
}

/**
* @notice Prepares the creation bytecode for BasicOrder
* @param _orderData The data required to create the order
* @param _executionData The data required for order execution
* @param maxKeychainFees The maximum fees allowed
* @param _scheduler The scheduler address
* @return The bytecode for deploying BasicOrder
*/
function getBasicOrderBytecode(
Types.OrderData calldata _orderData,
Types.BasicOrderData memory _orderData,
Types.CommonExecutionData calldata _executionData,
CommonTypes.Coin[] calldata maxKeychainFees,
address _scheduler
)
internal
view
returns (bytes memory)
{
return abi.encodePacked(
type(BasicOrder).creationCode,
abi.encode(_orderData, _executionData, maxKeychainFees, _scheduler, address(REGISTRY))
);
}

/**
* @notice Prepares the creation bytecode for AdvancedOrder
* @param _orderData The data required to create the order
* @param _executionData The data required for order execution
* @param maxKeychainFees The maximum fees allowed
* @param _scheduler The scheduler address
* @return The bytecode for deploying AdvancedOrder
*/
function getAdvancedOrderBytecode(
Types.AdvancedOrderData memory _orderData,
Types.CommonExecutionData calldata _executionData,
CommonTypes.Coin[] calldata maxKeychainFees,
address _scheduler
)
Expand All @@ -183,7 +231,8 @@ contract OrderFactory is Ownable, ReentrancyGuard {
returns (bytes memory)
{
return abi.encodePacked(
type(BasicOrder).creationCode, abi.encode(_orderData, maxKeychainFees, _scheduler, address(REGISTRY))
type(AdvancedOrder).creationCode,
abi.encode(_orderData, _executionData, maxKeychainFees, _scheduler, address(REGISTRY))
);
}
}
15 changes: 13 additions & 2 deletions solidity/orders/src/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,22 @@ library Types {
GTE
}

// Data for execution
struct OrderData {
// Data for basic order creation
struct BasicOrderData {
uint256 thresholdPrice;
PriceCondition priceCondition;
PricePair pricePair;
}

// Data for advanced order creation
struct AdvancedOrderData {
uint64 futureId;
PriceCondition priceCondition;
PricePair pricePair;
}

// Data for execution
struct CommonExecutionData {
CreatorDefinedTxFields creatorDefinedTxFields;
SignRequestData signRequestData;
}
Expand Down
Loading

0 comments on commit d334e4c

Please sign in to comment.