@Amxx Regarding the retry logic: it seems like that it implementation-specific, no? I hesitate to include that in the EIP. As you said earlier, different bridges have different retry logic.
I do like your additional specification around the gas field. However, it feels like there are two elements to this: how much gas the CrossChainReceiver#receiveCalls fxn uses, and how much each of the calls in the batch should use.
Here’s a diagram of the EIP in its current form:
There are a couple of issues here:
- The
CrossChainReceiver#receiveCalls()
fxn is called by the bridge layer. The bridge will only know the gas usage after thereceiveCalls
function is executed. This makes it hard to know costs up-front. - Each
Call
struct currently has agas
value, but really it’s up to the user-implemented CrossChainReceiver to respect that value. It’s not used directly by the ERC.
I noticed that in your bridge code it defines the call along the lines:
Bridge.crossChainCall(address target, bytes memory message, uint32 gasLimit)
This ERC has essentially encoded a batch of calls in the message. In your bridge, however, the gas limit essentially applies to the CrossChainReceiver#receiveCalls
function.
This makes a lot more sense to me, as it is deeply functional for the bridge: the bridge now knows the expected gas limit for the CrossChainReceiver#receiveCalls
function. This is made available on the sending chain as well, so the bridge could even take a payment on the sending side based on the required gas (a la the payable relayCalls
fxn)
This makes me think we should follow the same logic as your bridge by adding a gas limit:
interface CrossChainRelayer {
function relayCalls(CrossChainReceiver receiver, Call[] calldata calls, uint gasLimit);
}
We would then remove the gas
field from the Call
struct.
I don’t think the CrossChainReceiver
needs to know the gas limit, because the limit is simply applied to the call by the bridge.
Thoughts?