@@ -9,8 +9,8 @@ use alloy_primitives::{Address as AlloyAddress, FixedBytes, U256};
99use alloy_sol_types:: { sol, SolCall , SolValue } ;
1010use async_trait:: async_trait;
1111use solver_types:: {
12- Address , ConfigSchema , Eip7683OrderData , ExecutionParams , FillProof , Intent , NetworksConfig ,
13- Order , OrderStatus , Schema , Transaction ,
12+ oracle :: OracleRoutes , Address , ConfigSchema , Eip7683OrderData , ExecutionParams , FillProof ,
13+ Intent , NetworksConfig , Order , OrderStatus , Schema , Transaction ,
1414} ;
1515
1616// Solidity type definitions for EIP-7683 contract interactions.
@@ -82,9 +82,12 @@ sol! {
8282/// # Fields
8383///
8484/// * `networks` - Networks configuration containing settler addresses for each chain
85+ /// * `oracle_routes` - Oracle routes for validation of input/output oracle compatibility
8586pub struct Eip7683OrderImpl {
8687 /// Networks configuration for dynamic settler address lookups.
8788 networks : NetworksConfig ,
89+ /// Oracle routes for validation of input/output oracle compatibility.
90+ oracle_routes : OracleRoutes ,
8891}
8992
9093impl Eip7683OrderImpl {
@@ -93,15 +96,19 @@ impl Eip7683OrderImpl {
9396 /// # Arguments
9497 ///
9598 /// * `networks` - Networks configuration with settler addresses
96- pub fn new ( networks : NetworksConfig ) -> Result < Self , OrderError > {
99+ /// * `oracle_routes` - Oracle routes for validation
100+ pub fn new ( networks : NetworksConfig , oracle_routes : OracleRoutes ) -> Result < Self , OrderError > {
97101 // Validate that networks config has at least 2 networks
98102 if networks. len ( ) < 2 {
99103 return Err ( OrderError :: ValidationFailed (
100104 "At least 2 networks must be configured" . to_string ( ) ,
101105 ) ) ;
102106 }
103107
104- Ok ( Self { networks } )
108+ Ok ( Self {
109+ networks,
110+ oracle_routes,
111+ } )
105112 }
106113}
107114
@@ -197,8 +204,81 @@ impl OrderInterface for Eip7683OrderImpl {
197204 return Err ( OrderError :: ValidationFailed ( "Order expired" . to_string ( ) ) ) ;
198205 }
199206
207+ // Validate oracle routes
208+ let origin_chain = order_data. origin_chain_id . to :: < u64 > ( ) ;
209+ let input_oracle = solver_types:: utils:: parse_address ( & order_data. input_oracle )
210+ . map_err ( |e| OrderError :: ValidationFailed ( format ! ( "Invalid input oracle: {}" , e) ) ) ?;
211+
212+ let input_info = solver_types:: oracle:: OracleInfo {
213+ chain_id : origin_chain,
214+ oracle : input_oracle,
215+ } ;
216+
217+ // Check if the input oracle is supported
218+ if !self
219+ . oracle_routes
220+ . supported_routes
221+ . contains_key ( & input_info)
222+ {
223+ return Err ( OrderError :: ValidationFailed ( format ! (
224+ "Input oracle {} on chain {} is not supported" ,
225+ order_data. input_oracle, origin_chain
226+ ) ) ) ;
227+ }
228+
229+ // Get supported output oracles for this input oracle
230+ let supported_outputs = self
231+ . oracle_routes
232+ . supported_routes
233+ . get ( & input_info)
234+ . ok_or_else ( || {
235+ OrderError :: ValidationFailed ( format ! (
236+ "No routes configured for input oracle {} on chain {}" ,
237+ order_data. input_oracle, origin_chain
238+ ) )
239+ } ) ?;
240+
241+ // Validate each output oracle
242+ for output in & order_data. outputs {
243+ let dest_chain = output. chain_id . to :: < u64 > ( ) ;
244+
245+ // If output oracle is zero (0x00...), it means use any compatible oracle
246+ // Otherwise, validate the specific oracle
247+ if output. oracle != [ 0u8 ; 32 ] {
248+ // Parse the oracle address from bytes32 (take first 20 bytes)
249+ let output_oracle_bytes = & output. oracle [ 12 ..32 ] ; // Last 20 bytes for address
250+ let output_oracle = Address ( output_oracle_bytes. into ( ) ) ;
251+
252+ let output_info = solver_types:: oracle:: OracleInfo {
253+ chain_id : dest_chain,
254+ oracle : output_oracle,
255+ } ;
256+
257+ // Check if this output oracle is in the supported list
258+ if !supported_outputs. contains ( & output_info) {
259+ return Err ( OrderError :: ValidationFailed ( format ! (
260+ "Output oracle {:?} on chain {} is not compatible with input oracle {} on chain {}" ,
261+ output. oracle, dest_chain, order_data. input_oracle, origin_chain
262+ ) ) ) ;
263+ }
264+ } else {
265+ // Zero oracle means any oracle on the destination chain is acceptable
266+ // Just verify that there's at least one oracle for this destination
267+ let has_route_to_dest = supported_outputs
268+ . iter ( )
269+ . any ( |info| info. chain_id == dest_chain) ;
270+
271+ if !has_route_to_dest {
272+ return Err ( OrderError :: ValidationFailed ( format ! (
273+ "No route available from chain {} to chain {}" ,
274+ origin_chain, dest_chain
275+ ) ) ) ;
276+ }
277+ }
278+ }
279+
200280 // Extract chain IDs
201- let input_chain_ids = vec ! [ order_data . origin_chain_id . to :: < u64 > ( ) ] ;
281+ let input_chain_ids = vec ! [ origin_chain ] ;
202282 let output_chain_ids = order_data
203283 . outputs
204284 . iter ( )
@@ -623,12 +703,13 @@ impl OrderInterface for Eip7683OrderImpl {
623703pub fn create_order_impl (
624704 config : & toml:: Value ,
625705 networks : & NetworksConfig ,
706+ oracle_routes : & solver_types:: oracle:: OracleRoutes ,
626707) -> Result < Box < dyn OrderInterface > , OrderError > {
627708 // Validate configuration first
628709 Eip7683OrderSchema :: validate_config ( config)
629710 . map_err ( |e| OrderError :: InvalidOrder ( format ! ( "Invalid configuration: {}" , e) ) ) ?;
630711
631- let order_impl = Eip7683OrderImpl :: new ( networks. clone ( ) ) ?;
712+ let order_impl = Eip7683OrderImpl :: new ( networks. clone ( ) , oracle_routes . clone ( ) ) ?;
632713 Ok ( Box :: new ( order_impl) )
633714}
634715
0 commit comments