Skip to content

Commit

Permalink
Prepare to advanced orders (#1161)
Browse files Browse the repository at this point in the history
* introduce AbstractOrder

* rm setByAIService as it's will be not used

* forge fmt

* move common parts into AbstractOrder

* new devnet deployment
  • Loading branch information
mn13 authored Dec 27, 2024
1 parent 99c2808 commit e0785e4
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 148 deletions.
4 changes: 2 additions & 2 deletions solidity/orders/broadcast/Deploy.s.sol/12345/latest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"orderFactory": "0x1E1FBD4495Ce5a05BcF9857663a6f2992dF47E04",
"registry": "0x8Fe9EADB851f4122273F34d09A8CA8D1B628E4bF"
"orderFactory": "0xA55973fB4cA5EbBb7e9879C73B2d27D5fe5d6E8a",
"registry": "0xa7f5a0571fd94dC8E48960a9819Bda8C7Ed0e433"
}
100 changes: 50 additions & 50 deletions solidity/orders/broadcast/Deploy.s.sol/12345/run-latest.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions solidity/orders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
},
"scripts": {
"clean": "rm -rf cache out",
"build": "forge build src",
"build": "forge build src --via-ir",
"lint": "yarn run lint:sol && yarn run prettier:check",
"lint:sol": "forge fmt --check && yarn solhint \"{script,src,test}/**/*.sol\"",
"prettier:check": "prettier --check \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"",
"prettier:write": "prettier --write \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"",
"test": "forge test --via-ir",
"test:coverage": "forge coverage",
"test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage",
"deploy": "forge script script/Deploy.s.sol:Deploy --chain $CHAIN_ID --rpc-url $RPC_URL --broadcast -vvvv"
"deploy": "forge script script/Deploy.s.sol:Deploy --chain $CHAIN_ID --rpc-url $RPC_URL --broadcast -vvvv --via-ir"
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
120 changes: 120 additions & 0 deletions solidity/orders/src/AbstractOrder.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.25 <0.9.0;

import { BroadcastType, IWarden, IWARDEN_PRECOMPILE_ADDRESS, KeyResponse } from "precompile-warden/IWarden.sol";
import { Types as CommonTypes } from "precompile-common/Types.sol";
import { RLPEncode } from "./RLPEncode.sol";
import { Types } from "./Types.sol";
import { ExecutionData } from "./IExecution.sol";
import { Strings } from "./Strings.sol";

error InvalidScheduler();
error InvalidRegistry();
error InvalidExpectedApproveExpression();
error InvalidExpectedRejectExpression();
error InvalidTxTo();

abstract contract AbstractOrder {
using Strings for *;

IWarden private immutable WARDEN_PRECOMPILE;
address private _keyAddress;
int32 private constant ETHEREUM_ADDRESS_TYPE = 1;

constructor(
Types.SignRequestData memory signRequestData,
Types.CreatorDefinedTxFields memory creatorDefinedTxFields,
address scheduler,
address registry
) {
if (scheduler == address(0)) {
revert InvalidScheduler();
}

if (registry == address(0)) {
revert InvalidRegistry();
}

if (bytes(signRequestData.expectedApproveExpression).length == 0) {
revert InvalidExpectedApproveExpression();
}

if (bytes(signRequestData.expectedRejectExpression).length == 0) {
revert InvalidExpectedRejectExpression();
}

if (creatorDefinedTxFields.to == address(0)) {
revert InvalidTxTo();
}

WARDEN_PRECOMPILE = IWarden(IWARDEN_PRECOMPILE_ADDRESS);
int32[] memory addressTypes = new int32[](1);
addressTypes[0] = ETHEREUM_ADDRESS_TYPE;
KeyResponse memory keyResponse = WARDEN_PRECOMPILE.keyById(signRequestData.keyId, addressTypes);
_keyAddress = keyResponse.addresses[0].addressValue.parseAddress();
}

function encodeUnsignedEIP1559(
uint256 nonce,
uint256 gas,
uint256 maxPriorityFeePerGas,
uint256 maxFeePerGas,
bytes[] calldata accessList,
Types.CreatorDefinedTxFields calldata creatorDefinedTxFields
)
public
pure
returns (bytes memory unsignedTx, bytes32 txHash)
{
uint256 txType = 2; // eip1559 tx type
bytes[] memory txArray = new bytes[](9);
txArray[0] = RLPEncode.encodeUint(creatorDefinedTxFields.chainId);
txArray[1] = RLPEncode.encodeUint(nonce);
txArray[2] = RLPEncode.encodeUint(maxPriorityFeePerGas);
txArray[3] = RLPEncode.encodeUint(maxFeePerGas);
txArray[4] = RLPEncode.encodeUint(gas);
txArray[5] = RLPEncode.encodeAddress(creatorDefinedTxFields.to);
txArray[6] = RLPEncode.encodeUint(creatorDefinedTxFields.value);
txArray[7] = RLPEncode.encodeBytes(creatorDefinedTxFields.data);
txArray[8] = RLPEncode.encodeList(accessList);
bytes memory unsignedTxEncoded = RLPEncode.encodeList(txArray);
unsignedTx = RLPEncode.concat(RLPEncode.encodeUint(txType), unsignedTxEncoded);
txHash = keccak256(unsignedTx);
}

function buildExecutionData(Types.CreatorDefinedTxFields calldata creatorDefinedTxFields)
public
view
returns (ExecutionData memory data)
{
data = ExecutionData({
caller: _keyAddress,
to: creatorDefinedTxFields.to,
chainId: creatorDefinedTxFields.chainId,
value: creatorDefinedTxFields.value,
data: creatorDefinedTxFields.data
});
}

function createSignRequest(
Types.SignRequestData calldata signRequestData,
bytes calldata signRequestInput,
CommonTypes.Coin[] calldata maxKeychainFees
)
public
returns (bool)
{
return WARDEN_PRECOMPILE.newSignRequest(
signRequestData.keyId,
signRequestInput,
signRequestData.analyzers,
signRequestData.encryptionKey,
maxKeychainFees,
signRequestData.spaceNonce,
signRequestData.actionTimeoutHeight,
signRequestData.expectedApproveExpression,
signRequestData.expectedRejectExpression,
BroadcastType.Automatic
);
}
}
96 changes: 14 additions & 82 deletions solidity/orders/src/BasicOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,54 @@ pragma solidity >=0.8.25 <0.9.0;

import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { Types as CommonTypes } from "precompile-common/Types.sol";
import { BroadcastType, IWarden, IWARDEN_PRECOMPILE_ADDRESS, KeyResponse } from "precompile-warden/IWarden.sol";
import { GetPriceResponse, ISlinky, ISLINKY_PRECOMPILE_ADDRESS } from "precompile-slinky/ISlinky.sol";
import { Caller, ExecutionData, IExecution } from "./IExecution.sol";
import { AbstractOrder } from "./AbstractOrder.sol";
import { Types } from "./Types.sol";
import { Registry } from "./Registry.sol";
import { RLPEncode } from "./RLPEncode.sol";
import { Strings } from "./Strings.sol";

error ConditionNotMet();
error ExecutedError();
error Unauthorized();
error InvalidPriceCondition();
error InvalidScheduler();
error InvalidRegistry();
error InvalidExpectedApproveExpression();
error InvalidExpectedRejectExpression();
error InvalidThresholdPrice();
error InvalidTxTo();

event Executed();

contract BasicOrder is IExecution, ReentrancyGuard {
using Strings for *;

contract BasicOrder is AbstractOrder, IExecution, ReentrancyGuard {
Types.OrderData public orderData;
string public constant SWAP_EXACT_ETH_FOR_TOKENS = "swapExactETHForTokens(uint256,address[],address,uint256)";

IWarden private immutable WARDEN_PRECOMPILE;
ISlinky private immutable SLINKY_PRECOMPILE;
Registry private immutable REGISTRY;
Caller[] private _callers;
CommonTypes.Coin[] private _coins;
bool private _executed;
address private _scheduler;
address private _keyAddress;
bytes private _unsignedTx;
int32 private constant ETHEREUM_ADDRESS_TYPE = 1;

// solhint-disable-next-line
constructor(
Types.OrderData memory _orderData,
CommonTypes.Coin[] memory maxKeychainFees,
address scheduler,
address registry
) {
for (uint256 i = 0; i < maxKeychainFees.length; i++) {
_coins.push(maxKeychainFees[i]);
}

if (scheduler == address(0)) {
revert InvalidScheduler();
}

if (registry == address(0)) {
revert InvalidRegistry();
}

if (bytes(_orderData.signRequestData.expectedApproveExpression).length == 0) {
revert InvalidExpectedApproveExpression();
}

if (bytes(_orderData.signRequestData.expectedRejectExpression).length == 0) {
revert InvalidExpectedRejectExpression();
}

)
AbstractOrder(_orderData.signRequestData, _orderData.creatorDefinedTxFields, scheduler, registry)
{
if (_orderData.thresholdPrice == 0) {
revert InvalidThresholdPrice();
}

if (_orderData.creatorDefinedTxFields.to == address(0)) {
revert InvalidTxTo();
}

WARDEN_PRECOMPILE = IWarden(IWARDEN_PRECOMPILE_ADDRESS);
int32[] memory addressTypes = new int32[](1);
addressTypes[0] = ETHEREUM_ADDRESS_TYPE;
KeyResponse memory keyResponse = WARDEN_PRECOMPILE.keyById(_orderData.signRequestData.keyId, addressTypes);
_keyAddress = keyResponse.addresses[0].addressValue.parseAddress();

SLINKY_PRECOMPILE = ISlinky(ISLINKY_PRECOMPILE_ADDRESS);
SLINKY_PRECOMPILE.getPrice(_orderData.pricePair.base, _orderData.pricePair.quote);

REGISTRY = Registry(registry);

for (uint256 i = 0; i < maxKeychainFees.length; i++) {
_coins.push(maxKeychainFees[i]);
}

orderData = _orderData;
_scheduler = scheduler;
_callers.push(Caller.Scheduler);
Expand Down Expand Up @@ -129,37 +93,15 @@ contract BasicOrder is IExecution, ReentrancyGuard {
}

bytes[] memory emptyAccessList = new bytes[](0);
uint256 txType = 2; // eip1559 tx type
bytes[] memory txArray = new bytes[](9);
txArray[0] = RLPEncode.encodeUint(orderData.creatorDefinedTxFields.chainId);
txArray[1] = RLPEncode.encodeUint(nonce);
txArray[2] = RLPEncode.encodeUint(maxPriorityFeePerGas);
txArray[3] = RLPEncode.encodeUint(maxFeePerGas);
txArray[4] = RLPEncode.encodeUint(gas);
txArray[5] = RLPEncode.encodeAddress(orderData.creatorDefinedTxFields.to);
txArray[6] = RLPEncode.encodeUint(orderData.creatorDefinedTxFields.value);
txArray[7] = RLPEncode.encodeBytes(orderData.creatorDefinedTxFields.data);
txArray[8] = RLPEncode.encodeList(emptyAccessList);
bytes memory unsignedTxEncoded = RLPEncode.encodeList(txArray);
bytes memory unsignedTx = RLPEncode.concat(RLPEncode.encodeUint(txType), unsignedTxEncoded);
(bytes memory unsignedTx, bytes32 txHash) = this.encodeUnsignedEIP1559(
nonce, gas, maxPriorityFeePerGas, maxFeePerGas, emptyAccessList, orderData.creatorDefinedTxFields
);

_unsignedTx = unsignedTx;

bytes32 txHash = keccak256(unsignedTx);
bytes memory signRequestInput = abi.encodePacked(txHash);

_executed = WARDEN_PRECOMPILE.newSignRequest(
orderData.signRequestData.keyId,
signRequestInput,
orderData.signRequestData.analyzers,
orderData.signRequestData.encryptionKey,
_coins,
orderData.signRequestData.spaceNonce,
orderData.signRequestData.actionTimeoutHeight,
orderData.signRequestData.expectedApproveExpression,
orderData.signRequestData.expectedRejectExpression,
BroadcastType.Automatic
);
_executed = this.createSignRequest(orderData.signRequestData, signRequestInput, _coins);

if (_executed) {
emit Executed();
Expand All @@ -181,17 +123,7 @@ contract BasicOrder is IExecution, ReentrancyGuard {
}

function executionData() external view returns (ExecutionData memory data) {
data = ExecutionData({
caller: _keyAddress,
to: orderData.creatorDefinedTxFields.to,
chainId: orderData.creatorDefinedTxFields.chainId,
value: orderData.creatorDefinedTxFields.value,
data: orderData.creatorDefinedTxFields.data
});
}

function setByAIService(bytes calldata) external pure returns (bool success) {
success = false;
data = this.buildExecutionData(orderData.creatorDefinedTxFields);
}

function getTx() external view returns (bytes memory transaction) {
Expand Down
10 changes: 1 addition & 9 deletions solidity/orders/src/IExecution.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ struct ExecutionData {
}

enum Caller {
Scheduler,
AI
Scheduler
}

interface IExecution {
Expand Down Expand Up @@ -46,13 +45,6 @@ interface IExecution {
*/
function callers() external returns (Caller[] memory callersList);

/**
* @dev Receives data by AI service.
* @param data Data from AI service.
* @return success A boolean value indicating whenever data was processed correctly.
*/
function setByAIService(bytes calldata data) external returns (bool success);

/**
* @dev Indicates if execution was executed already.
*/
Expand Down
5 changes: 2 additions & 3 deletions solidity/orders/test/BasicOrder.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ import { Caller, IExecution } from "../src/IExecution.sol";
import { MockWardenPrecompile } from "../mocks/MockWardenPrecompile.sol";
import { MockSlinkyPrecompile } from "../mocks/MockSlinkyPrecompile.sol";
import { Types as CommonTypes } from "precompile-common/Types.sol";
import {
BasicOrder, Executed, ConditionNotMet, ExecutedError, InvalidScheduler, Unauthorized
} from "../src/BasicOrder.sol";
import { InvalidScheduler } from "../src/AbstractOrder.sol";
import { BasicOrder, Executed, ConditionNotMet, ExecutedError, Unauthorized } from "../src/BasicOrder.sol";
import {
BadCreatorAddress,
ExecutionAlreadyRegistered,
Expand Down

0 comments on commit e0785e4

Please sign in to comment.