Skip to content

Commit

Permalink
πŸ‘·πŸ»β€β™‚οΈ Move interfaces into src/
Browse files Browse the repository at this point in the history
  • Loading branch information
JaredBorders committed Sep 25, 2023
1 parent 792c865 commit 961f15c
Show file tree
Hide file tree
Showing 3 changed files with 869 additions and 3 deletions.
5 changes: 2 additions & 3 deletions src/SMv2SessionValidationModule.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.18;

import {IAccount} from "lib/smart-margin/src/interfaces/IAccount.sol";
import {IAccount} from "src/kwenta/smv2/IAccount.sol";
import {
ISessionValidationModule,
UserOperation
Expand All @@ -14,7 +14,6 @@ import {ECDSA} from "src/openzeppelin/ECDSA.sol";
* @author Fil Makarov - <[email protected]>
* @author JaredBorders ([email protected])
*/

contract SMv2SessionValidationModule is ISessionValidationModule {
error InvalidSelector(bytes4 selector);
error InvalidSMv2ExecuteSelector(bytes4 selector);
Expand Down
308 changes: 308 additions & 0 deletions src/kwenta/smv2/IAccount.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.18;

/// @title Kwenta Smart Margin Account v2.1.0 Implementation Interface
/// @author JaredBorders ([email protected]), JChiaramonte7 ([email protected])
interface IAccount {
/*///////////////////////////////////////////////////////////////
Types
///////////////////////////////////////////////////////////////*/

/// @notice Command Flags used to decode commands to execute
/// @dev under the hood ACCOUNT_MODIFY_MARGIN = 0, ACCOUNT_WITHDRAW_ETH = 1
enum Command {
ACCOUNT_MODIFY_MARGIN, // 0
ACCOUNT_WITHDRAW_ETH,
PERPS_V2_MODIFY_MARGIN,
PERPS_V2_WITHDRAW_ALL_MARGIN,
PERPS_V2_SUBMIT_ATOMIC_ORDER,
PERPS_V2_SUBMIT_DELAYED_ORDER, // 5
PERPS_V2_SUBMIT_OFFCHAIN_DELAYED_ORDER,
PERPS_V2_CLOSE_POSITION,
PERPS_V2_SUBMIT_CLOSE_DELAYED_ORDER,
PERPS_V2_SUBMIT_CLOSE_OFFCHAIN_DELAYED_ORDER,
PERPS_V2_CANCEL_DELAYED_ORDER, // 10
PERPS_V2_CANCEL_OFFCHAIN_DELAYED_ORDER,
GELATO_PLACE_CONDITIONAL_ORDER,
GELATO_CANCEL_CONDITIONAL_ORDER,
UNISWAP_V3_SWAP,
PERMIT2_PERMIT // 15
}

/// @notice denotes conditional order types for code clarity
/// @dev under the hood LIMIT = 0, STOP = 1
enum ConditionalOrderTypes {
LIMIT,
STOP
}

/// @notice denotes conditional order cancelled reasons for code clarity
/// @dev under the hood CONDITIONAL_ORDER_CANCELLED_BY_USER = 0, CONDITIONAL_ORDER_CANCELLED_NOT_REDUCE_ONLY = 1
enum ConditionalOrderCancelledReason {
CONDITIONAL_ORDER_CANCELLED_BY_USER,
CONDITIONAL_ORDER_CANCELLED_NOT_REDUCE_ONLY
}

/// @notice denotes what oracle is used for price when executing conditional orders
/// @dev under the hood PYTH = 0, CHAINLINK = 1
enum PriceOracleUsed {
PYTH,
CHAINLINK
}

/// @param factory: address of the Smart Margin Account Factory
/// @param events: address of the contract used by all accounts for emitting events
/// @param marginAsset: address of the Synthetix ProxyERC20sUSD contract used as the margin asset
/// @param perpsV2ExchangeRate: address of the Synthetix PerpsV2ExchangeRate
/// @param futuresMarketManager: address of the Synthetix FuturesMarketManager
/// @param systemStatus: address of the Synthetix SystemStatus
/// @param gelato: address of Gelato
/// @param ops: address of Ops
/// @param settings: address of contract used to store global settings
/// @param universalRouter: address of Uniswap's Universal Router
/// @param permit2: address of Uniswap's Permit2
struct AccountConstructorParams {
address factory;
address events;
address marginAsset;
address perpsV2ExchangeRate;
address futuresMarketManager;
address systemStatus;
address gelato;
address ops;
address settings;
address universalRouter;
address permit2;
}

/// marketKey: Synthetix PerpsV2 Market id/key
/// marginDelta: amount of margin to deposit or withdraw; positive indicates deposit, negative withdraw
/// sizeDelta: denoted in market currency (i.e. ETH, BTC, etc), size of Synthetix PerpsV2 position
/// targetPrice: limit or stop price target needing to be met to submit Synthetix PerpsV2 order
/// gelatoTaskId: unqiue taskId from gelato necessary for cancelling conditional orders
/// conditionalOrderType: conditional order type to determine conditional order fill logic
/// desiredFillPrice: desired price to fill Synthetix PerpsV2 order at execution time
/// reduceOnly: if true, only allows position's absolute size to decrease
struct ConditionalOrder {
bytes32 marketKey;
int256 marginDelta;
int256 sizeDelta;
uint256 targetPrice;
bytes32 gelatoTaskId;
ConditionalOrderTypes conditionalOrderType;
uint256 desiredFillPrice;
bool reduceOnly;
}
/// @dev see example below elucidating targtPrice vs desiredFillPrice:
/// 1. targetPrice met (ex: targetPrice = X)
/// 2. account submits delayed order to Synthetix PerpsV2 with desiredFillPrice = Y
/// 3. keeper executes Synthetix PerpsV2 order after delay period
/// 4. if current market price defined by Synthetix PerpsV2
/// after delay period satisfies desiredFillPrice order is filled

/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/

/// @notice thrown when commands length does not equal inputs length
error LengthMismatch();

/// @notice thrown when Command given is not valid
error InvalidCommandType(uint256 commandType);

/// @notice thrown when conditional order type given is not valid due to zero sizeDelta
error ZeroSizeDelta();

/// @notice exceeds useable margin
/// @param available: amount of useable margin asset
/// @param required: amount of margin asset required
error InsufficientFreeMargin(uint256 available, uint256 required);

/// @notice call to transfer ETH on withdrawal fails
error EthWithdrawalFailed();

/// @notice base price from the oracle was invalid
/// @dev Rate can be invalid either due to:
/// 1. Returned as invalid from ExchangeRates - due to being stale or flagged by oracle
/// 2. Out of deviation bounds w.r.t. to previously stored rate
/// 3. if there is no valid stored rate, w.r.t. to previous 3 oracle rates
/// 4. Price is zero
error InvalidPrice();

/// @notice thrown when account execution has been disabled in the settings contract
error AccountExecutionDisabled();

/// @notice thrown when a call attempts to reenter the protected function
error Reentrancy();

/// @notice thrown when token swap attempted with invalid token (i.e. token that is not whitelisted)
/// @param tokenIn: token attempting to swap from
/// @param tokenOut: token attempting to swap to
error TokenSwapNotAllowed(address tokenIn, address tokenOut);

/// @notice thrown when a conditional order is attempted to be executed during invalid market conditions
/// @param conditionalOrderId: conditional order id
/// @param executor: address of executor
error CannotExecuteConditionalOrder(
uint256 conditionalOrderId, address executor
);

/// @notice thrown when a conditional order is attempted to be executed but SM account cannot pay fee
/// @param executorFee: fee required to execute conditional order
error CannotPayExecutorFee(uint256 executorFee, address executor);

/*//////////////////////////////////////////////////////////////
VIEWS
//////////////////////////////////////////////////////////////*/

/// @notice returns the version of the Account
function VERSION() external view returns (bytes32);

/// @return returns the amount of margin locked for future events (i.e. conditional orders)
function committedMargin() external view returns (uint256);

/// @return returns current conditional order id
function conditionalOrderId() external view returns (uint256);

/// @notice get delayed order data from Synthetix PerpsV2
/// @dev call reverts if _marketKey is invalid
/// @param _marketKey: key for Synthetix PerpsV2 Market
/// @return delayed order struct defining delayed order (will return empty struct if no delayed order exists)
function getDelayedOrder(bytes32 _marketKey)
external
returns (IPerpsV2MarketConsolidated.DelayedOrder memory);

/// @notice checker() is the Resolver for Gelato
/// (see https://docs.gelato.network/developer-services/automate/guides/custom-logic-triggers/smart-contract-resolvers)
/// @notice signal to a keeper that a conditional order is valid/invalid for execution
/// @dev call reverts if conditional order Id does not map to a valid conditional order;
/// ConditionalOrder.marketKey would be invalid
/// @param _conditionalOrderId: key for an active conditional order
/// @return canExec boolean that signals to keeper a conditional order can be executed by Gelato
/// @return execPayload calldata for executing a conditional order
function checker(uint256 _conditionalOrderId)
external
view
returns (bool canExec, bytes memory execPayload);

/// @notice the current withdrawable or usable balance
/// @return free margin amount
function freeMargin() external view returns (uint256);

/// @notice get up-to-date position data from Synthetix PerpsV2
/// @param _marketKey: key for Synthetix PerpsV2 Market
/// @return position struct defining current position
function getPosition(bytes32 _marketKey)
external
returns (IPerpsV2MarketConsolidated.Position memory);

/// @notice conditional order id mapped to conditional order
/// @param _conditionalOrderId: id of conditional order
/// @return conditional order
function getConditionalOrder(uint256 _conditionalOrderId)
external
view
returns (ConditionalOrder memory);

/*//////////////////////////////////////////////////////////////
MUTATIVE
//////////////////////////////////////////////////////////////*/

/// @notice sets the initial owner of the account
/// @dev only called once by the factory on account creation
/// @param _owner: address of the owner
function setInitialOwnership(address _owner) external;

/// @notice executes commands along with provided inputs
/// @param _commands: array of commands, each represented as an enum
/// @param _inputs: array of byte strings containing abi encoded inputs for each command
function execute(Command[] calldata _commands, bytes[] calldata _inputs)
external
payable;

/// @notice execute queued conditional order
/// @dev currently only supports conditional order submission via PERPS_V2_SUBMIT_OFFCHAIN_DELAYED_ORDER COMMAND
/// @param _conditionalOrderId: key for an active conditional order
function executeConditionalOrder(uint256 _conditionalOrderId) external;
}

interface IPerpsV2MarketConsolidated {
struct Position {
uint64 id;
uint64 lastFundingIndex;
uint128 margin;
uint128 lastPrice;
int128 size;
}

struct DelayedOrder {
bool isOffchain;
int128 sizeDelta;
uint128 desiredFillPrice;
uint128 targetRoundId;
uint128 commitDeposit;
uint128 keeperDeposit;
uint256 executableAtTime;
uint256 intentionTime;
bytes32 trackingCode;
}

function marketKey() external view returns (bytes32 key);

function positions(address account)
external
view
returns (Position memory);

function delayedOrders(address account)
external
view
returns (DelayedOrder memory);

function baseAsset() external view returns (bytes32 key);

function assetPrice() external view returns (uint256 price, bool invalid);

function transferMargin(int256 marginDelta) external;

function withdrawAllMargin() external;

function modifyPositionWithTracking(
int256 sizeDelta,
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function closePositionWithTracking(
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function submitCloseOffchainDelayedOrderWithTracking(
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function submitCloseDelayedOrderWithTracking(
uint256 desiredTimeDelta,
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function submitDelayedOrderWithTracking(
int256 sizeDelta,
uint256 desiredTimeDelta,
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function submitOffchainDelayedOrderWithTracking(
int256 sizeDelta,
uint256 desiredFillPrice,
bytes32 trackingCode
) external;

function cancelDelayedOrder(address account) external;

function cancelOffchainDelayedOrder(address account) external;
}
Loading

0 comments on commit 961f15c

Please sign in to comment.