| 780 | |
| 781 | #[instrument(skip_all)] |
| 782 | async fn validate_and_construct_order( |
| 783 | &self, |
| 784 | order: OrderCreation, |
| 785 | domain_separator: &DomainSeparator, |
| 786 | settlement_contract: Address, |
| 787 | full_app_data_override: Option<String>, |
| 788 | ) -> Result<(Order, Option<Quote>), ValidationError> { |
| 789 | // Happens before signature verification because a miscalculated app data hash |
| 790 | // by the API user would lead to being unable to validate the signature below. |
| 791 | let app_data = self.validate_app_data(&order.app_data, &full_app_data_override)?; |
| 792 | let app_data_signer = app_data.inner.protocol.signer; |
| 793 | |
| 794 | let owner = order.verify_owner(domain_separator, app_data_signer)?; |
| 795 | tracing::debug!(?owner, "recovered owner from order and signature"); |
| 796 | let signing_scheme = order.signature.scheme(); |
| 797 | let data = OrderData { |
| 798 | app_data: app_data.inner.hash, |
| 799 | ..order.data() |
| 800 | }; |
| 801 | let uid = data.uid(domain_separator, owner); |
| 802 | |
| 803 | // Cheap in-memory rejection checks run before the eth_call-driven |
| 804 | // verification step below so banned users, forbidden tokens, and |
| 805 | // zero-amount orders fail fast without consuming a simulation-node |
| 806 | // round-trip. |
| 807 | if data.buy_amount.is_zero() || data.sell_amount.is_zero() { |
| 808 | return Err(ValidationError::ZeroAmount); |
| 809 | } |
| 810 | |
| 811 | let pre_order = PreOrderData::from_order_creation(owner, &data, signing_scheme); |
| 812 | let class = pre_order.class; |
| 813 | self.partial_validate(pre_order) |
| 814 | .await |
| 815 | .map_err(ValidationError::Partial)?; |
| 816 | |
| 817 | let preview_order = Order { |
| 818 | metadata: OrderMetadata { |
| 819 | owner, |
| 820 | uid, |
| 821 | ..Default::default() |
| 822 | }, |
| 823 | data, |
| 824 | signature: order.signature.clone(), |
| 825 | interactions: app_data.interactions.clone(), |
| 826 | }; |
| 827 | let full_app_data = app_data.inner.document.clone(); |
| 828 | let hash = hashed_eip712_message(domain_separator, &data.hash_struct()); |
| 829 | |
| 830 | let eip1271_check = if let Signature::Eip1271(sig) = &order.signature |
| 831 | && !self.eip1271_skip_creation_validation |
| 832 | { |
| 833 | Some(SignatureCheck::new( |
| 834 | owner, |
| 835 | hash.0, |
| 836 | sig.to_owned(), |
| 837 | app_data.interactions.pre.clone(), |
| 838 | app_data |
| 839 | .inner |