I’ve thought about how to respond to this a lot and I think ultimately I favor keeping originChainId at the top level of the Order struct.
The reason why is I think this standard is really designed to enable gasless cross chain intent orders and that means supporting AA frameworks with social momentum like Permit2 or 7702. I think using a single originChainId fits in best with these AA frameworks and is the easiest to support technically.
Also, I’m not sure in a vacuum how much I agree with this:
In a chain abstracted world user balances will be pulled parallely from several chains for the same order.
I think supporting multiple input chain ids makes the filler’s job (i.e. of handling input chain finality, tracking input chain accounts, tracking input chain market prices, etc.) exponentially more difficult and my instinct is this won’t be a large enough use case. If 7683 gets widely adopted and it becomes very common for users to be able to declare intents gasless-ly, then wouldn’t they be more likely to consolidate all of their funds on to a single “home” chain and use it to fund actions on arbitrary destination chains?
Thanks for putting in the work here and appreciate the open collaboration opportunity
Have been discussing this proposal with a few people and wanted to highlight a few important problems:
goal of making it easy for fillers is not fulfilled: The order and settlement contract are generic and impact essential details required by fillers to operate, meaning every filler will have to understand each order and how it impacts fulfillment anyway, the bytes while generic(add gas overhead) are important for fillers to interpret in order to make sure operations are done as user intended
fulfillment flow is non standardised: as someone pointed out above, the standard addresses only source-side of operations and not fulfillment breaking the loop, fillers will need to work with order specific fulfillment flows
the standard order is application specific: while the proposal attempts at being as generic as possible still constrains the application developer in a couple of ways already, the proposal is limit order based which tend to be fragile in async environments as highlighted here + order is incompatible with authorisations that span multiple input chains which makes it un-desireable to get to the desired UX
Ultimately, it seems like while making things easier for fillers is the intention here it doesnt get us there, fillers need to still interpret each order-type to fill it + it adds gas overhead due to additional bytes encoding/decoding that is needed. While at it, the standard order while being minimal is incompatible with upcoming applications which might not want to do limit orders and want to accept input tokens from multiple chains to provide the best experience
Keen to discuss and find solutions to above, it does seem like standardising at this layer is hard due to the tradeoff between finding a good enough standard interface while also making fillers generic.
curious to hear what others might think and again huge props for starting the discussion on this
Agree with @vaibhavchellani, the impact of gas is underestimated. While the standardisation of the data will help make cross chain orders readable through a wide variety of scenarios, The reality will be that intent systems will tend to optimise call data and specialise their contracts in order to provide competitive execution and features. An example of specialisation alluded to in the spec is permit2 which has a rough definition but you can also consider standard permit which is unrepresented.
A more verbose representation of intents that covers all scenarios which extends with time may be useful for off chain consumption. Where intent systems can publish their data optionally in this format.
Wanted to echo this – In the way the generic bytes exist today, the proposed standard effectively serves as a thin framework for fillers. Fillers needing to interpret the bytes per implementation creates significant burden (orderData contains pretty essential details).
Keen to hear how people are thinking about fillers dealing with the numerous orderData types. This is obviously a tough balance to strike between standardization and allowing implementations to still create new interesting features while matching the standard.
I’m skeptical about this. Most users move assets for the sake of yield events, but they won’t consolidate assets back to their original locations just for the sake of consolidation. I believe that yield opportunities on different chains will cause users’ assets to be scattered all over the place.
An open standard makes sense for very simple scenarios (such as a cross-chain swap between USDC <> USDC), but for more complex actions may crowd out innovation, and may be counter-productive. Much of the innovation around cross-chain intents is packaging additional complexity with varying tradeoffs (gas etc.).
If relayers opt-into a singular standard for more generalized use cases, I worry that innovation from protocols like Klaster, who bundles a series of txns together, will suffer. Specificically defining, and likely reducing the scope would be a helpful activity
Should we use this version for building on 7683 instead?
A few feedbacks about it:
I think all interfaces and types pushed to the standard should be tried to be compiled first. Almost all of them are syntactically incorrect and/or supplied with incorrect Natspec. We fixed this internally, but not sure if we did it as designed ; )
It looks like Output is meant to show minimum inflows for the intent to be considered fulfilled. Would it make sense to introduce a bool fixedOutput that requires some inflows to be exactly the number specified in Output, rather than at least it? This is certainly a feature we’d want in our workflow, but not sure if we should implement it outside the struct.
Continuing this logical chain, Input might need to implement this flag too. In case some kind of Dutch auction is used, how will the filler know how much they’ll receive without knowing anything about the settlement contract (other than its 7683-compliance)?
I’m not sure if it makes sense for anyone but us given EVM-standardized destination settlement contract, but in case the destination chain is not fully/not EVM-compliant and does not use Ethereum’s 60’ SLIP-44 coin ID, would it make sense to store chain ID in a uint32, where EVM chain IDs must be < 0x80000000, and non-EVM chain IDs (SLIP-44 coin IDs) must be >=0x80000000? According to Chainlist, virtually all live EVM networks have their chain IDs fit to this requirement.
I believe that ERC-7683 will come outside the EVM environment fairly quickly, thanks to alt-VM rollups, and it seems that at least SVM, Starknet, and Fuel are using SLIP-44 for their key derivation.
If you go with implementing the feature above, destination settlement contract should not be enforced to comply with provided interface in case destinationChainId is >= 0x80000000. However, it’s not clear to me how to exactly enforce standardization of DSCs in a non-EVM environment. Maybe, you’ll have some thoughts about this.
Otherwise, everything looks good to me. I’m very excited about this standard and look forward to building on it.
I think all interfaces and types pushed to the standard should be tried to be compiled first. Almost all of them are syntactically incorrect and/or supplied with incorrect Natspec. We fixed this internally, but not sure if we did it as designed ; )
Sorry about that. I’ve been making a bunch of changes recently based on comments on the PR, but haven’t actually compiled it in a while. Should be fixed.
It looks like Output is meant to show minimum inflows for the intent to be considered fulfilled. Would it make sense to introduce a bool fixedOutput that requires some inflows to be exactly the number specified in Output , rather than at least it? This is certainly a feature we’d want in our workflow, but not sure if we should implement it outside the struct.
I don’t think this is how the standard is intended to work (which may mean we may need to add some clarification). Meeting the minSpent is not sufficient for an intent to be considered fulfilled. The DestinationSettler’s fill method will revert if the requirements for fulfillment aren’t satisfied. So, if the actual amount that’s needed to be paid to satisfy the intent depends on some state on the destination chain, for instance, the DestinationSettler can take that into account and revert if the filler doesn’t satisfy that requirement.
Does that make sense?
I’m not sure if it makes sense for anyone but us given EVM-standardized destination settlement contract, but in case the destination chain is not fully/not EVM-compliant and does not use Ethereum’s 60’ SLIP-44 coin ID, would it make sense to store chain ID in a uint32, where EVM chain IDs must be < 0x80000000, and non-EVM chain IDs (SLIP-44 coin IDs) must be >=0x80000000? According to Chainlist, virtually all live EVM networks have their chain IDs fit to this requirement.
I believe that ERC-7683 will come outside the EVM environment fairly quickly, thanks to alt-VM rollups, and it seems that at least SVM, Starknet, and Fuel are using SLIP-44 for their key derivation.
Yeah, the chainId question is hard because there’s no universal set of identifiers. Originally, I was thinking 64 bits where you reserve >=0x8000.... for non EVM chains, but I think there is some desire to support chainIds that are hashes of chain names, so it may make sense to go back to a 256 bit field, as is common outside of 7683.
Thoughts?
If you go with implementing the feature above, destination settlement contract should not be enforced to comply with provided interface in case destinationChainId is >= 0x80000000. However, it’s not clear to me how to exactly enforce standardization of DSCs in a non-EVM environment. Maybe, you’ll have some thoughts about this.
The interfaces described in the standard only apply if that contract exists on an EVM chain. If it’s a non-EVM chain, then the requirement does not apply, and the cross-compatible standard for that ecosystem would apply instead.
Maybe we could make that clearer, though. Thoughts?
Hmm yes I think so. I’m thinking if 7685 needs some very basic elaborations in the workflow of intents and what use cases it tries to cover. Currently, it’s pretty complicated to dive into using it as an external team, as you need to guess what a certain thing was added for by the proposal’s creators.
Honestly, we’re not an intents-native team unlike, say, Across, so there might be some things that are necessary for more expressive usage of intents, just not ours. Hence why I don’t get them😅
Thoughts?
Yes, I think using 256-bit slot would be the best approach, especially given the recent ERC-7785 proposal.
Regarding your take on destination settlers, I think there should be some elaboration, like “if the settler contract == bytes32(0), then the intent can be filled through any logic”. However here comes a race condition issue, and I’m not sure if fixing it with temporary exclusivity (as in Across) is a good idea.
Hi! This looks really great. We have a super clear use case for this, at Peanut we do send-anything-receive-anything payments. I’d love to add support for 7683.
Is any solver actually live with this? Or any liquidity layer considering adding support any time soon?
It will be good to understand if with Cross Chain intents we could achieve nearly free transactions across chains with no token swap?
From a payments processing point of view we need free transactions even if they are cross rollups. So Bob can pay Alice Flowers with USDC on Base and Alice can get in the chain she wants with virtually no cost. For more background you can read this article: hackmd (dot) io/@sprintcheckout/L1-L2-chain-fragmentation
Thanks.
/// @dev The max outputs that the filler will send. It's possible the actual amount depends on the state of the destination
/// chain (destination dutch auction, for instance), so these outputs should be considered a cap on filler liabilities.
Output[] maxSpent;
/// @dev The minimum outputs that must be given to the filler as part of order settlement. Similar to maxSpent, it's possible
/// that special order types may not be able to guarantee the exact amount at open time, so this should be considered
/// a floor on filler receipts.
Output[] minReceived;
I would like some clarifications in this part. The user is generating the intents. Filler will be accepting the intents and fulfilling them by fronting liquidity. So I assume the user’s funds should be locked in the source chain settlement contract. So the user should specify how much funds the contract can lock right? I think whatever amount we lock, the filler is not likely to get any more as if we do not lock, the user can just prevent the contract from getting more funds. So the max amount they are willing to spend for this intent should be specified upfront by the user, right? Am I missing something?
ERC-7683 simplifies multichain interactions by creating a unified framework for intent-based actions like token transfers and swaps. Many (including Vitalik) consider ERC-7683 a critical component of the plan to make L2s less fragmented and improve cross-chain UX for users.
This article (from 2077 Research explores how ERC-7683 aims to streamline execution, boost liquidity access, and enhance interoperability. We also discuss the challenges/considerations associated with ERC-7683 as well as the implications of adopting the standard for the wider ecosystem.
So I assume the user’s funds should be locked in the source chain settlement contract.
I think this is true for most settlement systems today but its not prescribed by the ERC.
So the user should specify how much funds the contract can lock right?
So the user doesn’t need to set the minReceived, in fact this should ideally be set by the settlement contract where the 7683 is open-ed. A very simple vanilla settlement system might return the exact amount input by the user as the minReceived, while others might charge a fee.
Similarly with maxSpent, its up to the settlement system to signal to the filler the maximum of outputs that the filler will owe to the user on the destination chain settlement system.
Also, the settlement system should ideally respect whatever the minReceived and maxOutputs values are set to, otherwise fillers won’t be able to trust the system or use it reliably.
So the max amount they are willing to spend for this intent should be specified upfront by the user, right?
In summary, I think most settlement systems would set the max amount that the filler should be expected to spend based on the user’s input amount, however the settlement system chooses this input amount.
makes sense. However I want to understand, in this scenario isn’t there a minimum that the user need to specify on the output. Here we are specifying the maxSpent. We do not specify any minimum value the filler needs to fulfil on the destination chain.
How will the settlement system know whether the fulfilment is satisfying the user intent. The filler should fulfil some minimum amount for the user right?
I believe we should try to standardize subtypes via ERCs. This may already be the goal when saying a subtypes repository, but this specification is better in my opinion.
Instead of:
All sub-types SHOULD be registered in a subtypes repository to encourage sharing of sub-types based on their functionality.
I suggest for it to be changed to something like what is in EIP-7786:
Sub-types SHOULD be standardize by publishing them as ERCs to encourage sharing of sub-types based on their functionality.
How will the settlement system know whether the fulfilment is satisfying the user intent. The filler should fulfil some minimum amount for the user right?
This is where the settlement-specific logic comes into play. Settlement systems might force the order to contain a settlement-specific struct including information like outputAmount.
The ERC is designed primarily for improving filler experience.