Proof of Concept Cross-Chain Bridge Secured by EigenLayer
Developer Documentation
For detailed developer documentation, please visit our GitHub Pages site. This site is autogenerated from the code and provides comprehensive information about the project's structure, functions, and usage.
Overview
This project is a proof of concept for a decentralized bridge secured with attestations by EigenLayer's AVS operators. The goal is to demonstrate how EigenLayer can be used to secure cross-chain token transfers without direct communication between chains. Arbitrary message passing allows not only instantaneous settlement but also the ability to transfer between non VM-compatible chains such as Ethereum and Solana, or Bitcoin.
What is EigenLayer?
EigenLayer is a protocol that allows operators to receive delegated stake in order to secure various applications (such as applications relying on off-chain state). Operators are incentivized through application rewards and penalized through stake slashing if they act maliciously.
EigenLayer relies on at least one smart contract interacting with the EigenLayer protocol, that registers and tracks operators and their stake, as well as defines the rules for rewards and penalties.
Objective
This proof of concept aims to showcase the potential of EigenLayer in securing decentralized bridges. It includes smart contracts that handle bridging operations, attestation verification, and slashing mechanisms.
Project Structure
-
Contracts:
ECDSAUtils.sol
: Provides ECDSA signature utilities.BridgeServiceManager.sol
: Manages bridge operations and attestation validations.PermissionedBridge.sol
: Manages bridge operations with manually set operator weights.Events.sol
: Contains event definitions for bridge operations.Structs.sol
: Defines structs and related functions for bridge operations.Vault.sol
: Abstract contract providing common vault functionality for bridge contracts.
-
Tests:
EigenLayerBridge.t.sol
: Tests forBridgeServiceManager.sol
.PermissionedBridge.t.sol
: Tests forPermissionedBridge.sol
.
Getting Started
Prerequisites
Installation
-
Clone the repository:
git clone https://github.com/your-repo/eigenlayer-bridge.git cd eigenlayer-bridge
-
Install Foundry:
curl -L https://foundry.paradigm.xyz | bash foundryup
Running Tests
To run the tests, use the Foundry framework. Running the tests requires an HTTP endpoint to Ethereum mainnet.
The tests use an anvil fork-test from latest Ethereum mainnet state in order to simulate a realistic environment and test against the EigenLayer contracts deployed there.
forge test --rpc-url <RPC_URL>
Detailed Explanations
ECDSA Signature Verification
The ECDSAUtils
contract provides utilities for verifying ECDSA signatures. These utilities are essential for ensuring the authenticity and integrity of the bridge request data. The process involves two main functions:
- getDigest: Computes the EIP712 digest of the bridge request data, which is used for signing.
- getSigner: Recovers the signer's address from the given bridge request data and signature.
Example Function: getDigest
This function computes the EIP712 digest for the given bridge request data, ensuring that the data can be signed in a standardized and secure way.
function getDigest(Structs.BridgeRequestData memory data) public view returns (bytes32) {
return _hashTypedDataV4(
keccak256(
abi.encode(
keccak256(
"BridgeRequestData(address user,address tokenAddress,uint256 amountIn,uint256 amountOut,address destinationVault,address destinationAddress,uint256 transferIndex)"
),
data.user,
data.tokenAddress,
data.amountIn,
data.amountOut,
data.destinationVault,
data.destinationAddress,
data.transferIndex
)
)
);
}
Attestation Mechanism
The attestation mechanism leverages EigenLayer's AVS operators to secure the bridge. Here's a detailed explanation of the process:
- Bridge Request Creation: A user creates a bridge request, which is stored on-chain and emits an event for operators to observe.
- Signature Collection: AVS operators observe the bridge request event and sign the request data using their private keys. These signatures are then submitted back to the bridge contract.
- Attestation Verification: The bridge contract verifies these signatures to ensure they are from valid operators with sufficient stake.
- Fund Release: Once the contract verifies that enough valid signatures (attestations) have been collected, it releases the funds to the destination address.
Example Function: publishAttestation
This function allows an AVS operator to publish an attestation for a bridge request. It verifies the operator's weight and ensures no double attestations for the same request.
function publishAttestation(bytes memory attestation, uint256 _bridgeRequestId) public nonReentrant onlyOperator {
require(operatorHasMinimumWeight(msg.sender), "Operator does not have minimum weight");
require(!operatorResponses[msg.sender][_bridgeRequestId], "Operator has already responded to the task");
require(msg.sender == getSigner(bridgeRequests[_bridgeRequestId], attestation), "Invalid attestation signature");
uint256 operatorWeight = getOperatorWeight(msg.sender);
bridgeRequestWeights[_bridgeRequestId] += operatorWeight;
rewardAttestation(msg.sender);
emit AVSAttestation(attestation, _bridgeRequestId, operatorWeight);
}
Fund Release Process
The fund release process is critical to ensuring that the bridge operates securely and efficiently. The process involves the following steps:
- Signature Verification: The contract verifies that the submitted signatures are valid and from authorized operators.
- Weight Calculation: It sums the weights of the valid signatures to ensure that the total weight meets or exceeds the required threshold.
- Fund Transfer: If the total weight is sufficient, the contract transfers the funds to the destination address.
- Incentivizing Validators: The contract pays out gas costs and a small incentive to the caller who initiates the fund release, encouraging users to participate in this final step.
Example Function: releaseFunds
This function releases the funds to the destination address once the required attestations are verified. It ensures the transaction's economic security by checking the total attested weight.
function releaseFunds(bytes[] memory signatures, Structs.BridgeRequestData memory data) public nonReentrant {
uint256 totalWeight = 0;
for (uint256 i = 0; i < signatures.length; i++) {
address signer = getSigner(data, signatures[i]);
require(operatorResponses[signer][data.transferIndex], "Invalid signature");
totalWeight += getOperatorWeight(signer);
}
require(totalWeight >= data.amountOut, "Insufficient total weight to cover swap");
IERC20(data.tokenAddress).transfer(data.destinationAddress, data.amountOut);
payoutCrankGasCost();
emit FundsReleased(data.tokenAddress, data.destinationAddress, data.amountOut);
}
AVS Interactions
EigenLayer's AVS operators play a crucial role in the security of the bridge. These operators:
- Monitor: Observe events emitted by the bridge contract to detect new bridge requests.
- Sign: Validate the bridge request and provide their signature as an attestation.
- Submit: Send their attestations back to the bridge contract.
- Get Rewarded: Receive rewards for valid attestations and get penalized for any malicious activities through slashing.
These interactions ensure that the bridge is both secure and decentralized, relying on the collective security provided by the EigenLayer's staked operators.
Testing
Introduction
This section covers the testing of our smart contracts using the Forge test framework. The tests are written in Solidity and simulate various scenarios to ensure the correctness of the bridge operations and attestation mechanisms.
Setting Up the Test Environment
The test environment is set up using the setUp
function in each test contract. This function initializes the contract instances, allocates initial balances, and configures the necessary parameters.
Example Setup Function
function setUp() public {
(operator, operatorPrivateKey) = makeAddrAndKey("operator");
localVault = new BridgeServiceManager(
aVSDirectory, stakeRegistry, rewardsCoordinator, delegationManager,
crankGasCost, 0, bridgeFee, "PermissionedBridge", "1"
);
localVault.initialize();
remoteVault = new BridgeServiceManager(
aVSDirectory, stakeRegistry, rewardsCoordinator, delegationManager,
crankGasCost, 0, bridgeFee, "PermissionedBridge", "1"
);
remoteVault.initialize();
deal(bob, 1 ether);
deal(usdc, bob, 1000 * 10**6);
deal(usdc, address(remoteVault), 1000 * 10**6);
deal(operator, 1 ether);
}
Test Cases
Test Case 1: Bridge Request Emission
This test case ensures that a bridge request emits the correct events when created.
function testBridgeRequestEmitEvents() public returns (Structs.BridgeRequestData memory) {
vm.startPrank(bob);
IERC20(usdc).approve(address(localVault), 1000 * 10**6);
vm.expectEmit(true, true, true, true);
emit Events.BridgeRequest(bob, usdc, 0, 1000 * 10**6, 1000 * 10**6, address(remote
Vault), alice, 0);
localVault.bridge{value: bridgeFee}(usdc, 1000 * 10**6, 1000 * 10**6, address(remoteVault), alice);
vm.stopPrank();
return Structs.BridgeRequestData(
bob,
usdc,
1000 * 10**6,
1000 * 10**6,
address(remoteVault),
alice,
0
);
}
Test Case 2: Operator Attestation Submission
This test case verifies that an operator can submit an attestation for a bridge request.
function testOperatorCanSubmitAttestation() public {
testBridgeRequestEmitEvents();
(
address user,
address tokenAddress,
uint256 amountIn,
uint256 amountOut,
address destinationVault,
address destinationAddress,
uint256 transferIndex
) = localVault.bridgeRequests(0);
Structs.BridgeRequestData memory bridgeRequest = Structs.BridgeRequestData(
user,
tokenAddress,
amountIn,
amountOut,
destinationVault,
destinationAddress,
transferIndex
);
bytes memory attestation = signBridgeRequestData(localVault, bridgeRequest, operatorPrivateKey);
vm.prank(operator);
vm.expectEmit(true, true, true, true);
emit Events.AVSAttestation(attestation, 0, 1000 ether);
localVault.publishAttestation(attestation, 0);
}
Test Case 3: Fund Release Completion
This test case ensures that the bridge completes and releases funds correctly.
function testBridgeCompletesReleaseFunds() public {
testBridgeRequestEmitEvents();
(
address user,
address tokenAddress,
uint256 amountIn,
uint256 amountOut,
address destinationVault,
address destinationAddress,
uint256 transferIndex
) = localVault.bridgeRequests(0);
Structs.BridgeRequestData memory bridgeRequest = Structs.BridgeRequestData(
user,
tokenAddress,
amountIn,
amountOut,
destinationVault,
destinationAddress,
transferIndex
);
bytes memory attestation = signBridgeRequestData(remoteVault, bridgeRequest, operatorPrivateKey);
bytes[] memory bridgeRequestSignatures = new bytes[](1);
bridgeRequestSignatures[0] = attestation;
assertEq(IERC20(usdc).balanceOf(address(remoteVault)), 1000 * 10**6);
assertEq(IERC20(usdc).balanceOf(alice), 0);
vm.prank(alice);
remoteVault.releaseFunds(bridgeRequestSignatures, bridgeRequest);
assertEq(IERC20(usdc).balanceOf(address(remoteVault)), 0);
assertEq(IERC20(usdc).balanceOf(alice), 1000 * 10**6);
}
License
This project is licensed under the UNLICENSED License.
Disclaimer
This project is provided "as is" with no guarantees or warranties. It is intended as a proof of concept only and should not be used in production environments. Use at your own risk.
BridgeServiceManager
Inherits: ECDSAServiceManagerBase, Vault
Manages bridge operations and attestation validations
Extends ECDSAServiceManagerBase and Vault for bridging and staking functionality
State Variables
operatorResponses
Tracks bridge requests that this operator has responded to once to avoid duplications
Double attestations would technically be valid and allow operators to recursively call until funds are released
mapping(address => mapping(uint256 => bool)) public operatorResponses;
bridgeRequestWeights
Tracks the total operator weight attested to a bridge request
Helpful for determining when enough attestations have been collected to release funds.
mapping(uint256 => uint256) public bridgeRequestWeights;
Functions
constructor
Initializes the contract with the necessary addresses and parameters
constructor(
address _avsDirectory,
address _stakeRegistry,
address _rewardsCoordinator,
address _delegationManager,
uint256 _crankGasCost,
uint256 _AVSReward,
uint256 _bridgeFee,
string memory _name,
string memory _version
)
ECDSAServiceManagerBase(_avsDirectory, _stakeRegistry, _rewardsCoordinator, _delegationManager)
Vault(_crankGasCost, _AVSReward, _bridgeFee, _name, _version);
Parameters
Name | Type | Description |
---|---|---|
_avsDirectory | address | The address of the AVS directory contract, managing AVS-related data for registered operators |
_stakeRegistry | address | The address of the stake registry contract, managing registration and stake recording |
_rewardsCoordinator | address | The address of the rewards coordinator contract, handling rewards distributions |
_delegationManager | address | The address of the delegation manager contract, managing staker delegations to operators |
_crankGasCost | uint256 | The estimated gas cost for calling release funds, used to calculate rebate and incentivize users to call |
_AVSReward | uint256 | The total reward for AVS attestation |
_bridgeFee | uint256 | The total fee charged to the user for bridging |
_name | string | The name of the contract, used for EIP-712 domain construction |
_version | string | The version of the contract, used for EIP-712 domain construction |
onlyOperator
Ensures that only registered operators can call the function
modifier onlyOperator();
rewardAttestation
Rewards the operator for providing a valid attestation
Placeholder for actual AVS reward distribution pending Eigen M2 implementation
function rewardAttestation(address operator) internal;
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator to be rewarded |
publishAttestation
Publishes an attestation for a bridge request
function publishAttestation(bytes memory attestation, uint256 _bridgeRequestId) public nonReentrant onlyOperator;
Parameters
Name | Type | Description |
---|---|---|
attestation | bytes | The signed attestation |
_bridgeRequestId | uint256 | The ID of the bridge request |
slashMaliciousAttestor
Slashes a malicious attestor's stake
Placeholder for slashing logic pending Eigen implementations
function slashMaliciousAttestor(address operator, uint256 penalty) internal;
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator to be slashed |
penalty | uint256 | The penalty amount to be slashed |
challengeAttestation
Challenges a potentially fraudulent attestation
function challengeAttestation(
bytes memory fraudulentSignature,
Structs.BridgeRequestData memory fraudulentBridgeRequest
) public nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
fraudulentSignature | bytes | The signature of the fraudulent attestation |
fraudulentBridgeRequest | Structs.BridgeRequestData | The data of the fraudulent bridge request |
payoutCrankGasCost
Payouts the crank gas cost to the caller
function payoutCrankGasCost() internal;
_releaseFunds
Releases funds to the destination address
function _releaseFunds(bytes memory data) public override nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
data | bytes | The bridge request data and signatures |
releaseFunds
Releases funds to the destination address with typed data for ABI construction
function releaseFunds(bytes[] memory signatures, Structs.BridgeRequestData memory data) public nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
signatures | bytes[] | The signatures of the operators attesting to the bridge request |
data | Structs.BridgeRequestData | The bridge request data |
operatorHasMinimumWeight
Checks if the operator has the minimum required weight
function operatorHasMinimumWeight(address operator) public view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | True if the operator has the minimum weight, false otherwise |
getOperatorWeight
Gets the weight of an operator
function getOperatorWeight(address operator) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The weight of the operator |
receive
Fallback function to receive ether
receive() external payable;
ECDSAUtils
Inherits: EIP712
Provides ECDSA signature utilities for verifying bridge request data
Functions
constructor
Initializes the EIP712 domain with the given name and version
constructor(string memory name, string memory version) EIP712(name, version);
Parameters
Name | Type | Description |
---|---|---|
name | string | The user-readable name of the signing domain |
version | string | The current major version of the signing domain |
getDigest
Computes the EIP712 digest for the given bridge request data
function getDigest(Structs.BridgeRequestData memory data) public view returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
data | Structs.BridgeRequestData | The bridge request data to be hashed |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The EIP712 hash of the given bridge request data |
getSigner
Recovers the signer address from the given bridge request data and signature
function getSigner(Structs.BridgeRequestData memory data, bytes memory signature) public view returns (address);
Parameters
Name | Type | Description |
---|---|---|
data | Structs.BridgeRequestData | The bridge request data that was signed |
signature | bytes | The ECDSA signature |
Returns
Name | Type | Description |
---|---|---|
<none> | address | The address of the signer |
Events
Contains event definitions for bridge operations
Events
BridgeRequest
Emitted when a new bridge request is created
event BridgeRequest(
address indexed user,
address indexed tokenAddress,
uint256 indexed bridgeRequestId,
uint256 amountIn,
uint256 amountOut,
address destinationVault,
address destinationAddress,
uint256 transferIndex
);
Parameters
Name | Type | Description |
---|---|---|
user | address | The address of the user initiating the bridge request |
tokenAddress | address | The address of the token to be bridged |
bridgeRequestId | uint256 | The unique ID of the bridge request |
amountIn | uint256 | The amount of tokens to be bridged |
amountOut | uint256 | The amount of tokens expected at the destination |
destinationVault | address | The address of the destination vault |
destinationAddress | address | The address of the recipient at the destination |
transferIndex | uint256 | The transfer index for unique tracking |
AVSAttestation
Emitted when an attestation is published by an AVS operator
event AVSAttestation(bytes indexed attestation, uint256 indexed bridgeRequestId, uint256 indexed operatorWeight);
Parameters
Name | Type | Description |
---|---|---|
attestation | bytes | The attestation data |
bridgeRequestId | uint256 | The ID of the bridge request |
operatorWeight | uint256 | The weight of the operator attesting |
FundsReleased
Emitted when funds are released to the destination address
event FundsReleased(address indexed destinationVault, address indexed destinationAddress, uint256 indexed amountOut);
Parameters
Name | Type | Description |
---|---|---|
destinationVault | address | The address of the destination vault |
destinationAddress | address | The address of the recipient at the destination |
amountOut | uint256 | The amount of tokens released |
PermissionedBridge
Inherits: Vault
Manages bridge operations with manually set operator weights
Extends Vault for bridging functionality
State Variables
operatorResponses
Tracks bridge requests that this operator has responded to once to avoid duplications
Double attestations would technically be valid and allow operators to recursively call until funds are released
mapping(address => mapping(uint256 => bool)) public operatorResponses;
bridgeRequestWeights
Tracks the total operator weight attested to a bridge request
Helpful for determining when enough attestations have been collected to release funds.
mapping(uint256 => uint256) public bridgeRequestWeights;
operatorWeights
Maps operator addresses to their respective weights
Temporary solution for illustrative purposes on non-mainnet chains
mapping(address => uint256) public operatorWeights;
Functions
constructor
Initializes the contract with the necessary parameters
constructor(uint256 _crankGasCost, uint256 _AVSReward, uint256 _bridgeFee, string memory _name, string memory _version)
Vault(_crankGasCost, _AVSReward, _bridgeFee, _name, _version);
Parameters
Name | Type | Description |
---|---|---|
_crankGasCost | uint256 | The estimated gas cost for calling release funds, used to calculate rebate and incentivize users to call |
_AVSReward | uint256 | The total reward for AVS attestation |
_bridgeFee | uint256 | The total fee charged to the user for bridging |
_name | string | The name of the contract, used for EIP-712 domain construction |
_version | string | The version of the contract, used for EIP-712 domain construction |
onlyOperator
Ensures that only operators with non-zero weight can call the function
modifier onlyOperator();
publishAttestation
Publishes an attestation for a bridge request
function publishAttestation(bytes memory attestation, uint256 _bridgeRequestId) public nonReentrant onlyOperator;
Parameters
Name | Type | Description |
---|---|---|
attestation | bytes | The signed attestation |
_bridgeRequestId | uint256 | The ID of the bridge request |
_releaseFunds
Releases funds to the destination address
function _releaseFunds(bytes memory data) public override nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
data | bytes | The bridge request data and signatures |
releaseFunds
Releases funds to the destination address with typed data for ABI construction
function releaseFunds(bytes[] memory signatures, Structs.BridgeRequestData memory data) public nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
signatures | bytes[] | The signatures of the operators attesting to the bridge request |
data | Structs.BridgeRequestData | The bridge request data |
operatorHasMinimumWeight
Checks if the operator has the minimum required weight
function operatorHasMinimumWeight(address operator) public view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | True if the operator has the minimum weight, false otherwise |
getOperatorWeight
Gets the weight of an operator
function getOperatorWeight(address operator) public view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator |
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The weight of the operator |
setOperatorWeight
Sets the weight of an operator
function setOperatorWeight(address operator, uint256 weight) public onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
operator | address | The address of the operator |
weight | uint256 | The new weight of the operator |
receive
Fallback function to receive ether
receive() external payable;
Structs
Contains struct definitions and related functions for bridge operations
Functions
hash
Computes the hash of the bridge request data
function hash(BridgeRequestData memory data) internal pure returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
data | BridgeRequestData | The bridge request data to be hashed |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | The hash of the given bridge request data |
Structs
BridgeRequestData
Structure representing bridge request data
struct BridgeRequestData {
address user;
address tokenAddress;
uint256 amountIn;
uint256 amountOut;
address destinationVault;
address destinationAddress;
uint256 transferIndex;
}
Properties
Name | Type | Description |
---|---|---|
user | address | The address of the user initiating the bridge request |
tokenAddress | address | The address of the token to be bridged |
amountIn | uint256 | The amount of tokens to be bridged |
amountOut | uint256 | The amount of tokens expected at the destination |
destinationVault | address | The address of the destination vault |
destinationAddress | address | The address of the recipient at the destination |
transferIndex | uint256 | The transfer index for unique tracking |
Vault
Inherits: ECDSAUtils, Events, ReentrancyGuard, OwnableUpgradeable
Abstract contract providing common vault functionality for bridge contracts
State Variables
nextUserTransferIndexes
Stores the transfer index for each user for unique transfer tracking
mapping(address => uint256) public nextUserTransferIndexes;
currentBridgeRequestId
Global unique bridge request ID
uint256 public currentBridgeRequestId;
bridgeRequests
Stores history of bridge requests
mapping(uint256 => Structs.BridgeRequestData) public bridgeRequests;
bridgeFee
Total fee charged to the user for bridging
uint256 public bridgeFee;
AVSReward
Total reward for AVS attestation
uint256 public AVSReward;
crankGasCost
Estimated gas cost for calling release funds, used to calculate rebate and incentivize users to call
uint256 public crankGasCost;
deployer
Address of the contract deployer
address deployer;
Functions
constructor
Initializes the contract with the necessary parameters
constructor(uint256 _crankGasCost, uint256 _AVSReward, uint256 _bridgeFee, string memory _name, string memory _version)
ECDSAUtils(_name, _version);
Parameters
Name | Type | Description |
---|---|---|
_crankGasCost | uint256 | The estimated gas cost for calling release funds, used to calculate rebate and incentivize users to call |
_AVSReward | uint256 | The total reward for AVS attestation |
_bridgeFee | uint256 | The total fee charged to the user for bridging |
_name | string | The name of the contract, used for EIP-712 domain construction |
_version | string | The version of the contract, used for EIP-712 domain construction |
initialize
Initializes the contract and transfers ownership to the deployer
function initialize() public initializer;
setBridgeFee
Sets the bridge fee
function setBridgeFee(uint256 _bridgeFee) external onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
_bridgeFee | uint256 | The new bridge fee |
setAVSReward
Sets the AVS reward
function setAVSReward(uint256 _AVSReward) external onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
_AVSReward | uint256 | The new AVS reward |
setCrankGasCost
Sets the crank gas cost
function setCrankGasCost(uint256 _crankGasCost) external onlyOwner;
Parameters
Name | Type | Description |
---|---|---|
_crankGasCost | uint256 | The new crank gas cost |
bridgeERC20
Internal function to transfer ERC20 tokens for bridging
function bridgeERC20(address tokenAddress, uint256 amountIn) internal;
Parameters
Name | Type | Description |
---|---|---|
tokenAddress | address | The address of the token to be transferred |
amountIn | uint256 | The amount of tokens to be transferred |
bridge
Initiates a bridge request
function bridge(
address tokenAddress,
uint256 amountIn,
uint256 amountOut,
address destinationVault,
address destinationAddress
) public payable nonReentrant;
Parameters
Name | Type | Description |
---|---|---|
tokenAddress | address | The address of the token to be bridged |
amountIn | uint256 | The amount of tokens to be bridged |
amountOut | uint256 | The amount of tokens expected at the destination |
destinationVault | address | The address of the destination vault |
destinationAddress | address | The address of the recipient at the destination |
_releaseFunds
Abstract function to release funds, to be implemented by inheriting contracts
function _releaseFunds(bytes memory data) public virtual;
Parameters
Name | Type | Description |
---|---|---|
data | bytes | The bridge request data and signatures |