From fb37d60ce804b93197823dc36141800cc3a8ce07 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 17 Jan 2025 22:11:12 +0100 Subject: [PATCH 01/29] feat: Support pending SpokePool upgrades This is a first pass at establishing concurrent support for the new & legacy events. There's stilll work to be done to (at least): - Specify how to handle new relayer repayment capabilities. - Specify how to handle pre-fills where the relayer orchestrates the deposit after the fill. There are edge cases to consider. --- UMIPs/umip-179.md | 221 +++++++++++++++++++++++++++++++++------------- 1 file changed, 161 insertions(+), 60 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index b194c76f..4e92c86d 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -39,25 +39,50 @@ All global constants from UMIP-157 will be retained for use in Across v3. The gl * This shall be a stringified list of chain ID numbers. Each chain in this list shall also appear in the `CHAIN_ID_INDICES` list. There shall be no duplicates in this list; any `LITE_CHAIN_ID_INDICES` update containing duplicates may be ignored. Chains may be removed from the `LITE_CHAIN_ID_INDICES` list in order to remove their "Lite" chain designation. ## Data Types -Across v3 introduces the following new data types: +Across v3 defines the following data types: ### V3RelayData -The V3RelayData type underpins the transfer of funds in or out of a SpokePool instance. V3RelayData is defined as follows: +The `V3RelayData` type underpins the transfer of funds in or out of a SpokePool instance. `V3RelayData` is defined as follows: | Name | Type | Description | | :--- |:---- | :---------- | -| depositor | address | The address that made the deposit on the origin chain. | -| recipient | address | The recipient address on the destination chain. | -| exclusiveRelayer | address | The optional exclusive relayer who can fill the deposit before the exclusivity deadline. | -| inputToken | address | The token that is deposited on the origin chain by the depositor. | -| outputToken | address | The token that is received on the destination chain by the recipient. | +| depositor | bytes32 | The address that made the deposit on the origin chain. | +| recipient | bytes32 | The recipient address on the destination chain. | +| exclusiveRelayer | bytes32 | The optional exclusive relayer who can fill the deposit before the exclusivity deadline. | +| inputToken | bytes32 | The token that is deposited on the origin chain by the depositor. | +| outputToken | bytes32 | The token that is received on the destination chain by the recipient. | | inputAmount | uint256 | The amount of inputToken that is deposited by the depositor. | | outputAmount | uint256 | The amount of outputToken that is received by the recipient. | | originChainId | uint256 | The chain ID of the origin SpokePool. | -| depositId | uint32 | The ID uniquely identifying a deposit on the origin chain. | +| depositId | uint256 | The ID identifying a deposit on the origin chain. | | fillDeadline | uint32 | The Unix timestamp on the destination chain after which the deposit can no longer be filled. | | exclusivityDeadline | uint32 | The optional Unix timestamp on the destination chain after which any relayer can fill the deposit. | | message | bytes | Optional data that is forwarded to the recipient as part of a relay. | +#### Note +- `V3RelayData` specifies `bytes32` representation for addresses (`depositor`, `recipient`, ...) in order to interface with non-EVM chains. EVM addressed supplied shall be promoted to type `bytes32` with the upper bytes zeroed. + +### V3RelayDataLegacy +The `V3RelayDataLegacy` type is supported for backwards compatibility, but is slated for deprecation. `V3RelayDataLegacy` has the following delta to the `V3RelayData` type: +| Name | Type | +| :--- |:---- | +| depositor | address | +| recipient | address | +| exclusiveRelayer | address | +| inputToken | address | +| outputToken | address | +| depositId | uint32 | + +## V3RelayExecutionParams +The `V3RelayExecutionParams` type is supplied by a relayer or executor when completing a fill. `V3RelayExecutionParams` is defined as follows: +| Name | Type | Description | +| :--- |:---- | :---------- | +| relay | V3RelayData | The V3RelayData object corresponding to the origin chain deposit to be filled. | +| relayHash | bytes32 | The keccak256 hash of the V3RelayData object. See also [Computing RelayData hashes](#computing-relaydata-hashes). | +| updatedOutputAmount | uint256 | The effective amount to be received by the recipient. This may be different to the deposit outputAmount. | +| updatedRecipient | bytes32 | The effective recipient address. This may be different to the deposit recipient. | +| updatedMessage | bytes | The effective message (if any) to be executed by the destination SpokePool. | +| repaymentChainId | uint256 | The repayment chain ID requested by the relayer completing the fill. This field is not relevant for slow fills. | + ### FillStatus A mapping of `RelayData` -> `FillStatus` is stored within each SpokePool instance. This mapping can be queried with the hashed `V3RelayData` for a deposit, allowing the status for the corresponding fill to be queried. @@ -81,7 +106,7 @@ A V3RelayExecutionEventInfo instance is emitted with each `FilledV3Relay` event | Name | Type | Description | | :--- |:---- | :---------- | -| updatedRecipient | address | The recipient of the funds being transferred. This may be the `recipient` identified in the original deposit, or an updated `recipient` following a `RequestedSpeedUpV3Deposit` event. | +| updatedRecipient | bytes32 | The recipient of the funds being transferred. This may be the `recipient` identified in the original deposit, or an updated `recipient` following a `RequestedSpeedUpV3Deposit` event. | | updatedOutputAmount | uint256 | The amount sent to `updatedRecipient` by the relayer completing the fill. | | updatedMessage | bytes | Data that is forwarded to the recipient as part of a relay. | | repaymentChainId | uint256 | The chain specified by the depositor for fill repayment. | @@ -102,20 +127,50 @@ A V3SlowFill instance is emitted with each `FilledV3Relay` event (see below). The `updatedRecipient` field is normally set to the `recipient` from the corresponding `V3FundsDeposited` event. In the event that the relayer completes the fill with an accompanying `RequestedSpeedUpV3Deposit` event, `updatedRecipient` will be set to the address approved by the update. ## Events -Across V3 defines the following new events: +Across V3 defines the following events: +- FundsDeposited - V3FundsDeposited +- RequestedSpeedUpDeposit - RequestedSpeedUpV3Deposit +- FilledRelay +- FilledV3Relay +- RequestedSlowFill - RequestedV3SlowFill +- ClaimedRelayerRefund + +### Event Deprecation +The following events are marked for future deprecation. Deprecation will be announced in a future update to this specification. +- V3FundsDeposited +- RequestedSpeedUpV3Deposit - FilledV3Relay +- RequestedV3SlowFill + +### FundsDeposited, V3FundsDeposited +The `FundsDeposited` event emits the unique `V3RelayData` for an individual deposit. No additional fields are defined. +The `V3FundsDeposited` event emits the unique `V3RelayDataLegacy` for an individual deposit. No additional fields are defined. -### V3FundsDeposited -The `V3FundsDeposited` event emits the unique `V3RelayData` for an individual deposit. No additional fields are defined. Consumers of this event should append the `originChainId` in order to avoid unintentionally mixing events from different chains. +Consumers of these events should append the `originChainId` in order to avoid unintentionally mixing events from different chains. Note: -- The `V3FundsDeposited` `outputToken` is not required to be a known HubPool `l1Token`. In-protocol arbitrary token swaps are technically supported by Across v3. +- The `FundsDeposited` and `V3FundsDeposited` `outputToken` field is not required to be a known HubPool `l1Token`. In-protocol arbitrary token swaps are technically supported by Across v3. +- The address identified by `exclusiveRelayer` has exclusive right to complete the relay on the destination chain until `exclusivityDeadline` has elapsed. +- If `exclusivityDeadline` is set to a past timestamp, any address is eligible to fill the relay. +- Any deposit that remains unfilled after the specified `fillDeadline` shall be refunded to the `depositor` address via the origin SpokePool in a subsequent settlement bundle. + +### RequestedSpeedUpDeposit, RequestedSpeedUpV3Deposit +The `RequestedSpeedUpDeposit` event emits the following data. + +| Name | Type | Description | +| :--- | :--- | :---------- | +| depositId | uint256 | The depositId of the corresponding `FundsDeposited` event to be updated. | +| depositor | bytes32 | The depositor of the corresponding `FundsDeposited` event to be updated. | +| updatedOutputAmount | uint256 | The new outputAmount approved by the depositor. This should be _lower_ than the original deposit `outputAmount`. | +| updatedRecipient | bytes32 | The new recipient to receive the funds. | +| updatedMessage | bytes | The new message to be supplied to the recipient. | +| depositorSignature | bytes | A signature by the depositor authorizing the above updated fields. | + +The `RequestedSpeedUpV3Deposit` event emits the following data: -### RequestedSpeedUpV3Deposit -The `RequestedSpeedUpV3Deposit` emits specifies the following fields: | Name | Type | Description | | :--- | :--- | :---------- | | depositId | uint32 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | @@ -126,28 +181,38 @@ The `RequestedSpeedUpV3Deposit` emits specifies the following fields: | depositorSignature | bytes | A signature by the depositor authorizing the above updated fields. | Note: -- Relayers may optionally append the updated request from a `RequestedSpeedUpV3Deposit` when filling a relay, but have no obligation to use the updated request. -- The address identified by `exclusiveRelayer` has exclusive right to complete the relay on the destination chain until `exclusivityDeadline` has elapsed. -- If `exclusivityDeadline` is set to a past timestamp, any address is eligible to fill the relay. -- Any attempted fill that occurs after `fillDeadline` has elapsed shall be rejected by the destination SpokePool. The corresponding deposit shall be refunded via the origin SpokePool in the relevant settlement bundle. +- Relayers may optionally append the updated request from a `RequestedSpeedUpDeposit` or `RequestedSpeedUpV3Deposit` event when filling a relay, but have no obligation to use the updated request. -### RequestedV3SlowFill -The `RequestedV3SlowFill` event emits `V3RelayData`. This event is emitted on the destination chain and is intended to signal to proposers that a slow fill has been requested. +### RequestedSlowFill, RequestedV3SlowFill +The `RequestedSlowFill` event emits an `V3RelayData` instance. +The `RequestedV3SlowFill` event emits an `V3RelayDataLegacy` instance. + +These events are emitted on the destination chain and signal to proposers that a slow fill has been requested for a specific deposit. Note: -- `RequestedV3SlowFill` events cannot occur until the `exclusivityDeadline` timestamp has elapsed on the destination chain. +- `RequestedV3SlowFill` events cannot be emitted until the `exclusivityDeadline` timestamp has elapsed on the destination chain. - `RequestedV3SlowFill` events cannot be emitted once the `fillDeadline` timestamp has elapsed on the destination chain. -### FilledV3Relay -The `FilledV3Relay` event extends the `V3RelayData` type by adding the following fields: +### FilledRelay, FilledV3Relay + +The `FilledRelay` event extends the `V3RelayData` type by applying the following adjustments: +| Name | Type | Description | +| :--- | :--- | :---------- | +| message | omitted | This field is omitted from the `FilledRelay` event in favour of the `messageHash` field. | +| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field. This field is included in place of the `V3RelayData` message field. See also [Computing RelayData hashes](#computing-relaydata-hashes). | +| relayer | bytes32 | The address completing relay on the destination SpokePool. | +| repaymentChainId | uint256 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | +| relayExecutionInfo | V3RelayExecutionEventInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | + +The `FilledV3Relay` event extends the `V3RelayDataLegacy` type by adding the following fields: | Name | Type | Description | | :--- | :--- | :---------- | | relayer | address | The address completing relay on the destination SpokePool. | | repaymentChainId | uint256 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | -| relayExecutionInfo | V3RelayExecutionInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | +| relayExecutionInfo | V3RelayExecutionEventInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | Note: -- Consumers of this event should append the `destinationChainId` attribute in order to avoid unintentioanlly mixing events from different chains. +- Consumers of these events should append the `destinationChainId` attribute in order to avoid unintentioanlly mixing events from different chains. # Root Bundle Proposals @@ -197,17 +262,39 @@ Across v3 `SlowRelayLeaf` objects are defined by the `V3SlowFill` [data type](#d Note: - The format of Slow Relay leaves is updated from Across v2. +## Definitions + +### Deposits +A Deposit event is defined as an instance of either of the following events: +- `FundsDeposited`. +- `V3FundsDeposited`. + +### Fills +A Fill event is defined as an instance of either of the following events: +- `FilledRelay`. +- `FilledV3Relay`. + +### Slow Fill Requests +A Slow Fill event is defined as an instance of either of the following events: +- `RequestedSlowFill`. +- `RequestedV3SlowFill`. + +### RelayData +RelayData is defined as an instance of etiher of the following data types: +- `V3RelayData`. +- `V3RelayDataLegacy`. + ## Method ### Identifying SpokePool Contracts The current SpokePool address for a specific chain is available by querying `HubPool.crossChainContracts()`. The chainId must be specified in the query. In case of SpokePool migations, historical SpokePool addresses can be identified by scraping HubPool `CrossChainContractsSet` events. -### Identifying a chains inclusion as a "Lite" Chain +### Identifying "Lite" deployments We consider a deposit to "originate" or be "destined for" a "Lite chain" if the `LITE_CHAIN_ID_INDICES` value in the AcrossConfigStore includes the deposit's origin chain or destination chain respectively as of the deposit's `quoteTimestamp` field. These chains impose constraints on relayer repayments and slow fills. ### Resolving SpokePool tokens to their HubPool equivalent For the purpose of identifying the equivalent HubPool token given a SpokePool token, the following shall be followed: 1. Find the latest `SetRebalanceRoute` event with a block timestamp at or before the relevant HubPool block number, where the relevant SpokePool chain ID and token address match the `SetRebalanceRoute` `destinationChainId` and `destinationToken` fields. - - In the case of a `V3FundsDeposited` event, the relevant HubPool block number is identified by resolving the `quoteTimestamp` to a HubPool block number. + - In the case of a `Deposit` event, the relevant HubPool block number is identified by resolving the `quoteTimestamp` to a HubPool block number. 3. From the resulting `SetRebalanceRoute` event, select the associated `l1Token` field. 4. Search the `SetPoolRebalanceRoute` events for the same `l1Token` and `destinationChainId` at or before the applicable HubPool block number. 5. Using the `l1Token` value found in step 2, search for the latest `SetRebalanceRoute` event at or before the applicable HubPool block number where `l1Token` and `destinationChainId` that match the extracted `l1Token` and SpokePool chain ID. If a match is found, the addresses match and are considered cross-chain equivalents. @@ -218,15 +305,26 @@ In addition to the description [UMIP-157](https://github.com/UMAprotocol/UMIPs/b - A "soft pause" of a chain is permitted in the event that the proposer cannot safely increment the bundle block range, or has no events to propose beyond the previous bundle block range. In this case, the proposer may repeat the procedure for DISABLED_CHAINS by proposing from and to the previous bundle end block. +### Computing RelayData Hashes +#### V3RelayData +The `V3RelayData` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: +- `relayData` is of type `V3RelayData`. +- `destinationChainId` is of type `uint256`. + +#### V3RelayDataLegacy +The `V3RelayDataLegacy` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: +- `relayData` is of type `V3RelayDataLegacy` +- `destinationChainId` is of type `uint256`. + ### Finding Valid Relays -For the purpose of computing relayer repayments, each `FilledV3Relay` event emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: -1. The `FilledV3Relay` `FillType` field is not set to `SlowFill`, -2. The component `V3RelayData` maps exactly to a corresponding `V3FundsDeposited` event emitted on the relevant `originChainId`. This may be compared by comparing the hashes of the two objects. +For the purpose of computing relayer repayments, each of the `Fill` events emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +1. The `Fill` event `FillType` field is not set to `SlowFill`, +2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be compared by comparing the hashes of the two objects. -If the `V3FundsDeposited` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `V3RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. +If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. ### Finding Expired Deposits -For the purpose of computing depositor refunds, each `V3FundsDeposited` event shall be considered expired by verifying that: +For the purpose of computing depositor refunds, each `Deposit` event shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the target block range on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. @@ -236,49 +334,50 @@ Note: - The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the target block range. ### Finding Slow Fill Requests -For the purpose of computing slow fills to be issued to recipients, each `RequestedV3SlowFill` event emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: 1. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, 2. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, -3. The destination SpokePool `FillStatus` mapping for the relevant `V3RelayData` hash is `SlowFillRequested`, -4. The `RequestedV3SlowFill` `V3RelayData` is matched by a corresponding `V3FundsDeposited` event on the origin SpokePool, +3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested`, +4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. Note: -- A slow fill request is made by supplying a complete copy of the relevant `V3RelayData` emitted by a `V3FundsDeposited` event. -- The resulting set of validated `RequestedV3SlowFill` events shall be included as SlowFills in the subsequent root bundle proposal. +- A slow fill request is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. +- The resulting set of validated `Slow Fill Requests` shall be included as SlowFills in the subsequent root bundle proposal. ### Computing LP Fees -Each valid `FilledV3Relay` event is subject to an LP fee. The procedure for computing LP fees is as defined in [UMIP-136 Add IS_RELAY_VALID as a supported price identifier](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-136.md), with the following amendments: +Each valid `Fill` event is subject to an LP fee. The procedure for computing LP fees is as defined in [UMIP-136 Add IS_RELAY_VALID as a supported price identifier](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-136.md), with the following amendments: - The AcrossConfigStore contract shall be used to identify the correct rate model, instead of a `RateModelStore` contract. - The `HubPool` `liquidityUtilizationCurrent()` and `liquidityUtilizationPostRelay()` functions shall be used instead of the `BridgePool` variant. - The event `inputToken` shall be mapped from the SpokePool address to a HubPool `l1Token` address by following the matching procedure outlined above. -- The LP fee is computed between the `originChainId` and `FilledV3Relay.repaymentChainId` where the `relayExecutionInfo.FillType != SlowFill` and `FilledV3Relay.destinationChainId` otherwise. +- The LP fee is computed between the `originChainId` specified by the `Deposit` and `repaymentChainId` specified by the relayer, where the `relayExecutionInfo.FillType != SlowFill` and the Fill `destinationChainId` otherwise. Note: -- The LP fee is typically referenced as a multiplier of the `V3FundsDeposited` `inputAmount`, named `realizedLpFeePct` elsewhere in this document. +- The LP fee is typically referenced as a multiplier of the `Deposit` `inputAmount`, named `realizedLpFeePct` elsewhere in this document. ### Computing Bundle LP Fees The bundle LP fee for a target block range on a SpokePool and token pair shall be determined by summing the applicable LP fees for each of the following validated events: -- `FilledV3Relay` +- `FilledRelay`. +- `FilledV3Relay`. ### Computing Relayer Repayments -For a validated `FilledV3Relay` event, the relayer repayment amount shall be computed as follows: -- `(inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed over the set of HubPool `l1Token`, `originChainId` and `repaymentChainId` at the HubPool block number corresponding to the relevant `V3FundsDeposited` `quoteTimestamp`. +For a validated `Deposit` event, the relayer repayment amount shall be computed as follows: +- `(inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed over the set of HubPool `l1Token`, `originChainId` and `repaymentChainId` at the HubPool block number corresponding to the relevant `Deposit` `quoteTimestamp`. - The applicable rate model shall be sourced from the AcrossConfigStore contract for the relevant `l1Token`. - Deposits where the `originChainId` is a "Lite" chain in the AcrossConfigStore as of the `quoteTimestamp` shall always be repaid on the deposit's origin chain. This means the protocol overrides the relayer's requested `repaymentChainId` with the `originChainId` instead. ### Computing Deposit Refunds -For an expired `V3FundsDeposited` event, the depositor refund amount shall be computed as `inputAmount` units of `inputToken`. +For an expired `Deposit` event, the depositor refund amount shall be computed as `inputAmount` units of `inputToken`. ### Computing Slow Fill updated output amounts For the purpose of computing the amount to issue to a recipient for a SlowFill, the relayer fee shall be nulled by applying the following procedure: - `updatedOutputAmount = (inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed at the deposit `quoteTimestamp` between `originChainId` and `destinationChainId`. Constraint: -- The `V3FundsDeposited` `outputAmount` shall _not_ be considered when determining SlowFill amounts. +- The `Deposit` `outputAmount` shall _not_ be considered when determining SlowFill amounts. Note: -- The `V3FundsDeposited` `outputAmount` specifies the exact amount to be received by the `recipient` for a standard fill, and is therefore exclusive of any relayer or LP fees paid. +- The `Deposit` `outputAmount` specifies the exact amount to be received by the `recipient` for a standard fill, and is therefore exclusive of any relayer or LP fees paid. ### Finding the Opening Running Balance The Opening Running Balance is defined as the cumulative running balance as at the previous successful (undisputed) Root Bundle Proposal. @@ -295,17 +394,17 @@ The procedure for computing running balances for an `l1Token` and `chainId` pair 1. Initialize the running balance to 0. 2. Add relayer refunds: - - For each group of validated `FilledV3Relay` events, initialize a running balance at 0 and add the add the relayer repayment. + - For each group of validated `Fill` events, initialize a running balance at 0 and add the add the relayer repayment. 3. Add deposit refunds: - - For each group of `V3FundsDeposited` events that expired within the target block range, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. + - For each group of `Deposit` events that expired within the target block range, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. 4. Add slow fills: - - For each group of validated `RequestedV3SlowFill` events, add each slow relay's `updatedOutputAmount` to the group's running balance. + - For each group of validated `Slow Fill Requests`, add each slow relay's `updatedOutputAmount` to the group's running balance. 5. Subtract excesses from unexecuted slow fills: - - For each group of validated `FilledV3Relay` events where the `FillType` is `ReplacedSlowFill` and where there is no valid `RequestedV3SlowFill` event with an identical relay data hash in the current bundle data, subtract the SlowFill `updatedOutputAmount` from the running balance in recognition that the SlowFill will never be executed because the fill amount has already been transferred. - - For each expired deposit refund identified above where the `FillStatus` on the deposit destination chain for the deposit's relay data is `RequestedSlowFill` and the matching slow fill request is not in the current bundle range, subtract the associated SlowFill `updatedOutputAmount` from the running balance in recognition that the SlowFill cannot be executed past the `fillDeadline`. + - For each group of validated `Fills` where the `FillType` is `ReplacedSlowFill` and where there is no valid `Slow Fill Request` with an identical relay data hash in the current bundle data, subtract the SlowFill `updatedOutputAmount` from the running balance in recognition that the SlowFill will never be executed because the fill amount has already been transferred. + - For each expired deposit refund identified above where the `FillStatus` on the deposit destination chain is `RequestedSlowFill` and the matching slow fill request is not in the current bundle range, subtract the associated SlowFill `updatedOutputAmount` from the running balance in recognition that the SlowFill cannot be executed past the `fillDeadline`. 6. Add the Opening Running Balance for the selected `l1Token` and `chainId` pair. @@ -331,7 +430,7 @@ The referenced `SpokeTargetBalances` is as specified by [UMIP-157 Token Constant ## Constructing Root Bundles ### Constructing the Pool Rebalance Root -One Pool Rebalance Leaf shall be produced per unique `chainId` & `l1Token` pair, where the corresponding SpokePool emitted `V3FundsDeposited`, `FilledV3Relay` or`RequestedV3SlowFill` events within the target block range. +One Pool Rebalance Leaf shall be produced per unique `chainId` & `l1Token` pair, where the corresponding `Deposit`, `Fill` or`Slow Fill Request` events were emitted by the relevant SpokePool within the target block range. Each Pool Rebalance Leaf shall be constructed as follows: 1. For each unique `chainId` and `l1Token` pair: @@ -361,8 +460,8 @@ Note: ### Constructing the Relayer Refund Root At least one Relayer Refund Leaf shall be produced for each unique combination of SpokePool and `l1Token` for any of the following conditions: -- Valid `FilledV3Relay` events, OR -- Expired `V3Fundsdeposited` events, OR +- Valid `Fill` events, OR +- Expired `Deposit` events, OR - A negative running balance net send amount. Each Relayer Refund Leaf shall be constructed as follows: @@ -395,13 +494,13 @@ Note: - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. ### Constructing the Slow Relay Root -One Slow Relay Leaf shall be produced per valid `RequestedV3SlowFill` event emitted within the target block range for a destination SpokePool. +One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the target block range for a destination SpokePool. -A Slow Relay Leaf shall not be produced if the `RequestedV3SlowFill` event's `inputAmount` is equal to 0 and the `message` is a zero bytes string. +A Slow Relay Leaf shall not be produced if the relevant `Slow Fill Request` `inputAmount` is equal to 0 and the `message` is a zero bytes string. Each Slow Relay Leaf shall be constructed as follows: -1. Set `relayData` to the `V3RelayData` data emitted by the validated `RequestedV3SlowFill` event. -2. Set `chainId` to `destinationChainId` from the corresponding validated `RequestedV3SlowFill` event. +1. Set `relayData` to the `RelayData` emitted by the validated `Slow Fill Request`. +2. Set `chainId` to `destinationChainId` from the corresponding validated `Slow Fill Request`. 3. Set `updatedOutputAmount` to the updated amount computed for the SlowFill. The array of Slow Relay Leaf instances shall be sorted according to; @@ -410,7 +509,7 @@ The array of Slow Relay Leaf instances shall be sorted according to; Note: - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. -- Deposits with disparate output tokens (i.e. where the outputToken is not the equivalent of inputToken on the destination chain) are explicitly not eligible for slow fills. Any instances of `RequestedV3SlowFill` events for non-equivalent tokens shall be ignored. +- Deposits with disparate output tokens (i.e. where the outputToken is not the equivalent of inputToken on the destination chain) are explicitly not eligible for slow fills. Any instances of `Slow Fill Requests` for non-equivalent tokens shall be ignored. # Recommendations - Proposers are responsible for detecting and mitigating incorrect or inconsistent RPC data. Proposers should take steps to validate the correctness of their RPC data before proposing. @@ -422,6 +521,8 @@ Across v3 is supplementary to Across v2, adding extra logic support new types of The V3 rules defined in this UMIP will apply beginning when the VERSION field in the ConfigStore is updated to 3 or higher. The ability for Across bundles to support V2 events may cease in a future VERSION increment. +XXX Identify a transition point for the pending upgrade. This is likely to be handled via a `VERSION` bump. + # Implementation The Across v3 implementation is available in the Across [contracts-v2](https://github.com/across-protocol/contracts-v2) repository. From 43b7aef1b959cf2f460a6980fd81de7b42857d1b Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:56:12 +0100 Subject: [PATCH 02/29] Describe pre-fills --- UMIPs/umip-179.md | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 4e92c86d..58a8c6b7 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -265,22 +265,22 @@ Note: ## Definitions ### Deposits -A Deposit event is defined as an instance of either of the following events: +A `Deposit` is defined as an instance of either of the following events: - `FundsDeposited`. - `V3FundsDeposited`. ### Fills -A Fill event is defined as an instance of either of the following events: +A `Fill` is defined as an instance of either of the following events: - `FilledRelay`. - `FilledV3Relay`. ### Slow Fill Requests -A Slow Fill event is defined as an instance of either of the following events: +A `Slow Fill` is defined as an instance of either of the following events: - `RequestedSlowFill`. - `RequestedV3SlowFill`. ### RelayData -RelayData is defined as an instance of etiher of the following data types: +`RelayData` is defined as an instance of etiher of the following data types: - `V3RelayData`. - `V3RelayDataLegacy`. @@ -316,14 +316,36 @@ The `V3RelayDataLegacy` hash is computed as the `keccak256` hash over the ABI-en - `relayData` is of type `V3RelayDataLegacy` - `destinationChainId` is of type `uint256`. -### Finding Valid Relays -For the purpose of computing relayer repayments, each of the `Fill` events emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +### Computing Relayer Repayments & Depositor Refunds +For the purpose of computing relayer repayments, the following procedures are completed: +- Finding Valid Fills +- Finding Valid Pre-Fills +- Finding Expired Deposits + +#### Note +- Depositor refunds are issued via the Relayer Repayment workflow. + +#### Validating Fills +Each of the `Fills` emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +1. The `Fill` event `FillType` field is not set to `SlowFill`, +2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects. + +If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. + +#### Validating Pre-fills +For each of the `Deposits` emitted within the target block range where no corresponding `Fill` is identified on the destination chain, identify the valid `Fill` according to the following criteria: +1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. +2. Resolve the corresponding `Fill` on the destination chain. + +#### Note +- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the target block range could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. + 1. The `Fill` event `FillType` field is not set to `SlowFill`, -2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be compared by comparing the hashes of the two objects. +2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects. If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. -### Finding Expired Deposits +#### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` event shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the target block range on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. @@ -346,7 +368,7 @@ Note: - The resulting set of validated `Slow Fill Requests` shall be included as SlowFills in the subsequent root bundle proposal. ### Computing LP Fees -Each valid `Fill` event is subject to an LP fee. The procedure for computing LP fees is as defined in [UMIP-136 Add IS_RELAY_VALID as a supported price identifier](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-136.md), with the following amendments: +Each valid `Fill` is subject to an LP fee. The procedure for computing LP fees is as defined in [UMIP-136 Add IS_RELAY_VALID as a supported price identifier](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-136.md), with the following amendments: - The AcrossConfigStore contract shall be used to identify the correct rate model, instead of a `RateModelStore` contract. - The `HubPool` `liquidityUtilizationCurrent()` and `liquidityUtilizationPostRelay()` functions shall be used instead of the `BridgePool` variant. - The event `inputToken` shall be mapped from the SpokePool address to a HubPool `l1Token` address by following the matching procedure outlined above. @@ -394,7 +416,7 @@ The procedure for computing running balances for an `l1Token` and `chainId` pair 1. Initialize the running balance to 0. 2. Add relayer refunds: - - For each group of validated `Fill` events, initialize a running balance at 0 and add the add the relayer repayment. + - For each group of validated `Fill` and `Pre-fill` events, initialize a running balance at 0 and add the add the relayer repayment. 3. Add deposit refunds: - For each group of `Deposit` events that expired within the target block range, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. From 1abce9d7ff3e9044b2062896fd35fa37176dc310 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:59:03 +0100 Subject: [PATCH 03/29] Cleanup --- UMIPs/umip-179.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 58a8c6b7..a9867c83 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -340,11 +340,6 @@ For each of the `Deposits` emitted within the target block range where no corres #### Note - No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the target block range could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. -1. The `Fill` event `FillType` field is not set to `SlowFill`, -2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects. - -If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. - #### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` event shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the target block range on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), From debf09d20b815daaccb01395e08383b1e7168158 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:02:22 +0100 Subject: [PATCH 04/29] Add origin chain deposit constraint --- UMIPs/umip-179.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index a9867c83..963f7d04 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -327,8 +327,9 @@ For the purpose of computing relayer repayments, the following procedures are co #### Validating Fills Each of the `Fills` emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: -1. The `Fill` event `FillType` field is not set to `SlowFill`, -2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects. +1. The `Fill` event `FillType` field is not set to `SlowFill`, AND +2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects, AND +3. The corresponding `Deposit` event occurred within or before the target block range on the origin chain SpokePool. If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. From 294518ddd5c4e55338972a28f1925c8ebba5e422 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:18:03 +0100 Subject: [PATCH 05/29] Describe relayer repaymnet corner cases --- UMIPs/umip-179.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 963f7d04..fbd5f8a2 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -384,6 +384,14 @@ For a validated `Deposit` event, the relayer repayment amount shall be computed - The applicable rate model shall be sourced from the AcrossConfigStore contract for the relevant `l1Token`. - Deposits where the `originChainId` is a "Lite" chain in the AcrossConfigStore as of the `quoteTimestamp` shall always be repaid on the deposit's origin chain. This means the protocol overrides the relayer's requested `repaymentChainId` with the `originChainId` instead. +The recipient of relayer repayments shall be the `Fill` `relayer` address. If the `relayer` address is invalid for the respective `repaymentChainId`, the proposer shall: +- Issue the refund on the `destinationChainId` instead of the `repaymentChainId`, AND +- Issue the refund to the `msg.sender` address, instead of the `relayer` address. + +#### Note +- Examples of an invalid `relayer` address include: + - An SVM address on an EVM chain. + ### Computing Deposit Refunds For an expired `Deposit` event, the depositor refund amount shall be computed as `inputAmount` units of `inputToken`. @@ -546,6 +554,3 @@ The Across v3 implementation is available in the Across [contracts-v2](https://g # Security considerations Across v3 has been audited by OpenZeppelin. - -Note: -- If a particular relayer refund is known to be unexecutable, it can be removed from the bundle by the proposer if a sufficient public justification is made before the proposal. This is intended to deal with unlikely situations, such as ag centralized token issuer blacklisting an address that is due a refund. If this leaf were to remain unaltered, this blacklisted address could block other addresses from recieving refunds. From 2880a4428a2d89a58b6aedf110fdde992d56de66 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:22:14 +0100 Subject: [PATCH 06/29] Minor wording tweak Co-authored-by: nicholaspai <9457025+nicholaspai@users.noreply.github.com> --- UMIPs/umip-179.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index fbd5f8a2..268c6f3a 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -152,7 +152,7 @@ The `V3FundsDeposited` event emits the unique `V3RelayDataLegacy` for an individ Consumers of these events should append the `originChainId` in order to avoid unintentionally mixing events from different chains. Note: -- The `FundsDeposited` and `V3FundsDeposited` `outputToken` field is not required to be a known HubPool `l1Token`. In-protocol arbitrary token swaps are technically supported by Across v3. +- The `FundsDeposited` and `V3FundsDeposited` `outputToken` field is not required to be a known HubPool `l1Token`. In-protocol arbitrary token swaps are supported by Across v3. - The address identified by `exclusiveRelayer` has exclusive right to complete the relay on the destination chain until `exclusivityDeadline` has elapsed. - If `exclusivityDeadline` is set to a past timestamp, any address is eligible to fill the relay. - Any deposit that remains unfilled after the specified `fillDeadline` shall be refunded to the `depositor` address via the origin SpokePool in a subsequent settlement bundle. From 67dba7656d96e8304947aecdd66b8f9bacadb385 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:28:35 +0100 Subject: [PATCH 07/29] Align block range terminology --- UMIPs/umip-179.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 268c6f3a..7d32deee 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -326,33 +326,33 @@ For the purpose of computing relayer repayments, the following procedures are co - Depositor refunds are issued via the Relayer Repayment workflow. #### Validating Fills -Each of the `Fills` emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +Each of the `Fills` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) on a destination SpokePool shall be considered valid by verifying that: 1. The `Fill` event `FillType` field is not set to `SlowFill`, AND 2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects, AND -3. The corresponding `Deposit` event occurred within or before the target block range on the origin chain SpokePool. +3. The corresponding `Deposit` event occurred within or before the [Bundle Block Range](#identifying-bundle-block-ranges) on the origin chain SpokePool. If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. #### Validating Pre-fills -For each of the `Deposits` emitted within the target block range where no corresponding `Fill` is identified on the destination chain, identify the valid `Fill` according to the following criteria: +For each of the `Deposits` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) where no corresponding `Fill` is identified on the destination chain, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. #### Note -- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the target block range could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. +- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the [Bundle Block Range](#identifying-bundle-block-ranges) could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. #### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` event shall be considered expired by verifying that: -1. The `fillDeadline` timestamp elapsed within the target block range on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), +1. The `fillDeadline` timestamp elapsed within the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. Note: - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - Depositor refunds are to be issued as part of the relayer refund procedure. -- The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the target block range. +- The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the [Bundle Block Range](#identifying-bundle-block-ranges). ### Finding Slow Fill Requests -For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the target block range on a destination SpokePool shall be considered valid by verifying that: +For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) on a destination SpokePool shall be considered valid by verifying that: 1. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, 2. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, 3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested`, @@ -374,7 +374,7 @@ Note: - The LP fee is typically referenced as a multiplier of the `Deposit` `inputAmount`, named `realizedLpFeePct` elsewhere in this document. ### Computing Bundle LP Fees -The bundle LP fee for a target block range on a SpokePool and token pair shall be determined by summing the applicable LP fees for each of the following validated events: +The bundle LP fee for a [Bundle Block Range](#identifying-bundle-block-ranges) on a SpokePool and token pair shall be determined by summing the applicable LP fees for each of the following validated events: - `FilledRelay`. - `FilledV3Relay`. @@ -423,7 +423,7 @@ The procedure for computing running balances for an `l1Token` and `chainId` pair - For each group of validated `Fill` and `Pre-fill` events, initialize a running balance at 0 and add the add the relayer repayment. 3. Add deposit refunds: - - For each group of `Deposit` events that expired within the target block range, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. + - For each group of `Deposit` events that expired within the [Bundle Block Range](#identifying-bundle-block-ranges), sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. 4. Add slow fills: - For each group of validated `Slow Fill Requests`, add each slow relay's `updatedOutputAmount` to the group's running balance. @@ -456,7 +456,7 @@ The referenced `SpokeTargetBalances` is as specified by [UMIP-157 Token Constant ## Constructing Root Bundles ### Constructing the Pool Rebalance Root -One Pool Rebalance Leaf shall be produced per unique `chainId` & `l1Token` pair, where the corresponding `Deposit`, `Fill` or`Slow Fill Request` events were emitted by the relevant SpokePool within the target block range. +One Pool Rebalance Leaf shall be produced per unique `chainId` & `l1Token` pair, where the corresponding `Deposit`, `Fill` or`Slow Fill Request` events were emitted by the relevant SpokePool within the [Bundle Block Range](#identifying-bundle-block-ranges). Each Pool Rebalance Leaf shall be constructed as follows: 1. For each unique `chainId` and `l1Token` pair: @@ -520,7 +520,7 @@ Note: - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. ### Constructing the Slow Relay Root -One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the target block range for a destination SpokePool. +One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) for a destination SpokePool. A Slow Relay Leaf shall not be produced if the relevant `Slow Fill Request` `inputAmount` is equal to 0 and the `message` is a zero bytes string. From a95d43744eaff6c39302c4f4c7d674ba63e50443 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:13:56 +0100 Subject: [PATCH 08/29] Clarify repayments on lite chains --- UMIPs/umip-179.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 7d32deee..1fdfcad3 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -382,11 +382,14 @@ The bundle LP fee for a [Bundle Block Range](#identifying-bundle-block-ranges) o For a validated `Deposit` event, the relayer repayment amount shall be computed as follows: - `(inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed over the set of HubPool `l1Token`, `originChainId` and `repaymentChainId` at the HubPool block number corresponding to the relevant `Deposit` `quoteTimestamp`. - The applicable rate model shall be sourced from the AcrossConfigStore contract for the relevant `l1Token`. -- Deposits where the `originChainId` is a "Lite" chain in the AcrossConfigStore as of the `quoteTimestamp` shall always be repaid on the deposit's origin chain. This means the protocol overrides the relayer's requested `repaymentChainId` with the `originChainId` instead. -The recipient of relayer repayments shall be the `Fill` `relayer` address. If the `relayer` address is invalid for the respective `repaymentChainId`, the proposer shall: -- Issue the refund on the `destinationChainId` instead of the `repaymentChainId`, AND -- Issue the refund to the `msg.sender` address, instead of the `relayer` address. +The applied `repaymentChainId` shall be determined as follows: +- When the `originChainId` is a `Lite chain` as at the `Deposit` `quoteTimestamp`: `originChainId`, ELSE: +- The `repaymentChainId` as specified in the `Fill`. + +The applied repayment address shall be determined as follows: +- When the `Fill` `relayer` address is valid for the applied `repaymentChainId`: `relayer`, ELSE +- The `Fill` `msg.sender` address. #### Note - Examples of an invalid `relayer` address include: From fde6509690a9932a746a0b9b943b0f98a7cbb5b6 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:33:18 +0100 Subject: [PATCH 09/29] Add invalid repayment chain clause --- UMIPs/umip-179.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 1fdfcad3..de0799d0 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -384,7 +384,8 @@ For a validated `Deposit` event, the relayer repayment amount shall be computed - The applicable rate model shall be sourced from the AcrossConfigStore contract for the relevant `l1Token`. The applied `repaymentChainId` shall be determined as follows: -- When the `originChainId` is a `Lite chain` as at the `Deposit` `quoteTimestamp`: `originChainId`, ELSE: +- When the `originChainId` is a `Lite chain` as at the `Deposit` `quoteTimestamp`: `originChainId`, ELSE +- When no `PoolRebalanceRoute` exists for the `repaymentToken` on the `Fill` `repaymentChainId`: `destinationChainId`, ELSE - The `repaymentChainId` as specified in the `Fill`. The applied repayment address shall be determined as follows: From e6e4980e69bfc28bca69e90d7a1a1482c382d4d4 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:25:34 +0100 Subject: [PATCH 10/29] Clarify FilledRelay messageHash --- UMIPs/umip-179.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index de0799d0..95a5d825 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -199,7 +199,7 @@ The `FilledRelay` event extends the `V3RelayData` type by applying the following | Name | Type | Description | | :--- | :--- | :---------- | | message | omitted | This field is omitted from the `FilledRelay` event in favour of the `messageHash` field. | -| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field. This field is included in place of the `V3RelayData` message field. See also [Computing RelayData hashes](#computing-relaydata-hashes). | +| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field. This field is included in place of the `V3RelayData` message field. | | relayer | bytes32 | The address completing relay on the destination SpokePool. | | repaymentChainId | uint256 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | | relayExecutionInfo | V3RelayExecutionEventInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | @@ -313,7 +313,7 @@ The `V3RelayData` hash is computed as the `keccak256` hash over the ABI-encoded #### V3RelayDataLegacy The `V3RelayDataLegacy` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: -- `relayData` is of type `V3RelayDataLegacy` +- `relayData` is of type `V3RelayDataLegacy`. - `destinationChainId` is of type `uint256`. ### Computing Relayer Repayments & Depositor Refunds @@ -348,6 +348,7 @@ For the purpose of computing depositor refunds, each `Deposit` event shall be co Note: - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. + - If the `depositor` address is not valid - Depositor refunds are to be issued as part of the relayer refund procedure. - The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the [Bundle Block Range](#identifying-bundle-block-ranges). From cab40f82e28a877634037c473fc9015c60f782bd Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Wed, 22 Jan 2025 15:24:36 +0100 Subject: [PATCH 11/29] Clarify behaviour on invalid depositor / relayer addresses --- UMIPs/umip-179.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 95a5d825..ef4f27a2 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -342,13 +342,13 @@ For each of the `Deposits` emitted within the [Bundle Block Range](#identifying- - No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the [Bundle Block Range](#identifying-bundle-block-ranges) could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. #### Finding Expired Deposits -For the purpose of computing depositor refunds, each `Deposit` event shall be considered expired by verifying that: +For the purpose of computing depositor refunds, each `Deposit` shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. Note: - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - - If the `depositor` address is not valid + - If the `depositor` address is not valid on the `originChainId`, the deposit refund shall be discarded. - Depositor refunds are to be issued as part of the relayer refund procedure. - The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the [Bundle Block Range](#identifying-bundle-block-ranges). @@ -389,10 +389,12 @@ The applied `repaymentChainId` shall be determined as follows: - When no `PoolRebalanceRoute` exists for the `repaymentToken` on the `Fill` `repaymentChainId`: `destinationChainId`, ELSE - The `repaymentChainId` as specified in the `Fill`. -The applied repayment address shall be determined as follows: +The applied `repayment address` shall be determined as follows: - When the `Fill` `relayer` address is valid for the applied `repaymentChainId`: `relayer`, ELSE - The `Fill` `msg.sender` address. +If the applied `repayment address` is not valid for the applied `repaymentChainId`, the repayment shall be discarded. + #### Note - Examples of an invalid `relayer` address include: - An SVM address on an EVM chain. From e4036da210c44b7550e85302a21110263baf4bca Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:49:24 +0100 Subject: [PATCH 12/29] Apply suggestions from code review Co-authored-by: Matt Rice Co-authored-by: nicholaspai <9457025+nicholaspai@users.noreply.github.com> --- UMIPs/umip-179.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index ef4f27a2..3e794093 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -59,7 +59,7 @@ The `V3RelayData` type underpins the transfer of funds in or out of a SpokePool | message | bytes | Optional data that is forwarded to the recipient as part of a relay. | #### Note -- `V3RelayData` specifies `bytes32` representation for addresses (`depositor`, `recipient`, ...) in order to interface with non-EVM chains. EVM addressed supplied shall be promoted to type `bytes32` with the upper bytes zeroed. +- `V3RelayData` specifies `bytes32` representation for addresses (`depositor`, `recipient`, ...) in order to interface with non-EVM chains. EVM addressed supplied shall be promoted to type `bytes32` with the upper 12 bytes zeroed. ### V3RelayDataLegacy The `V3RelayDataLegacy` type is supported for backwards compatibility, but is slated for deprecation. `V3RelayDataLegacy` has the following delta to the `V3RelayData` type: @@ -334,9 +334,10 @@ Each of the `Fills` emitted within the [Bundle Block Range](#identifying-bundle- If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. #### Validating Pre-fills -For each of the `Deposits` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) where no corresponding `Fill` is identified on the destination chain, identify the valid `Fill` according to the following criteria: +For each of the `Deposits` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. +3. Verify that the `Fill` occurred prior to the current the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination chain SpokePool. #### Note - No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the [Bundle Block Range](#identifying-bundle-block-ranges) could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. @@ -357,7 +358,7 @@ For the purpose of computing slow fills to be issued to recipients, each `Slow F 1. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, 2. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, 3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested`, -4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event on the origin SpokePool, +4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the [Bundle Block Range](#identifying-bundle-block-ranges) on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. Note: From 9758785973fb737e6546d5adb6bac956fdbb551b Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:48:11 +0100 Subject: [PATCH 13/29] Describe updated RelayData --- UMIPs/umip-179.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 3e794093..91c0316b 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -306,15 +306,12 @@ In addition to the description [UMIP-157](https://github.com/UMAprotocol/UMIPs/b DISABLED_CHAINS by proposing from and to the previous bundle end block. ### Computing RelayData Hashes -#### V3RelayData -The `V3RelayData` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: -- `relayData` is of type `V3RelayData`. +A `RelayData` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: +- `relayData` is of type `V3RelayData` or `V3RelayDataLegacy`. - `destinationChainId` is of type `uint256`. -#### V3RelayDataLegacy -The `V3RelayDataLegacy` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: -- `relayData` is of type `V3RelayDataLegacy`. -- `destinationChainId` is of type `uint256`. +#### Note +- This method produces the identical hashes for `V3RelayData` and `V3RelayDataLegacy` for the same input data due to `address` promotion to `bytes32` prior to hashing. ### Computing Relayer Repayments & Depositor Refunds For the purpose of computing relayer repayments, the following procedures are completed: From f74a4ab60c8d6099cf09861fe8fa6981ea055cd7 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 24 Jan 2025 14:27:13 +0100 Subject: [PATCH 14/29] Add migration information --- UMIPs/umip-179.md | 51 +++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 91c0316b..872b9f2f 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -139,7 +139,7 @@ Across V3 defines the following events: - ClaimedRelayerRefund ### Event Deprecation -The following events are marked for future deprecation. Deprecation will be announced in a future update to this specification. +The following events are marked for deprecation. See [Migration](#migration) for more information. - V3FundsDeposited - RequestedSpeedUpV3Deposit - FilledV3Relay @@ -149,9 +149,8 @@ The following events are marked for future deprecation. Deprecation will be anno The `FundsDeposited` event emits the unique `V3RelayData` for an individual deposit. No additional fields are defined. The `V3FundsDeposited` event emits the unique `V3RelayDataLegacy` for an individual deposit. No additional fields are defined. -Consumers of these events should append the `originChainId` in order to avoid unintentionally mixing events from different chains. - -Note: +#### Note +- Consumers of these events should append the `originChainId` in order to avoid unintentionally mixing events from different chains. - The `FundsDeposited` and `V3FundsDeposited` `outputToken` field is not required to be a known HubPool `l1Token`. In-protocol arbitrary token swaps are supported by Across v3. - The address identified by `exclusiveRelayer` has exclusive right to complete the relay on the destination chain until `exclusivityDeadline` has elapsed. - If `exclusivityDeadline` is set to a past timestamp, any address is eligible to fill the relay. @@ -180,16 +179,15 @@ The `RequestedSpeedUpV3Deposit` event emits the following data: | updatedMessage | bytes | The new message to be supplied to the recipient. | | depositorSignature | bytes | A signature by the depositor authorizing the above updated fields. | -Note: +#### Note - Relayers may optionally append the updated request from a `RequestedSpeedUpDeposit` or `RequestedSpeedUpV3Deposit` event when filling a relay, but have no obligation to use the updated request. ### RequestedSlowFill, RequestedV3SlowFill The `RequestedSlowFill` event emits an `V3RelayData` instance. The `RequestedV3SlowFill` event emits an `V3RelayDataLegacy` instance. -These events are emitted on the destination chain and signal to proposers that a slow fill has been requested for a specific deposit. - -Note: +#### Note +- These events are emitted on the destination chain and signal to proposers that a slow fill has been requested for a specific deposit. - `RequestedV3SlowFill` events cannot be emitted until the `exclusivityDeadline` timestamp has elapsed on the destination chain. - `RequestedV3SlowFill` events cannot be emitted once the `fillDeadline` timestamp has elapsed on the destination chain. @@ -211,7 +209,7 @@ The `FilledV3Relay` event extends the `V3RelayDataLegacy` type by adding the fol | repaymentChainId | uint256 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | | relayExecutionInfo | V3RelayExecutionEventInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | -Note: +#### Note - Consumers of these events should append the `destinationChainId` attribute in order to avoid unintentioanlly mixing events from different chains. # Root Bundle Proposals @@ -239,7 +237,7 @@ A `PoolRebalanceLeaf` shall consist of the following: | leafId | uint8 | Index of the `PoolRebalanceLeaf` within the ordered array of `PoolRebalanceLeaves`. | | l1Tokens | address[] | Ordered array of HubPool `l1Token` addresses. -Note: +#### Note - The format of Pool Rebalance leaves is unchanged from Across v2. ### Relayer Refund Leaves @@ -252,14 +250,14 @@ Note: | refundAddresses | uint256[] | Ordered array of addresses to be refunded by this `RelayerRefundLeaf`. | | refundAmounts | uint256[] | Ordered array of amounts of `l2TokenAddress`to be refunded to the corresponding `refundAddress`. | -Note: +#### Note - The format of Relayer Refund leaves is unchanged from Across v2. - Across v3 expands the utility of the `RelayerRefundLeaf` to include issuing depositor refunds on origin chains in the event of an expired `V3FundsDeposited` `fillDeadline`. ### Slow Relay Leaves Across v3 `SlowRelayLeaf` objects are defined by the `V3SlowFill` [data type](#data-types). -Note: +#### Note - The format of Slow Relay leaves is updated from Across v2. ## Definitions @@ -344,7 +342,7 @@ For the purpose of computing depositor refunds, each `Deposit` shall be consider 1. The `fillDeadline` timestamp elapsed within the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. -Note: +##### Note - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - If the `depositor` address is not valid on the `originChainId`, the deposit refund shall be discarded. - Depositor refunds are to be issued as part of the relayer refund procedure. @@ -358,7 +356,7 @@ For the purpose of computing slow fills to be issued to recipients, each `Slow F 4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the [Bundle Block Range](#identifying-bundle-block-ranges) on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. -Note: +#### Note - A slow fill request is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. - The resulting set of validated `Slow Fill Requests` shall be included as SlowFills in the subsequent root bundle proposal. @@ -369,7 +367,7 @@ Each valid `Fill` is subject to an LP fee. The procedure for computing LP fees i - The event `inputToken` shall be mapped from the SpokePool address to a HubPool `l1Token` address by following the matching procedure outlined above. - The LP fee is computed between the `originChainId` specified by the `Deposit` and `repaymentChainId` specified by the relayer, where the `relayExecutionInfo.FillType != SlowFill` and the Fill `destinationChainId` otherwise. -Note: +#### Note - The LP fee is typically referenced as a multiplier of the `Deposit` `inputAmount`, named `realizedLpFeePct` elsewhere in this document. ### Computing Bundle LP Fees @@ -404,10 +402,10 @@ For an expired `Deposit` event, the depositor refund amount shall be computed as For the purpose of computing the amount to issue to a recipient for a SlowFill, the relayer fee shall be nulled by applying the following procedure: - `updatedOutputAmount = (inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed at the deposit `quoteTimestamp` between `originChainId` and `destinationChainId`. -Constraint: +#### Constraint - The `Deposit` `outputAmount` shall _not_ be considered when determining SlowFill amounts. -Note: +#### Note - The `Deposit` `outputAmount` specifies the exact amount to be received by the `recipient` for a standard fill, and is therefore exclusive of any relayer or LP fees paid. ### Finding the Opening Running Balance @@ -455,7 +453,7 @@ else if abs(running_balance) >= spoke_balance_threshold: running_balance = running_balance - net_send_amount ``` -Note: +#### Note The referenced `SpokeTargetBalances` is as specified by [UMIP-157 Token Constants](https://github.com/UMAprotocol/UMIPs/blob/pxrl/umip179/UMIPs/umip-157.md#token-constants): ## Constructing Root Bundles @@ -486,7 +484,7 @@ The hash for each Pool Rebalance Leaf shall be constructed by using Solidity's s The Pool Rebalance Merkle Tree shall be constructed such that it is verifyable using [OpenZeppelin's MerkleProof](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/742e85be7c08dff21410ba4aa9c60f6a033befb8/contracts/utils/cryptography/MerkleProof.sol) library. -Note: +#### Note - See examples [here](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/742e85be7c08dff21410ba4aa9c60f6a033befb8/test/utils/cryptography/MerkleProof.test.js) for how to construct these types of trees. ### Constructing the Relayer Refund Root @@ -521,7 +519,7 @@ The set of relayer refund leaves shall be ordered according to: The Relayer Refund Leaf `leafId` field shall be numbered according to the ordering established above, starting at 0. -Note: +#### Note - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. ### Constructing the Slow Relay Root @@ -538,7 +536,7 @@ The array of Slow Relay Leaf instances shall be sorted according to; 1. `originChainId`, then 2. `depositId`. -Note: +#### Note - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. - Deposits with disparate output tokens (i.e. where the outputToken is not the equivalent of inputToken on the destination chain) are explicitly not eligible for slow fills. Any instances of `Slow Fill Requests` for non-equivalent tokens shall be ignored. @@ -547,15 +545,12 @@ Note: - Proposers should avoid relying on the deposit `outputAmount`, even for deposits where the `outputToken` is a known HubPool token. When computing fees, ensure that the `realizedLpFee` is _always_ subtracted from the `inputAmount`, rather than trying to infer them based on the spread between `inputAmount` and `outputAmount`. - Relayers are advised to factor in origin chain finality guarantees when making fills on destination chains. Origin chain re-organisation can lead to deposit re-ordering and can thus invalidate fills. -# Across v2 -> V3 Transition -Across v3 is supplementary to Across v2, adding extra logic support new types of deposits, fills and slow fill requests. At the point of upgrading to Across v3, it will no longer be possible for Across v2 `FundsDeposited` events to be emitted. In order to support continuity of service and to minimise disruption for third-party integrators, it will be possible for pre-existing `FundsDeposited` events to be filled via `FilledRelay` events. During this period, RootBundleProposals will contain relayer repayment and slow fill leaves for both Across v2 and v3. - -The V3 rules defined in this UMIP will apply beginning when the VERSION field in the ConfigStore is updated to 3 or higher. The ability for Across bundles to support V2 events may cease in a future VERSION increment. - -XXX Identify a transition point for the pending upgrade. This is likely to be handled via a `VERSION` bump. +# Migration +- Support for Across events with `bytes32` types (`FundsDeposited`, `FilledRelay`, ...) is required as at ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 4. +- The `Legacy` events defined in this UMIP are marked as deprecated 7 days after the ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) migration from 3 to 4. # Implementation -The Across v3 implementation is available in the Across [contracts-v2](https://github.com/across-protocol/contracts-v2) repository. +The Across v3 implementation is available in the Across [contracts-v2](https://github.com/across-protocol/contracts) repository. # Security considerations Across v3 has been audited by OpenZeppelin. From 065dc86b7a0b649b7cccfd53c17d269bc968cafb Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 28 Jan 2025 11:59:49 +0100 Subject: [PATCH 15/29] Initial wording for early slow fill requests Identified by @nicholaspai --- UMIPs/umip-179.md | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 872b9f2f..aeefe00c 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -282,6 +282,9 @@ A `Slow Fill` is defined as an instance of either of the following events: - `V3RelayData`. - `V3RelayDataLegacy`. +### Bundle Block Range +The `Bundle Block Range` is the pair of start and end blocks for a given proposal. See [Identifying Bundle Block Ranges](#identifying-bundle-block-ranges) for guidance on identifying the `Bundle Block Range`. + ## Method ### Identifying SpokePool Contracts The current SpokePool address for a specific chain is available by querying `HubPool.crossChainContracts()`. The chainId must be specified in the query. In case of SpokePool migations, historical SpokePool addresses can be identified by scraping HubPool `CrossChainContractsSet` events. @@ -321,44 +324,54 @@ For the purpose of computing relayer repayments, the following procedures are co - Depositor refunds are issued via the Relayer Repayment workflow. #### Validating Fills -Each of the `Fills` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) on a destination SpokePool shall be considered valid by verifying that: +Each of the `Fills` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `Fill` event `FillType` field is not set to `SlowFill`, AND 2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects, AND -3. The corresponding `Deposit` event occurred within or before the [Bundle Block Range](#identifying-bundle-block-ranges) on the origin chain SpokePool. +3. The corresponding `Deposit` event occurred within or before the `Bundle Block Range` on the origin chain SpokePool. If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. #### Validating Pre-fills -For each of the `Deposits` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: +For each of the `Deposits` emitted within the `Bundle Block Range` where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. -3. Verify that the `Fill` occurred prior to the current the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination chain SpokePool. +3. Verify that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool. #### Note -- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the [Bundle Block Range](#identifying-bundle-block-ranges) could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. +- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. #### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` shall be considered expired by verifying that: -1. The `fillDeadline` timestamp elapsed within the [Bundle Block Range](#identifying-bundle-block-ranges) on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), +1. The `fillDeadline` timestamp elapsed within the `Bundle Block Range` on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. ##### Note - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - If the `depositor` address is not valid on the `originChainId`, the deposit refund shall be discarded. - Depositor refunds are to be issued as part of the relayer refund procedure. -- The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the [Bundle Block Range](#identifying-bundle-block-ranges). +- The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the `Bundle Block Range`. ### Finding Slow Fill Requests -For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) on a destination SpokePool shall be considered valid by verifying that: -1. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, -2. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, +For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: +1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, +2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, 3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested`, -4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the [Bundle Block Range](#identifying-bundle-block-ranges) on the origin SpokePool, +4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the `Bundle Block Range` on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. #### Note -- A slow fill request is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. +- A `slow Fill Request` is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. - The resulting set of validated `Slow Fill Requests` shall be included as SlowFills in the subsequent root bundle proposal. +- A `Slow Fill Request` may correspond to a `Deposit` from previous bundles. + +### Finding Early Slow Fill Requests +When an early `Slow Fill Request` is implied, the `Slow Fill Request` shall be validated as follows: +1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, +2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, +3. The `originChainId` and `destinationChainId` are not Lite chains. + +#### Note +- An early `Slow Fill Request` is implied where a `Deposit` emitted within the current `Bundle Block Range` has a `FillStatus` of `SlowFillRequested` as at the end of the current `Bundle Block Range` on the destination chain, but where no `Slow Fill Request` is identified within the current `Bundle Block Range`. This may occur where the `Slow Fill Request` was submitted prior to the current bundle. ### Computing LP Fees Each valid `Fill` is subject to an LP fee. The procedure for computing LP fees is as defined in [UMIP-136 Add IS_RELAY_VALID as a supported price identifier](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-136.md), with the following amendments: @@ -371,7 +384,7 @@ Each valid `Fill` is subject to an LP fee. The procedure for computing LP fees i - The LP fee is typically referenced as a multiplier of the `Deposit` `inputAmount`, named `realizedLpFeePct` elsewhere in this document. ### Computing Bundle LP Fees -The bundle LP fee for a [Bundle Block Range](#identifying-bundle-block-ranges) on a SpokePool and token pair shall be determined by summing the applicable LP fees for each of the following validated events: +The bundle LP fee for a `Bundle Block Range` on a SpokePool and token pair shall be determined by summing the applicable LP fees for each of the following validated events: - `FilledRelay`. - `FilledV3Relay`. @@ -426,7 +439,7 @@ The procedure for computing running balances for an `l1Token` and `chainId` pair - For each group of validated `Fill` and `Pre-fill` events, initialize a running balance at 0 and add the add the relayer repayment. 3. Add deposit refunds: - - For each group of `Deposit` events that expired within the [Bundle Block Range](#identifying-bundle-block-ranges), sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. + - For each group of `Deposit` events that expired within the `Bundle Block Range`, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. 4. Add slow fills: - For each group of validated `Slow Fill Requests`, add each slow relay's `updatedOutputAmount` to the group's running balance. @@ -523,7 +536,7 @@ The Relayer Refund Leaf `leafId` field shall be numbered according to the orderi - Once these leaves are constructed, they can be used to form a merkle root as described in the previous section. ### Constructing the Slow Relay Root -One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the [Bundle Block Range](#identifying-bundle-block-ranges) for a destination SpokePool. +One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the `Bundle Block Range` for a destination SpokePool. A Slow Relay Leaf shall not be produced if the relevant `Slow Fill Request` `inputAmount` is equal to 0 and the `message` is a zero bytes string. From c4005eec6ed63f6ccce484d1c31ac28cb7f4c0b2 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:31:39 +0100 Subject: [PATCH 16/29] Update RelayData comparisons --- UMIPs/umip-179.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index aeefe00c..db0c51de 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -197,7 +197,7 @@ The `FilledRelay` event extends the `V3RelayData` type by applying the following | Name | Type | Description | | :--- | :--- | :---------- | | message | omitted | This field is omitted from the `FilledRelay` event in favour of the `messageHash` field. | -| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field. This field is included in place of the `V3RelayData` message field. | +| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field where the message is non-empty, or `bytes32(0)` for an empty message. This field is included in place of the `V3RelayData` message field. | | relayer | bytes32 | The address completing relay on the destination SpokePool. | | repaymentChainId | uint256 | The depositId of the corresponding `V3FundsDeposited` event to be updated. | | relayExecutionInfo | V3RelayExecutionEventInfo | The effective `recipient`, `message` and `outputAmount`, as well as the `FillType` performed (FastFill, ReplacedSlowFill, SlowFill). | @@ -306,11 +306,18 @@ In addition to the description [UMIP-157](https://github.com/UMAprotocol/UMIPs/b - A "soft pause" of a chain is permitted in the event that the proposer cannot safely increment the bundle block range, or has no events to propose beyond the previous bundle block range. In this case, the proposer may repeat the procedure for DISABLED_CHAINS by proposing from and to the previous bundle end block. +### Reconstructing FilledRelay messages +The `FilledRelay` event emits the `messsageHash` field. This field is set as follows: +- When the `RelayData` `message` field is empty (`0x`): `bytes32(0)`, OR +- When the `RelayData` `message` field is non-empty (`0x...`): `keccak256(message)`. + ### Computing RelayData Hashes A `RelayData` hash is computed as the `keccak256` hash over the ABI-encoded representation of the arguments `relayData`, `destinationChainId`, where: - `relayData` is of type `V3RelayData` or `V3RelayDataLegacy`. - `destinationChainId` is of type `uint256`. +- When the `FilledRelay` event data omits the `message` field, the `message` field shall be populated according to the procedure specified in [Reconstructing FilledRelay messages](#resonstructing-filledrelay-messages). + #### Note - This method produces the identical hashes for `V3RelayData` and `V3RelayDataLegacy` for the same input data due to `address` promotion to `bytes32` prior to hashing. @@ -323,15 +330,18 @@ For the purpose of computing relayer repayments, the following procedures are co #### Note - Depositor refunds are issued via the Relayer Repayment workflow. -#### Validating Fills +### Validating Fills Each of the `Fills` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `Fill` event `FillType` field is not set to `SlowFill`, AND -2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`. This may be determined by comparing the hashes of the two objects, AND +2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`, AND 3. The corresponding `Deposit` event occurred within or before the `Bundle Block Range` on the origin chain SpokePool. -If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. +#### Note +- If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. +- `RelayData` equality can be determined by comparing the keccak256 hashes of two `RelayData` objects. +- Fills of type `SlowFill` are valid, but are not relevant for computing relayer repayments. -#### Validating Pre-fills +### Validating Pre-fills For each of the `Deposits` emitted within the `Bundle Block Range` where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. @@ -340,12 +350,12 @@ For each of the `Deposits` emitted within the `Bundle Block Range` where no corr #### Note - No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. -#### Finding Expired Deposits +### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the `Bundle Block Range` on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), 2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. -##### Note +#### Note - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - If the `depositor` address is not valid on the `originChainId`, the deposit refund shall be discarded. - Depositor refunds are to be issued as part of the relayer refund procedure. From 3a7815d8922ac5c57709147fe3ca63dd41775acc Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:23:50 +0100 Subject: [PATCH 17/29] Apply suggestions from code review Co-authored-by: Matt Rice --- UMIPs/umip-179.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index db0c51de..fcaabe4e 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -59,7 +59,7 @@ The `V3RelayData` type underpins the transfer of funds in or out of a SpokePool | message | bytes | Optional data that is forwarded to the recipient as part of a relay. | #### Note -- `V3RelayData` specifies `bytes32` representation for addresses (`depositor`, `recipient`, ...) in order to interface with non-EVM chains. EVM addressed supplied shall be promoted to type `bytes32` with the upper 12 bytes zeroed. +- `V3RelayData` specifies `bytes32` representation for addresses (`depositor`, `recipient`, ...) in order to interface with non-EVM chains. The EVM address supplied shall be promoted to type `bytes32` with the upper 12 bytes zeroed. ### V3RelayDataLegacy The `V3RelayDataLegacy` type is supported for backwards compatibility, but is slated for deprecation. `V3RelayDataLegacy` has the following delta to the `V3RelayData` type: @@ -348,16 +348,15 @@ For each of the `Deposits` emitted within the `Bundle Block Range` where no corr 3. Verify that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool. #### Note -- No specific method is prescribed for resolving the fill on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. +- No specific method is prescribed for resolving the `Fill` on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. ### Finding Expired Deposits For the purpose of computing depositor refunds, each `Deposit` shall be considered expired by verifying that: 1. The `fillDeadline` timestamp elapsed within the `Bundle Block Range` on the destination SpokePool (i.e. the `fillDeadline` expired between the `block.timestamp` of the destination chain's bundle start and end block), -2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested`. +2. The `FillStatus` on the destination SpokePool is set to `Unfilled` or `SlowFillRequested` as at the end of the `Bundle Block Range`. #### Note - Expired deposits shall be refunded to the `depositor` address on the origin SpokePool. - - If the `depositor` address is not valid on the `originChainId`, the deposit refund shall be discarded. - Depositor refunds are to be issued as part of the relayer refund procedure. - The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the `Bundle Block Range`. @@ -378,7 +377,7 @@ For the purpose of computing slow fills to be issued to recipients, each `Slow F When an early `Slow Fill Request` is implied, the `Slow Fill Request` shall be validated as follows: 1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, 2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, -3. The `originChainId` and `destinationChainId` are not Lite chains. +3. Neither the`originChainId` nor the `destinationChainId` is a `Lite` chain. #### Note - An early `Slow Fill Request` is implied where a `Deposit` emitted within the current `Bundle Block Range` has a `FillStatus` of `SlowFillRequested` as at the end of the current `Bundle Block Range` on the destination chain, but where no `Slow Fill Request` is identified within the current `Bundle Block Range`. This may occur where the `Slow Fill Request` was submitted prior to the current bundle. From 7ddf4719192352f73c9e6602e33ed357dbf6c04b Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:24:43 +0100 Subject: [PATCH 18/29] Apply suggestions from code review --- UMIPs/umip-179.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index fcaabe4e..0d7b892a 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -364,7 +364,7 @@ For the purpose of computing depositor refunds, each `Deposit` shall be consider For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, 2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, -3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested`, +3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` as at the end of the `Bundle Block Range`, 4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the `Bundle Block Range` on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. From 1fe92dc0fb9fdbd84ee0f33285b96d8666077e00 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Thu, 30 Jan 2025 09:34:31 +0100 Subject: [PATCH 19/29] Update UMIPs/umip-179.md --- UMIPs/umip-179.md | 1 - 1 file changed, 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 0d7b892a..a6d35b4c 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -188,7 +188,6 @@ The `RequestedV3SlowFill` event emits an `V3RelayDataLegacy` instance. #### Note - These events are emitted on the destination chain and signal to proposers that a slow fill has been requested for a specific deposit. -- `RequestedV3SlowFill` events cannot be emitted until the `exclusivityDeadline` timestamp has elapsed on the destination chain. - `RequestedV3SlowFill` events cannot be emitted once the `fillDeadline` timestamp has elapsed on the destination chain. ### FilledRelay, FilledV3Relay From 4c99a3ee7ea18d08299c9b22a9299e53ad5604e7 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:35:34 +0100 Subject: [PATCH 20/29] Updates --- UMIPs/umip-179.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index a6d35b4c..07cc9112 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -284,6 +284,9 @@ A `Slow Fill` is defined as an instance of either of the following events: ### Bundle Block Range The `Bundle Block Range` is the pair of start and end blocks for a given proposal. See [Identifying Bundle Block Ranges](#identifying-bundle-block-ranges) for guidance on identifying the `Bundle Block Range`. +### Fill Statuses +A `Deposit` is considered to be `Filled` on the destination chain when the destination `SpokePool` `FillStatus` mapping shows state `Filled` for the `Deposit` `RelayData` hash. + ## Method ### Identifying SpokePool Contracts The current SpokePool address for a specific chain is available by querying `HubPool.crossChainContracts()`. The chainId must be specified in the query. In case of SpokePool migations, historical SpokePool addresses can be identified by scraping HubPool `CrossChainContractsSet` events. @@ -336,7 +339,7 @@ Each of the `Fills` emitted within the `Bundle Block Range` on a destination Spo 3. The corresponding `Deposit` event occurred within or before the `Bundle Block Range` on the origin chain SpokePool. #### Note -- If the `Deposit` event specifies `outputToken` 0x0 (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of 0x0. +- If the `Deposit` event specifies `outputToken` `bytes32(0)` (i.e. the Zero Address), the equivalent SpokePool token on the destination chain shall be substituted in. For the purpose of determining `RelayData` equivalency, the updated/substituted `outputToken` shall be used in place of the Zero Address. - `RelayData` equality can be determined by comparing the keccak256 hashes of two `RelayData` objects. - Fills of type `SlowFill` are valid, but are not relevant for computing relayer repayments. @@ -567,8 +570,8 @@ The array of Slow Relay Leaf instances shall be sorted according to; - Relayers are advised to factor in origin chain finality guarantees when making fills on destination chains. Origin chain re-organisation can lead to deposit re-ordering and can thus invalidate fills. # Migration -- Support for Across events with `bytes32` types (`FundsDeposited`, `FilledRelay`, ...) is required as at ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 4. -- The `Legacy` events defined in this UMIP are marked as deprecated 7 days after the ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) migration from 3 to 4. +- Support for Across events with `bytes32` types (`FundsDeposited`, `FilledRelay`, ...) is required as at ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 5. +- The `Legacy` events defined in this UMIP are marked as deprecated 7 days after the ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) migration from 4 to 5. # Implementation The Across v3 implementation is available in the Across [contracts-v2](https://github.com/across-protocol/contracts) repository. From 7edfba7fe819c6e94598902bf7cc551c4f233250 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:42:03 +0100 Subject: [PATCH 21/29] Fix RequestedSlowFill event --- UMIPs/umip-179.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 07cc9112..221c4c99 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -183,12 +183,17 @@ The `RequestedSpeedUpV3Deposit` event emits the following data: - Relayers may optionally append the updated request from a `RequestedSpeedUpDeposit` or `RequestedSpeedUpV3Deposit` event when filling a relay, but have no obligation to use the updated request. ### RequestedSlowFill, RequestedV3SlowFill -The `RequestedSlowFill` event emits an `V3RelayData` instance. +The `RequestedSlowFill` event extends the `V3RelayData` type by applying the following adjustments: + +| Name | Type | Description | +| :--- | :--- | :---------- | +| message | omitted | This field is omitted in favour of the `messageHash` field. | +| messageHash | bytes32 | The keccak256 hash of the `V3RelayData` message field where the message is non-empty, or `bytes32(0)` for an empty message. This field is included in place of the `V3RelayData` message field. | + The `RequestedV3SlowFill` event emits an `V3RelayDataLegacy` instance. #### Note - These events are emitted on the destination chain and signal to proposers that a slow fill has been requested for a specific deposit. -- `RequestedV3SlowFill` events cannot be emitted once the `fillDeadline` timestamp has elapsed on the destination chain. ### FilledRelay, FilledV3Relay From d6eb6046300bab92a0e86d800aadd1ef81b7aeea Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:51:46 +0100 Subject: [PATCH 22/29] Describe slow pre-fills --- UMIPs/umip-179.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 221c4c99..b0fbc311 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -289,7 +289,7 @@ A `Slow Fill` is defined as an instance of either of the following events: ### Bundle Block Range The `Bundle Block Range` is the pair of start and end blocks for a given proposal. See [Identifying Bundle Block Ranges](#identifying-bundle-block-ranges) for guidance on identifying the `Bundle Block Range`. -### Fill Statuses +### Fill Status A `Deposit` is considered to be `Filled` on the destination chain when the destination `SpokePool` `FillStatus` mapping shows state `Filled` for the `Deposit` `RelayData` hash. ## Method @@ -352,7 +352,9 @@ Each of the `Fills` emitted within the `Bundle Block Range` on a destination Spo For each of the `Deposits` emitted within the `Bundle Block Range` where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. -3. Verify that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool. +3. Verify that the `FillType` is `FastFill` or `ReplacedSlowFill` AND that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool, OR + +When the `FillType` is `SlowFill`, the `Deposit` shall be refunded to the `depositor` address on the origin chain. #### Note - No specific method is prescribed for resolving the `Fill` on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. @@ -529,8 +531,9 @@ Each Relayer Refund Leaf shall be constructed as follows: - If no relays are present, then the relevant token mapping from the previous successful proposal shall be used. - Each element of the `refundAddresses` and `refundAmounts` arrays shall be produced according to the defined procedure for computing relayer repayments. - One entry shall exist per unique address, containing the sum of any outstanding: - - Relayer repayments, and/or - - Expired deposits. + - Relayer repayments, and + - Expired deposits, and + - Pre-filled deposits where the `FillType` is `SlowFill`. - The `refundAddresses` and `refundAmounts` arrays shall be ordered according to the following criteria: 1. `refundAmount` descending order, then 2. `relayerAddress` ascending order (in case of duplicate `refundAmount` values). From 3405adc3663819beb02f7b6e9ff3752adc44b08e Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:54:54 +0100 Subject: [PATCH 23/29] Tweak --- UMIPs/umip-179.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index b0fbc311..5ebd7aae 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -352,11 +352,10 @@ Each of the `Fills` emitted within the `Bundle Block Range` on a destination Spo For each of the `Deposits` emitted within the `Bundle Block Range` where no corresponding `Fill` is identified on the destination chain within the `Bundle Block Range`, identify the valid `Fill` according to the following criteria: 1. Verify that the destination chain `FillStatus` for the `Deposit` `RelayData` is `Filled` as at the destination chain end block number for the proposal. 2. Resolve the corresponding `Fill` on the destination chain. -3. Verify that the `FillType` is `FastFill` or `ReplacedSlowFill` AND that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool, OR - -When the `FillType` is `SlowFill`, the `Deposit` shall be refunded to the `depositor` address on the origin chain. +3. Verify that the `FillType` is `FastFill` or `ReplacedSlowFill` AND that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool. #### Note +- When the `FillType` is `SlowFill`, the `Deposit` shall be refunded to the `depositor` address on the origin chain. - No specific method is prescribed for resolving the `Fill` on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. ### Finding Expired Deposits From 79112263700f570bfefc7656c42490b964b863d6 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Fri, 31 Jan 2025 21:57:56 +0100 Subject: [PATCH 24/29] Typos --- UMIPs/umip-179.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 5ebd7aae..c6124d40 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -330,8 +330,8 @@ A `RelayData` hash is computed as the `keccak256` hash over the ABI-encoded repr ### Computing Relayer Repayments & Depositor Refunds For the purpose of computing relayer repayments, the following procedures are completed: -- Finding Valid Fills -- Finding Valid Pre-Fills +- Validating Fills +- Validating Pre-Fills - Finding Expired Deposits #### Note @@ -377,7 +377,7 @@ For the purpose of computing slow fills to be issued to recipients, each `Slow F 5. The `originChainId` and `destinationChainId` are not Lite chains. #### Note -- A `slow Fill Request` is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. +- A `Slow Fill Request` is made by supplying a complete copy of the relevant `RelayData` emitted by a `Deposit` event. - The resulting set of validated `Slow Fill Requests` shall be included as SlowFills in the subsequent root bundle proposal. - A `Slow Fill Request` may correspond to a `Deposit` from previous bundles. From afc8eb9b043c23b271140278bb3252542b5f8ea9 Mon Sep 17 00:00:00 2001 From: Paul <108695806+pxrl@users.noreply.github.com> Date: Sat, 1 Feb 2025 00:28:46 +0100 Subject: [PATCH 25/29] Update for duplicates & refunds --- UMIPs/umip-179.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index c6124d40..382b0b5e 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -333,6 +333,7 @@ For the purpose of computing relayer repayments, the following procedures are co - Validating Fills - Validating Pre-Fills - Finding Expired Deposits +- Finding Unfillable Deposits #### Note - Depositor refunds are issued via the Relayer Repayment workflow. @@ -355,7 +356,6 @@ For each of the `Deposits` emitted within the `Bundle Block Range` where no corr 3. Verify that the `FillType` is `FastFill` or `ReplacedSlowFill` AND that the `Fill` occurred prior to the current the `Bundle Block Range` on the destination chain SpokePool. #### Note -- When the `FillType` is `SlowFill`, the `Deposit` shall be refunded to the `depositor` address on the origin chain. - No specific method is prescribed for resolving the `Fill` on the destination chain. An `eth_getLogs` request can facilitate this, and if required, the `Bundle Block Range` could be narrowed by a binary search over the `FillStatus` field. This is left as an implementation decision. ### Finding Expired Deposits @@ -368,6 +368,17 @@ For the purpose of computing depositor refunds, each `Deposit` shall be consider - Depositor refunds are to be issued as part of the relayer refund procedure. - The `fillDeadline` timestamp shall be resolved to a block number on the destination chain in order to determine inclusion within the `Bundle Block Range`. +### Finding Unfillable Deposits +For the purpose of computing depositor refunds, each duplicate `Deposit` shall be considered unfillable by verifying that: +1. The `Deposit` is identical with another `Deposit`. +2. The destination chain `FillStatus` for the `Deposit` is `Filled`. +3. The destination chain `Fill` `FillType` was `SlowFill`. +4. The destination chain `Fill` occurred within the current `BundleBlockRange`. + +#### Note +- `Deposits` are considered identical when their `RelayData` matches. +- `Deposits` are considered duplicate when they are emitted after their initial identical instance. + ### Finding Slow Fill Requests For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, @@ -519,8 +530,9 @@ The Pool Rebalance Merkle Tree shall be constructed such that it is verifyable u ### Constructing the Relayer Refund Root At least one Relayer Refund Leaf shall be produced for each unique combination of SpokePool and `l1Token` for any of the following conditions: -- Valid `Fill` events, OR -- Expired `Deposit` events, OR +- Valid `Fills`, OR +- Expired `Deposits`, OR +- Unfillable `Deposits`, OR - A negative running balance net send amount. Each Relayer Refund Leaf shall be constructed as follows: @@ -555,9 +567,12 @@ The Relayer Refund Leaf `leafId` field shall be numbered according to the orderi ### Constructing the Slow Relay Root One Slow Relay Leaf shall be produced per valid `Slow Fill Request` emitted within the `Bundle Block Range` for a destination SpokePool. +One Slow Relay Leaf shall be produced per valid early `Slow Fill Request` where the corresponding `Deposit` was emitted within the `Bundle Block Range` for an origin SpokePool. A Slow Relay Leaf shall not be produced if the relevant `Slow Fill Request` `inputAmount` is equal to 0 and the `message` is a zero bytes string. +When a `Slow Fill Request` corresponds to multiple identical `Deposits`, the applied `quoteTimestamp` shall be sourced from the earliest identical `Deposit`. + Each Slow Relay Leaf shall be constructed as follows: 1. Set `relayData` to the `RelayData` emitted by the validated `Slow Fill Request`. 2. Set `chainId` to `destinationChainId` from the corresponding validated `Slow Fill Request`. From 33541bcba3f3875fe9ac94a180f7d251a1ed4334 Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Sun, 2 Feb 2025 17:09:06 -0500 Subject: [PATCH 26/29] Update UMIPs/umip-179.md --- UMIPs/umip-179.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 382b0b5e..e300a732 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -383,7 +383,7 @@ For the purpose of computing depositor refunds, each duplicate `Deposit` shall b For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, 2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, -3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` as at the end of the `Bundle Block Range`, +3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` at the end of the `Bundle Block Range`, 4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the `Bundle Block Range` on the origin SpokePool, 5. The `originChainId` and `destinationChainId` are not Lite chains. From 30439e9fc56069526a925ca8c184301d4797f922 Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Sun, 2 Feb 2025 17:09:33 -0500 Subject: [PATCH 27/29] Update UMIPs/umip-179.md --- UMIPs/umip-179.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index e300a732..3a577719 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -381,7 +381,7 @@ For the purpose of computing depositor refunds, each duplicate `Deposit` shall b ### Finding Slow Fill Requests For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: -1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, +1. The `fillDeadline` is greater than `destinationChainId` bundle end block's `block.timestamp`, 2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, 3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` at the end of the `Bundle Block Range`, 4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the `Bundle Block Range` on the origin SpokePool, From 3ddd03bbafaae5633096141c49b8e7e2d6879057 Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Sun, 2 Feb 2025 18:33:45 -0500 Subject: [PATCH 28/29] WIP Signed-off-by: Matt Rice --- UMIPs/umip-179.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 3a577719..193942af 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -341,7 +341,7 @@ For the purpose of computing relayer repayments, the following procedures are co ### Validating Fills Each of the `Fills` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `Fill` event `FillType` field is not set to `SlowFill`, AND -2. The component `RelayData` maps exactly to a corresponding `Deposit` event emitted on the relevant `originChainId`, AND +2. The component `RelayData` maps exactly to one or more corresponding `Deposit` events emitted on the relevant `originChainId`, AND 3. The corresponding `Deposit` event occurred within or before the `Bundle Block Range` on the origin chain SpokePool. #### Note @@ -373,7 +373,7 @@ For the purpose of computing depositor refunds, each duplicate `Deposit` shall b 1. The `Deposit` is identical with another `Deposit`. 2. The destination chain `FillStatus` for the `Deposit` is `Filled`. 3. The destination chain `Fill` `FillType` was `SlowFill`. -4. The destination chain `Fill` occurred within the current `BundleBlockRange`. +4. The destination chain `Fill` occurred within the current `BundleBlockRange` or the `Deposit` occurred within the current `BundleBlockRange`. #### Note - `Deposits` are considered identical when their `RelayData` matches. @@ -382,9 +382,9 @@ For the purpose of computing depositor refunds, each duplicate `Deposit` shall b ### Finding Slow Fill Requests For the purpose of computing slow fills to be issued to recipients, each `Slow Fill Request` emitted within the `Bundle Block Range` on a destination SpokePool shall be considered valid by verifying that: 1. The `fillDeadline` is greater than `destinationChainId` bundle end block's `block.timestamp`, -2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, -3. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` at the end of the `Bundle Block Range`, -4. The `Slow Fill Request` `RelayData` is matched by a corresponding `Deposit` event that occurred within or before the `Bundle Block Range` on the origin SpokePool, +2. The `Slow Fill Request` `RelayData` is matched by one or more corresponding `Deposit` events that occurred within or before the `Bundle Block Range` on the origin SpokePool, +3. The `inputToken` and `outputToken` addresses are equivalent at the earliest matching deposit's `quoteTimestamp`, +4. The destination SpokePool `FillStatus` mapping for the relevant `RelayData` hash is `SlowFillRequested` at the end of the `Bundle Block Range`, 5. The `originChainId` and `destinationChainId` are not Lite chains. #### Note @@ -395,7 +395,7 @@ For the purpose of computing slow fills to be issued to recipients, each `Slow F ### Finding Early Slow Fill Requests When an early `Slow Fill Request` is implied, the `Slow Fill Request` shall be validated as follows: 1. The `fillDeadline` has not already elapsed relative to the `destinationChainId` bundle end block number, -2. The `inputToken` and `outputToken` addresses are equivalent at the deposit `quoteTimestamp`, +2. The `inputToken` and `outputToken` addresses are equivalent at the earliest matching deposit's `quoteTimestamp`, 3. Neither the`originChainId` nor the `destinationChainId` is a `Lite` chain. #### Note @@ -416,10 +416,15 @@ The bundle LP fee for a `Bundle Block Range` on a SpokePool and token pair shall - `FilledRelay`. - `FilledV3Relay`. +#### Note + +Each `FilledRelay` or `FilledV3Relay` can have multiple associated deposit events. In the event of multiple matching deposit events, there will be multiple LP fees paid per event in the case of a non slow fill. + ### Computing Relayer Repayments -For a validated `Deposit` event, the relayer repayment amount shall be computed as follows: +For each validated matching `Deposit` event, the relayer repayment amount shall be computed as follows: - `(inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed over the set of HubPool `l1Token`, `originChainId` and `repaymentChainId` at the HubPool block number corresponding to the relevant `Deposit` `quoteTimestamp`. - The applicable rate model shall be sourced from the AcrossConfigStore contract for the relevant `l1Token`. +- For a given `Fill` that satisfies the requirements for relayer repayment, each matching `Deposit` generates a distinct repayment computed against its `quoteTimestamp`. The applied `repaymentChainId` shall be determined as follows: - When the `originChainId` is a `Lite chain` as at the `Deposit` `quoteTimestamp`: `originChainId`, ELSE @@ -441,7 +446,7 @@ For an expired `Deposit` event, the depositor refund amount shall be computed as ### Computing Slow Fill updated output amounts For the purpose of computing the amount to issue to a recipient for a SlowFill, the relayer fee shall be nulled by applying the following procedure: -- `updatedOutputAmount = (inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed at the deposit `quoteTimestamp` between `originChainId` and `destinationChainId`. +- `updatedOutputAmount = (inputAmount * (1 - realizedLpFeePct)) / 1e18`, where `realizedLpFeePct` is computed at the earliest matching deposit's `quoteTimestamp` between `originChainId` and `destinationChainId`. #### Constraint - The `Deposit` `outputAmount` shall _not_ be considered when determining SlowFill amounts. @@ -467,7 +472,7 @@ The procedure for computing running balances for an `l1Token` and `chainId` pair - For each group of validated `Fill` and `Pre-fill` events, initialize a running balance at 0 and add the add the relayer repayment. 3. Add deposit refunds: - - For each group of `Deposit` events that expired within the `Bundle Block Range`, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. + - For each group of `Deposit` events that expired or were deemed unfillable within the `Bundle Block Range`, sum the total deposit refunds on the origin chain. Add the amount to the exsting relayer refunds for that chain. 4. Add slow fills: - For each group of validated `Slow Fill Requests`, add each slow relay's `updatedOutputAmount` to the group's running balance. From b221c6f2d6cd40f3a51745bb5fb8630f020827af Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Mon, 3 Feb 2025 14:12:51 -0500 Subject: [PATCH 29/29] update language around migration Signed-off-by: Matt Rice --- UMIPs/umip-179.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/UMIPs/umip-179.md b/UMIPs/umip-179.md index 193942af..624aaab6 100644 --- a/UMIPs/umip-179.md +++ b/UMIPs/umip-179.md @@ -597,8 +597,10 @@ The array of Slow Relay Leaf instances shall be sorted according to; - Relayers are advised to factor in origin chain finality guarantees when making fills on destination chains. Origin chain re-organisation can lead to deposit re-ordering and can thus invalidate fills. # Migration -- Support for Across events with `bytes32` types (`FundsDeposited`, `FilledRelay`, ...) is required as at ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 5. -- The `Legacy` events defined in this UMIP are marked as deprecated 7 days after the ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) migration from 4 to 5. +- Support for the logic described above (BUT NOT the updated events with `bytes32` types, like `FundsDeposited`, `FilledRelay`, ...) is required as of ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 5. +- To ensure pre-fills are not double-refunded, the `Bundle Block Range` containing the version bump from 4 to 5 will follow the rules of this UMIP, but will not consider any `Fill` events from prior bundles for the purposes of generating relayer repayments. Similarly, no `Slow Fill Request` that was included in any prior bundle will be considered for the generation of a `Slow Relay Leaf`. All subsequent bundles will perform the logic exactly as described above. +- Support for Across events with `bytes32` types (`FundsDeposited`, `FilledRelay`, ...) is required as of ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) 6. +- The `Legacy` events defined in this UMIP are marked as deprecated 7 days after the ConfigStore [VERSION](https://github.com/UMAprotocol/UMIPs/blob/7b1a046098d3e2583abd0372c5e9c6003b46ad92/UMIPs/umip-157.md#versions) migration from 5 to 6. # Implementation The Across v3 implementation is available in the Across [contracts-v2](https://github.com/across-protocol/contracts) repository.