changes requested in final review

This commit is contained in:
maquirriaincf
2025-04-04 03:44:55 -03:00
parent 3463591b56
commit 1de43a53ab

View File

@@ -1,8 +1,8 @@
# BridgeEndpoint
- Location: `xlink/packages/contracts/bridge-solidity/contracts`
- Deployed contracts: [BridgeEndpoint](0x84254dA34abE4678017A5Bf78506B48490ce4547), [BridgeEndpointWithSwap](0x84254dA34abE4678017A5Bf78506B48490ce4547).
- Deployed contracts: See [Ethereum Contract Addresses](https://docs.xlink.network/xlink-network/readme/ethereum-contract-addresses).
This technical document provides a detailed overview of the Bridge Endpoint in the Ethereum blockchain. The Bridge Endpoint facilitates communication between two blockchain networks by acting as the entry and exit point for assets moving along the Cross Chain Bridge. It passes messages between chains in the form of events, triggers contract calls, processes token transfers and validates and executes the unwrapping of tokens. The Bridge Endpoint functionality is implemented across two contracts, `BridgeEndpoint` and `BridgeEndpointWithSwap`. `BridgeEndpointWithSwap` extends `BridgeEndpoint` and implements the necessary functionality to source liquidity from external aggregators.
This technical document provides a detailed overview of the Bridge Endpoint in EVM-compatible blockchains. The Bridge Endpoint facilitates communication between two blockchain networks by acting as the entry and exit point for assets moving along the Cross Chain Bridge. It passes messages between chains in the form of events, triggers contract calls, processes token transfers and validates and executes the unwrapping of tokens. The Bridge Endpoint functionality is implemented across two contracts, `BridgeEndpoint` and `BridgeEndpointWithSwap`. `BridgeEndpointWithSwap` extends `BridgeEndpoint` and implements the necessary functionality to source liquidity from external aggregators.
This functionality is implemented and distributed across the following contracts:
@@ -25,7 +25,7 @@ Stores a reference to the `BridgeRegistry` contract, which manages approved toke
| -------- | ------ |
| Variable | `address` |
The address where tokens are deposited before bridging.
The address from which non-burnable tokens are transferred during peg-in operations.
### `timeLock`
@@ -33,7 +33,7 @@ The address where tokens are deposited before bridging.
| -------- | ------ |
| Variable | `ITimeLock` |
Manages locked transactions that require a delay before execution. Tokens exceeding the timelock threshold are not immediately sent to the user. Instead, the timeLock contract holds them until the waiting period expires and then releases the tokens.
Manages locked transactions that require a delay before execution. Tokens amounts that exceed the threshold are not immediately sent to the user. Instead, the `timeLock` contract holds them until the waiting period expires and then releases the tokens, completing the transfer.
### `timeLockThreshold`
@@ -41,21 +41,21 @@ Manages locked transactions that require a delay before execution. Tokens exceed
| -------- | ------ |
| Variable | `uint256` |
The minimum token amount that triggers a timelock. By default, the value is set to `0`.
The global minimum token amount that triggers a timelock. By default, the value is set to `0`.
### `timeLockThresholdByToken`
| Data | Type |
| -------- | ------ |
| Variable | `mapping(address => uint256)` |
Custom timelock thresholds for different tokens.
Optional custom timelock thresholds for different tokens. The timelock will be triggered when a token amount exceeds the custom threshold, if applicable. If no custom threshold is set, the token amount will need to exceed the global threshold set in [`timeLockThreshold`](#timelockthreshold).
### `unwrapSent`
| Data | Type |
| -------- | ------ |
| Variable | `mapping(bytes32 => OrderPackage)` |
Stores unwrap transactions that need to be finalized. It stores a mapping of `OrderPackage` structs, which contain a flag indicating whether the unwrap has been completed.
Stores unwrap orders that need to be finalized. It stores a mapping of [`OrderPackage`](#orderpackage) structs, which contain a flag indicating whether the unwrap has been completed. `bytes32` is a unique hash of the struct parameters, as calculated by [`transferToUnwrap`](#transfertounwrap).
### `swapExecutor`
###### _(only present in BridgeEndpointWithSwap)_
@@ -64,7 +64,7 @@ Stores unwrap transactions that need to be finalized. It stores a mapping of `Or
| -------- | ------ |
| Variable | `SwapExecutor` |
Holds a reference to SwapExecutor, which is the contract that executes swaps.
Holds a reference to `SwapExecutor`, which is the contract that executes swaps.
### `swapSent`
###### _(only present in BridgeEndpointWithSwap)_
@@ -73,7 +73,7 @@ Holds a reference to SwapExecutor, which is the contract that executes swaps.
| -------- | ------ |
| Variable | `mapping(bytes32 => SwapOrderPackage)` |
A mapping to track swap orders. `bytes32` is a unique hash of the swap parameters, as calculated by `transferToSwap`.
A mapping of [`SwapOrderPackage`](#swaporderpackage) structs that contains details of swap orders.`bytes32` is a unique hash of the swap parameters, as calculated by [`transferToSwap`](#transfertoswap).
## Data Types
@@ -92,7 +92,7 @@ struct OrderPackage {
#### `SignaturePackage`
Contains signatures from validators to prove a transaction is legitimate. It is used for verifying cross-chain transactions.
Contains signatures from validators to prove an order is legitimate. It is used for verifying cross-chain transfers.
```solidity
struct SignaturePackage {
@@ -105,7 +105,7 @@ struct SignaturePackage {
#### `SwapOrderPackage`
###### _(only present in BridgeEndpointWithSwap)_
A struct that stores details of a swap transaction.
A struct that stores details of a swap order.
```solidity
struct SwapOrderPackage {
@@ -124,18 +124,21 @@ struct SwapOrderPackage {
- `onlyApprovedToken(token)`: ensures the token is approved in the registry.
- `onlyApprovedRelayer()`: ensures the caller is an approved relayer.
- `notWatchlist(recipient)`: prevents transactions to watchlisted addresses.
- `notWatchlist(recipient)`: prevents transfers to watchlisted addresses.
- `nonReentrant`: protects against reentrancy attacks.
- `onlyAllowlisted`: ensures only allowed addresses can execute certain functions.
## Features
#### `sendMessageWithToken`
This function transfers a token across chains, deducts a fee, and emits an event. The user deposits tokens on the bridge contract in the source chain. The contract checks that the token is approved (since `sendMessageWithToken` has the `onlyApprovedToken` modifier). This function calls `_transfer`, which performs validations. Finally, it emits a `SendMessageWithTokenEvent` containing the transaction details. Afterwards, off-chain validators sign the transaction.
This function is called to initiate the peg-out process from an EVM-compatible blockchain onto other chains, such as Stacks or Solana. The user deposits tokens in the bridge contract, which are burned or locked, depending on the token. The contract checks that the token is approved, since [`sendMessageWithToken`](#sendmessagewithtoken) has the `onlyApprovedToken` modifier. The function calls [`_transfer`](#_transfer), which performs validations. Finally, the function emits a [`SendMessageWithTokenEvent`](#sendmessagewithtokenevent) containing the transaction details, which will be reviewed by validators. Once they verify that the tokens were deposited in the `BridgeEndpoint` contract, the validators will sign the order and relayers will submit it in the destination chain.
##### Parameters
```solidity
address token, uint256 amount, bytes calldata payload
address token,
uint256 amount,
bytes calldata payload
```
#### `sendMessage`
@@ -149,7 +152,7 @@ bytes calldata payload
#### `transferToUnwrap`
This function is called by a relayer after `sendMessageWithToken` is executed, with the purpose of sending tokens to a recipient. Relayers will listen for the corresponding `SendMessageWithTokenEvent` on the source chain and call `transferToUnwrap` providing the token, recipient and amount, a salt (a unique transaction identifier, usually the source chain transaction hash), and an array of validator signatures (proofs). The contract validates the transaction and generates a EIP-712 hash, which acts as a unique identifier for each swap.
This function is called by a relayer when a user initiates a token transfer from another blockchain. The originating order may come from an EVM chain (via [`sendMessageWithToken`](#sendmessagewithtoken)), or from a non-EVM chain like Stacks or Solana. Relayers listen for the corresponding event on the source chain and call [`transferToUnwrap`](#transfertounwrap) on the destination chain, supplying the recipient, token, amount, a salt (usually the source chain order hash), and an array of validator signatures (proofs). The contract verifies these proofs and generates an EIP-712-compliant hash, which acts as a unique identifier for each transfer.
##### Parameters
```solidity
@@ -161,8 +164,7 @@ SignaturePackage[] calldata proofs
```
#### `finalizeUnwrap`
Completes an unwrap transaction and releases tokens to the recipient. If the token transfer was delayed (timelocked), the unwrap must be manually finalized. The function loops through each `orderHash` and calls `_finalizeUnwrap(orderHash)`, which verifies that the transaction has not already been completed, transfers tokens from `unwrapSent` mapping to the recipient and marks the order as sent. Finally, it emits `FinalizeUnwrapEvent.`
This function completes a pending unwrap order for non-burnable tokens. It is called by a relayer once the timeLock period expires and the recipient can receive their locked tokens. It loops through each `orderHash` and calls [`_finalizeUnwrap()`](#_finalizeunwrap), which verifies that the order has not already been completed and transfers the token and amount stored in [`unwrapSent`](#unwrapsent) to the recipient. The order is then marked as completed, and the [`FinalizeUnwrapEvent`](#finalizeunwrapevent) is emitted.
##### Parameters
```solidity
@@ -172,7 +174,7 @@ bytes32[] calldata orderHash
#### `transferToSwap`
###### _(in contract BridgeEndpointWithSwap)_`
This function executes a swap before bridging tokens. If the token is burnable, the contract mints the required amount before swapping, calls `_executeSwap` to perform the swap and emits a `TransferToSwapEvent` recording the details. If it is not burnable, it saves swap details in the `swapSent` mapping and emits `SwapOrderCreated` so the swap can be finalized later. In either case, the function will validate token and relayer permissions and generate a unique EIP-712 hash to identify the swap.
This function executes a swap before bridging tokens. If the token is burnable, the contract mints the required amount before swapping, calls [`_executeSwap`](#_executeswap) to perform the swap and emits a [`TransferToSwapEvent`](#transfertoswapevent) recording the details. If it is not burnable, it saves swap details in the [`swapSent`](#swapsent) mapping and emits [`SwapOrderCreated`](#swapordercreated) so the swap can be finalized later. In either case, the function will validate token and relayer permissions and generate a unique EIP-712 hash to identify the swap.
##### Parameters
```solidity
@@ -190,7 +192,7 @@ SignaturePackage[] calldata proofs
#### `finalizeSwap`
###### _(in contract BridgeEndpointWithSwap)_`
This function is used when a token is not burnable, leading `transferToSwap` to store the swap order instead of executing it immediately. It ensures input arrays are valid, and it loops through each `orderHash` and calls `_finalizeSwap()`.
This function is used when a token is not burnable, leading [`transferToSwap`](#transfertoswap) to store the swap order instead of executing it immediately. It ensures input arrays are valid, and it loops through each `orderHash` and calls [`_finalizeSwap()`](#_finalizeswap).
##### Parameters
```solidity
@@ -223,7 +225,8 @@ Sets a custom timelock threshold per token.
##### Parameters
```solidity
address token, uint256 _timeLockThreshold
address token,
uint256 _timeLockThreshold
```
#### `addAllowList`
@@ -247,10 +250,6 @@ Resumes contract operations after a pause, allowing bridging and transfers again
### Read-Only Functions
#### `onAllowList`
Returns `true` if the provided address is on the allowlist, which means it has permission to use the contracts functions.
#### `offAllowList`
Returns `true` if the provided address is not on the allowlist.
@@ -260,15 +259,20 @@ Returns `true` if the provided address is not on the allowlist.
address account
```
#### `onAllowList`
Returns `true` if the provided address is on the allowlist, which means it has permission to use the contracts functions.
### Relevant Internal Functions
#### `_transfer`
Transfers a token from the sender, deducts fees, and sends the remainder to the bridge.
This internal function is responsible for processing token transfers when a user sends tokens into the bridge. It is called from [`sendMessageWithToken`](#sendmessagewithtoken) and performs validations, calculates and deducts fees, and sends the remaining amount to the receiver. This function ensures the transfer amount is within allowed limits and that it is large enough to cover the minimum fee. If the token is burnable, if burns the amount minus the fee, which is sent to the `BridgeRegistry` contract.
##### Parameters
```solidity
address token, uint256 amount
address token,
uint256 amount
```
#### `_validateOrder`
@@ -277,7 +281,8 @@ Verifies if an order is legitimate by checking validator signatures.
##### Parameters
```solidity
bytes32 orderHash, SignaturePackage[] calldata proofs
bytes32 orderHash,
SignaturePackage[] calldata proofs
```
#### `_finalizeUnwrap`
@@ -286,23 +291,24 @@ Completes an unwrap transaction by transferring tokens to the recipient.
##### Parameters
```solidity
(bytes32 orderHash)
bytes32 orderHash
```
#### `_finalizeSwap`
###### _(in contract BridgeEndpointWithSwap)_`
This function is called by `finalizeSwap` to retrieve a stored swap order and to execute the swap. It checks if the order exists and has not been executed, transfers `amountIn` tokens from the sender to the `BridgeEndpointWithSwap` contract and calls `_executeSwap` to perform the swap. Finally, it marks the order as sent and emits a `SwapOrderFinalized` event.
This function is called by [`finalizeSwap`](#finalizeswap) to retrieve a stored swap order and to execute the swap. It checks if the order exists and has not been executed, transfers `amountIn` tokens from the sender to the `BridgeEndpointWithSwap` contract and calls [`_executeSwap`](#_executeswap) to perform the swap. Finally, it marks the order as sent and emits a [`SwapOrderFinalized`](#swaporderfinalized) event.
##### Parameters
```solidity
bytes32 orderHash, bytes memory swapPayload
bytes32 orderHash,
bytes memory swapPayload
```
#### `_executeSwap`
###### _(in contract BridgeEndpointWithSwap)_`
This function approves `swapExecutor` to spend `tokenIn` and calls its `executeSwap()` function to attempt the swap. If the swap succeeds, it either burns the swapped tokens or prepares them for transfer. To transfer the tokens, `tokenOut` is sent to `pegInAddress` for bridging and a `SendMessageWithTokenEvent` is emitted. If the swap fails, the error is logged via `SwapExecutorError`, approvals are revoked and a `SendMessageWithTokenEvent` with `bridgePayloadFailure` is emitted. In either case, the function will burn `tokenIn` tokens if applicable.
This function approves `swapExecutor` to spend `tokenIn` and calls its `executeSwap()` function to attempt the swap. If the swap succeeds, it either burns the swapped tokens or prepares them for transfer. To transfer the tokens, `tokenOut` is sent to [`pegInAddress`](#peginaddress) for bridging and a [`SendMessageWithTokenEvent`](#sendmessagewithtokenevent) is emitted. If the swap fails, the error is logged via `SwapExecutorError`, approvals are revoked and a [`SendMessageWithTokenEvent`](#sendmessagewithtokenevent) with `bridgePayloadFailure` is emitted. In either case, the function will burn `tokenIn` tokens if applicable.
##### Parameters
```solidity
@@ -324,12 +330,14 @@ Emitted when a user sends a message without transferring tokens.
##### Parameters
```solidity
address indexed from, uint256 value, bytes payload
address indexed from,
uint256 value,
bytes payload
```
#### `SendMessageWithTokenEvent`
Emitted when a user executes a transaction.
Emitted when a user initiates a peg-out order.
##### Parameters
```solidity
@@ -342,7 +350,7 @@ bytes payload
#### `TransferToUnwrapEvent`
Emitted when an order is created to unwrap tokens. This event is emitted when a transaction is validated and tokens have to be transfered to a recipient.
Emitted when an order is created to unwrap tokens. This event is emitted when an order is validated and tokens have to be transfered to a recipient.
##### Parameters
```solidity
@@ -364,7 +372,7 @@ bytes32 indexed orderHash
#### `SetTimelockEvent`
Emitted when `timeLock` is updated by the contract owner.
Emitted when [`timeLock`](#timelock) is updated by the contract owner.
##### Parameters
```solidity
@@ -397,13 +405,14 @@ Emitted when a swap operation fails during the bridge transfer.
##### Parameters
```solidity
address indexed target, bytes reason
address indexed target,
bytes reason
```
#### `SwapOrderCreated`
###### _(only present in BridgeEndpointWithSwap)_
Emitted when a new swap order is created for non-burnable tokens. It logs the creation of swap orders, helping track orders before execution.
Emitted when a new swap order is created for non-burnable tokens. It logs the creation of swap orders, helping to track them before execution.
##### Parameters
```solidity
@@ -450,6 +459,7 @@ bool success
## Contract Calls (Interactions)
- `BridgeRegistry`: this contract is called to process orders and to manage validator roles and fees. It acts as the central registry for approved tokens, relayers and validators.
- `ITimeLock`: provides the implementation for timelocked transactions.
- `IBurnable`: handles the wrapping/unwrapping process in a bridge by burning tokens on one chain and minting them on another.
- `ITimeLock`: the `ITimeLock` interface is utilized to interact with the [`timeLock`](#timelock) contract by calling the `createAgreement` function when bridged amounts exceeds the threshold.
- `IBurnable`: this interface is used for burnable tokens to enable mint and burn operations.
- `ERC20`: all approved tokens within the bridge must implement the `ERC20Fixed` standard, which is an XLink's custom standard that extends ERC-20 to handle fixed precision. Token contract interactions occur in both peg-in and peg-out operations for non-burnable tokens, using the `transferFromFixed`, `transferFixed`, and `increaseAllowanceFixed` functions.
- `SwapExecutor`: this contract is called by `BridgeEndpointWithSwap` to execute swaps with external liquidity aggregators during bridging.