tempo_contracts/precompiles/
stablecoin_exchange.rs

1pub use IStablecoinExchange::{
2    IStablecoinExchangeErrors as StablecoinExchangeError,
3    IStablecoinExchangeEvents as StablecoinExchangeEvents,
4};
5
6use alloy::sol;
7
8sol! {
9    /// StablecoinExchange interface for managing orderbook based trading of stablecoins.
10    ///
11    /// The StablecoinExchange provides a limit orderbook system where users can:
12    /// - Place limit orders (buy/sell) with specific price ticks
13    /// - Place flip orders that automatically create opposite-side orders when filled
14    /// - Execute swaps against existing liquidity
15    /// - Manage internal balances for trading
16    ///
17    /// The exchange operates on pairs between base tokens and their designated quote tokens,
18    /// using a tick-based pricing system for precise order matching.
19    #[derive(Debug, PartialEq, Eq)]
20    #[sol(rpc, abi)]
21    interface IStablecoinExchange {
22        // Structs
23        struct Order {
24            uint128 orderId;
25            address maker;
26            bytes32 bookKey;
27            bool isBid;
28            int16 tick;
29            uint128 amount;
30            uint128 remaining;
31            uint128 prev;
32            uint128 next;
33            bool isFlip;
34            int16 flipTick;
35        }
36
37        struct PriceLevel {
38            uint128 head;
39            uint128 tail;
40            uint128 totalLiquidity;
41        }
42
43        struct Orderbook {
44            address base;
45            address quote;
46            int16 bestBidTick;
47            int16 bestAskTick;
48        }
49
50        // Core Trading Functions
51        function createPair(address base) external returns (bytes32 key);
52        function place(address token, uint128 amount, bool isBid, int16 tick) external returns (uint128 orderId);
53        function placeFlip(address token, uint128 amount, bool isBid, int16 tick, int16 flipTick) external returns (uint128 orderId);
54        function cancel(uint128 orderId) external;
55        function executeBlock() external;
56
57        // Swap Functions
58        function swapExactAmountIn(address tokenIn, address tokenOut, uint128 amountIn, uint128 minAmountOut) external returns (uint128 amountOut);
59        function swapExactAmountOut(address tokenIn, address tokenOut, uint128 amountOut, uint128 maxAmountIn) external returns (uint128 amountIn);
60        function quoteSwapExactAmountIn(address tokenIn, address tokenOut, uint128 amountIn) external view returns (uint128 amountOut);
61        function quoteSwapExactAmountOut(address tokenIn, address tokenOut, uint128 amountOut) external view returns (uint128 amountIn);
62
63        // Balance Management
64        function balanceOf(address user, address token) external view returns (uint128);
65        function withdraw(address token, uint128 amount) external;
66
67        // View Functions
68        function getOrder(uint128 orderId) external view returns (Order memory);
69
70        function getTickLevel(address base, int16 tick, bool isBid) external view returns (uint128 head, uint128 tail, uint128 totalLiquidity);
71        function pairKey(address tokenA, address tokenB) external pure returns (bytes32);
72        function activeOrderId() external view returns (uint128);
73        function pendingOrderId() external view returns (uint128);
74        function books(bytes32 pairKey) external view returns (Orderbook memory);
75
76        // Constants (exposed as view functions)
77        function MIN_TICK() external pure returns (int16);
78        function MAX_TICK() external pure returns (int16);
79        function TICK_SPACING() external pure returns (int16);
80        function PRICE_SCALE() external pure returns (uint32);
81        function MIN_PRICE() external pure returns (uint32);
82        function MAX_PRICE() external pure returns (uint32);
83
84        // Price conversion functions
85        function tickToPrice(int16 tick) external pure returns (uint32 price);
86        function priceToTick(uint32 price) external pure returns (int16 tick);
87
88        // Events
89        event PairCreated(bytes32 indexed key, address indexed base, address indexed quote);
90        event OrderPlaced(uint128 indexed orderId, address indexed maker, address indexed token, uint128 amount, bool isBid, int16 tick);
91        event FlipOrderPlaced(uint128 indexed orderId, address indexed maker, address indexed token, uint128 amount, bool isBid, int16 tick, int16 flipTick);
92        /// Pre-Allegretto: OrderFilled event without taker parameter
93        event OrderFilled(uint128 indexed orderId, address indexed maker, uint128 amountFilled, bool partialFill);
94        /// Post-Allegretto: OrderFilled event with taker parameter
95        event OrderFilled(uint128 indexed orderId, address indexed maker, address indexed taker, uint128 amountFilled, bool partialFill);
96        event OrderCancelled(uint128 indexed orderId);
97
98        // Errors
99        error Unauthorized();
100        error PairDoesNotExist();
101        error PairAlreadyExists();
102        error OrderDoesNotExist();
103        error IdenticalTokens();
104        error InvalidToken();
105        error TickOutOfBounds(int16 tick);
106        error InvalidTick();
107        error InvalidFlipTick();
108        error InsufficientBalance();
109        error InsufficientLiquidity();
110        error InsufficientOutput();
111        error MaxInputExceeded();
112        error BelowMinimumOrderSize(uint128 amount);
113        error InvalidBaseToken();
114    }
115}
116
117impl StablecoinExchangeError {
118    /// Creates an unauthorized access error.
119    pub const fn unauthorized() -> Self {
120        Self::Unauthorized(IStablecoinExchange::Unauthorized {})
121    }
122
123    /// Creates an error when pair does not exist.
124    pub const fn pair_does_not_exist() -> Self {
125        Self::PairDoesNotExist(IStablecoinExchange::PairDoesNotExist {})
126    }
127
128    /// Creates an error when pair already exists.
129    pub const fn pair_already_exists() -> Self {
130        Self::PairAlreadyExists(IStablecoinExchange::PairAlreadyExists {})
131    }
132
133    /// Creates an error when order does not exist.
134    pub const fn order_does_not_exist() -> Self {
135        Self::OrderDoesNotExist(IStablecoinExchange::OrderDoesNotExist {})
136    }
137
138    /// Creates an error when trying to swap identical tokens.
139    pub const fn identical_tokens() -> Self {
140        Self::IdenticalTokens(IStablecoinExchange::IdenticalTokens {})
141    }
142
143    /// Creates an error when a token address is not a valid TIP20 token.
144    pub const fn invalid_token() -> Self {
145        Self::InvalidToken(IStablecoinExchange::InvalidToken {})
146    }
147
148    /// Creates an error for tick out of bounds.
149    pub const fn tick_out_of_bounds(tick: i16) -> Self {
150        Self::TickOutOfBounds(IStablecoinExchange::TickOutOfBounds { tick })
151    }
152
153    /// Creates an error for invalid flip tick.
154    pub const fn invalid_flip_tick() -> Self {
155        Self::InvalidFlipTick(IStablecoinExchange::InvalidFlipTick {})
156    }
157
158    /// Creates an error for invalid tick.
159    pub const fn invalid_tick() -> Self {
160        Self::InvalidTick(IStablecoinExchange::InvalidTick {})
161    }
162
163    /// Creates an error for insufficient balance.
164    pub const fn insufficient_balance() -> Self {
165        Self::InsufficientBalance(IStablecoinExchange::InsufficientBalance {})
166    }
167
168    /// Creates an error for insufficient liquidity.
169    pub const fn insufficient_liquidity() -> Self {
170        Self::InsufficientLiquidity(IStablecoinExchange::InsufficientLiquidity {})
171    }
172
173    /// Creates an error for insufficient output.
174    pub const fn insufficient_output() -> Self {
175        Self::InsufficientOutput(IStablecoinExchange::InsufficientOutput {})
176    }
177
178    /// Creates an error for max input exceeded.
179    pub const fn max_input_exceeded() -> Self {
180        Self::MaxInputExceeded(IStablecoinExchange::MaxInputExceeded {})
181    }
182
183    /// Creates an error for order amount below minimum.
184    pub const fn below_minimum_order_size(amount: u128) -> Self {
185        Self::BelowMinimumOrderSize(IStablecoinExchange::BelowMinimumOrderSize { amount })
186    }
187
188    /// Creates an error for invalid base token.
189    pub const fn invalid_base_token() -> Self {
190        Self::InvalidBaseToken(IStablecoinExchange::InvalidBaseToken {})
191    }
192}