Liquidity and Relayer Fees #899
Replies: 7 comments 15 replies
-
One potential thought I had here was - what if we optionally allowed a library for on-chain gas usage metering (using the Leftover gas funds could either be refunded to the user directly after paying out the relayer, or they could be stored in a Leftovers contract where those funds would be stored with ownership mapped to the user (like router relayer fees), so that they can re-use them for future transfers - which would directly contribute to future fee savings for repeat users. |
Beta Was this translation helpful? Give feedback.
-
Ik it's just an example, but for I'm wondering if you meant "there should be a separate library" as "they should have a separate library" or "we should implement one"? |
Beta Was this translation helpful? Give feedback.
-
For 4. we'll obviously have to have a discussion with gelato about this pattern, as they'll have to implement some off-chain stuff on their side for:
However, we also need to discuss the fact that we'll basically be having the sequencer blindly submitting meta txs to gelato. I say 'blindly' because the alternative is that the sequencer does some awkward 'gatekeeping' and determines whether a user has posted enough relayer fee to merit relaying the tx. This means that we now have a hard requirement for the sequencer to cache gelato task IDs, or we risk it sending in duplicate tasks (i.e. meta txs for the same transfer) multiple times. Not a big deal, but we certainly don't want to DOS gelato with the same transfer |
Beta Was this translation helpful? Give feedback.
-
Finally, there is a small potential "attack" vector here.... gelato essentially has a monopoly on all our metatxs. They could potentially stonewall transfers to get users to pay higher amounts (they won't do this obvi, but we should aim for trustless-ness here lol). How can we make it so the relayer (whoever they may be lol) has an incentive to execute as soon as they see a transfer relayer fee that's sufficient for them? How do we prevent them from "holding out" in order to get higher fees? This could especially become problematic as a contract like a DAO might have some behavior to deterministically raise their relayer bid on an interval.... the relayer could literally just watch as the bid goes up and cash out whenever they want (or when the bid deterministically hits maximum). Might have to be glossed over for now... in the future when we aggregate multiple relayers (adding competition), this may be a non-issue |
Beta Was this translation helpful? Give feedback.
-
Don't forget to add the |
Beta Was this translation helpful? Give feedback.
-
For
I'm confused. The relayerFee is forwarded to the destination? Why? It might not even be accurate if the user bumps. |
Beta Was this translation helpful? Give feedback.
-
Summary
Users should pay the costs associated with the onchain transactions for their crosschain transfer. They should be able to specify these fees upfront, separately from the bridged asset amount and possible liquidity fee, so it is easy to include the
amount
in the calldata as needed as shown in the below picture:Motivation
There are costs associated with sending a transaction across chains, especially when arbitrary
calldata
is executed. The sequencer will be responsible for submitting these transactions via a relayer network (i.e. Gelato), but the user should be responsible for paying the incurred fees.Charging for relaying transactions is notoriously difficult, as the fees are assessed in a dynamic environment and only the submitter is able to alter the actual costs paid. In an asynchronous, cross-domain environment this problem is compounded. Not only does gas work very differently in each domain, but when using permissioned calls the gas estimate on the destination domain must be made far in advance of when the call is executed. These calls will use slow-liquidity and must wait the nomad optimistic timeout (currently 30 minutes) to ensure only the correct data is used.
You can see a breakdown of alternative solutions here.
Needs
amount
for functions executed on the destination domain (usually needs to be included in encodedcalldata
)Wants
Proposed Solution
A step-by-step breakdown of this proposal is:
User decides they want to create a crosschain transaction, and must determine the
relayerFee
.If the user can calculate the gas costs on the frontend (i.e. offchain), they call
sdk.estimateCost()
. This function will:provider.estimateGas
ConnextOracle
(can use the oracle with the best pricing)ConnextOracle
(can use the oracle with the best pricing)gasLimit
buffer and (2) provide incentive for relayerNOTE: It will not be possible to calculate gas fees offchain if you are using the slow-liquidity path because the permissioned
require
s will fail without the properties setIf the user must calculate the gas costs onchain, they will need to use an onchain library that will provide the following utility functions to calculate appropriate fees based on a provided amount of gas:
These functions will return an appropriate amount of native asset to send along as a
relayerFee
for the transaction, including a bump for fees.User gets
relayerFee
amount of native origin assetIf the user needs to swap for
relayerFee
from the transacting asset to the origin asset, then there should be a library for doing that (in DAO cases, they likely start with some starting amount of their treasury, for example):User calls
xcall
withamount
of transacting asset andrelayerFee
of origin domain native assetamount
is sent across chains via nomadrelayerFee
is custodied on the origin domainConnext.sol
(but included in theExecuteArgs
that are forwarded to the destination domain)Relayer sees gets the payload and independently determines if the
relayerFee
is sufficientmapping(address => mapping(uint32 => uint256) relayerFees
mapping stored onchain). ThetransferId
the relayer supported is stored onchain.execute
on the destination domain themselves and keep the relayer feebump(transferId)
on the origin domain to add value to their relayer feeWhen a relayer decides to claim their fees they call
initiateClaim(uint32 domain)
, which will use the following nomad router to send a claim to the specified domain:initiateClaim
function must use themsg.sender
to track the earned relayer fees.The
handle
function on theRelayerFeeRouter
would callclaimRelayerFee
which would tally all of the additional bumps and transfer the amounts to the specified recipient.Domain Requirements
RelayerFeeRouter
Test Cases
Outstanding Questions
Tasks
LibFeeEstimates
with the following interface:relayerFee
of native asset toBridgeMessage
/BridgeRouter
relayerFee
amount in theCallParams
, and debit the amount onxcall
relayerFee
tomsg.sender
onexecute
bump
fee on origin domainBeta Was this translation helpful? Give feedback.
All reactions