Closed tomusdrw closed 3 years ago
I've realised that relayers can increase gas price requirements arbitrary, so instead I propose a slight alteration.
We add ExpectedRelayTime
, which is for instance a moving average of the difference between delivery confirmation and message block creation time. Instead of paying the relayer (max_gas_price - RecentGasPrice) * gas_limit / 2
the price component is unlocked linearly if the ExpectedRelayTime
is exceeded. (Assume all ops are saturating) I.e.:
let relay_time_factor = min(1, (RelayTime - ExpectedRelayTime) / ExpectedRelayTime); // how much delayed are we? 0-1
(0.5 * max_gas_price + 0.5 * max_gas_price * relay_time_factor - RecentGasPrice) * gas_limit / 2
That way, relayers are incentivised to look for a smaller GasPrice
within ExpectedRelayTime
to get any profit. The incentivisation scheme most likely needs a lot of fine-tuning and way more analysis though, since long-term if the gas price stabilises there is little incentive for the relayers to actually take part, so a small fee might be required to be payed even if we stabilise at the optimal gas price.
Closing, since the ETH bridge is being worked as W3F Grant in polkadot-ethereum repositry. Happy to re-open if the outlook changes.
Neither #318 nor #215 delivery protocol is suitable for ETH Mainnet. They both require Substrate storage proofs, which in turn need a full header + state root for verification. The goal is to make a delivery-protocol that is going to be quite specific to Ethereum, and will not require any extra builtin contracts nor excessive data to provide alongside the proof. We also need to cater for Ethereum's low bandwidth and gas price fluctuations, so that the incentivisation mechanism is robust for the relayers to do their job. The bridge builds on top of #323
Each constant in the issue (i.e.
2x
or1/2
) is subject to discussion.Substrate -> ETH
The proposal is to create a substrate pallet that will be responsible for:
1/2
of the current block weight.Structures
Substrate pallet (Substrate side)
At the end of every block (or maybe in
on_initialize
of the next block):LastSetMessages
is not empty orMessagesOrdered
is empty we do nothing. (note we may consider having up to 2 (or more) message blocks pending)RecentBlockLimit / 2
messages from theMessagesOrdered
. (removed fromMessagesByHash
as well).LastSentMessages
value with theMessagesBlock
data.The idea is that the pallet will serve as a simple messages queue, ordered by the gas price the sender is willing to pay. The senders are expected to declare a gas price high enough (
2x
or more) so that we can be sure that it's possible for relayers to actually cover the costs on the ETH side. Since we trackRecentGasPrice
, which indicates the actual gas price the relayer had to use to get to the block, we can return the overpayed fee to the sender, but at the same we reward the relayer for not simply paying the highest possible fee (they also earn the difference betweengas_limit
and actualused_gas
).If the senders see that messages are not getting through, they can simply replace them with ones that pay higher fee - that way the relayers can decide to relay a block even below their profitability point, just to be able to unlock the next block.
Note that without any buffering, we may only start relaying the next
MessageBlock
if the previous one is on-chain and is confirmed to be final. This adds quite a lot of delay between messages, so a more sophisticated mechanism is most likely required.Solidity contract (ETH side)
A relay calls the contract and passes the next
MessagesBlock
. The contract then:parent_messages_hash
matches the last-received one storage in the state.messages_hash
matches the one we have in the MMR forsubstrate_block_number
.(MessagesHash, GasPriceOfTheTransaction, BlockGasLimit, Vec<DispatchSuccesful>)
ETH -> Substrate
This side seems a bit easier on the first sight. We might consider just generating ETH events in the contract and then have each event contain a separate message that get's relayed in-order (increasing nonce) to the substrate side. This scheme should be more alike #318, where each message (event) has:
The delivery is confirmed on the entire
Lane
and the confirmation releases the fee, locked on the ETH side. To trustlessly confirm delivery we need to make the lane state part of the MMR as well (A merkle-tree of lane statuses, with root hash placed in the MMR). I haven't thought exactly how we can propagate fee information from Substrate -> ETH yet, but I imagine this could happen through a system-generated (substrate's root account as a sender) messages transferred via Substrate -> ETH delivery protocol for instance (which would just update Solidity contract).