Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
7a62df2
config: whitelist new OKX contract
mathiasmoeller Aug 25, 2025
7144e4e
bootstrap
ezynda3 Aug 25, 2025
300f188
real fork test
ezynda3 Aug 26, 2025
38e383f
refactor
ezynda3 Aug 27, 2025
1d74e8b
deploy to staging
ezynda3 Aug 27, 2025
d045ad9
simple demo
ezynda3 Aug 27, 2025
12b2a21
fix
ezynda3 Aug 27, 2025
abfcb1d
docs
ezynda3 Aug 27, 2025
9265a47
revert
ezynda3 Aug 27, 2025
581bac1
update
ezynda3 Aug 27, 2025
b1ff9d1
fix tests
ezynda3 Aug 27, 2025
5267d2c
redeploy to staging + update demo script
ezynda3 Aug 27, 2025
acd28da
update demo script
ezynda3 Aug 29, 2025
4129082
Merge branch 'main' of github.com:lifinance/contracts into LF-14918-E…
ezynda3 Sep 11, 2025
2630da7
update contract, test, demo to work with updated Eco interface
ezynda3 Sep 11, 2025
1d7d661
redeploy to staging and update demo
ezynda3 Sep 11, 2025
40d63fe
Upgrade EcoFacet to use Portal V2 contract (#1379)
carlosfebres Sep 16, 2025
d5765bb
conflicts
ezynda3 Sep 16, 2025
fac7bef
Merge branch 'main' of github.com:lifinance/contracts into LF-14918-E…
ezynda3 Sep 16, 2025
3fc361d
update demo script
ezynda3 Sep 16, 2025
2698753
handle solana
ezynda3 Sep 16, 2025
9997cd5
add swap demo
ezynda3 Sep 17, 2025
7fd3fe7
Merge branch 'main' into LF-14918-Eco-Facet
ezynda3 Sep 17, 2025
4fdaf57
update docs
ezynda3 Sep 17, 2025
2b7bc42
update constants
ezynda3 Sep 17, 2025
811282d
boost coverage
ezynda3 Sep 17, 2025
d122c06
update
ezynda3 Sep 17, 2025
a397da1
update
ezynda3 Sep 17, 2025
19147bb
fix: address PR review comments for EcoFacet
ezynda3 Sep 18, 2025
4bc4cf2
validate
ezynda3 Sep 21, 2025
9155e02
validate
ezynda3 Sep 21, 2025
1c093fe
cleanup
ezynda3 Sep 22, 2025
16edd39
verify solana
ezynda3 Sep 22, 2025
a770146
update portal
ezynda3 Sep 22, 2025
531129f
fix: improve Solana recipient extraction from Borsh-encoded routes (#…
carlosfebres Sep 23, 2025
5e981e7
update to properly validate
ezynda3 Sep 23, 2025
b7c793a
Merge branch 'LF-14918-Eco-Facet' of github.com:lifinance/contracts i…
ezynda3 Sep 23, 2025
82d9d5f
fix
ezynda3 Sep 24, 2025
1e10a72
Merge branch 'main' into LF-14918-Eco-Facet
ezynda3 Sep 24, 2025
9146f94
update docs
ezynda3 Sep 24, 2025
06385fb
update tests
ezynda3 Sep 24, 2025
62c430e
fix
ezynda3 Sep 24, 2025
40be564
fix coverage
ezynda3 Sep 24, 2025
92547fc
validate ATA vs solana address
ezynda3 Sep 24, 2025
39b7daa
Update script/demoScripts/demoEco.ts
ezynda3 Sep 25, 2025
839f548
Merge branch 'main' into LF-14918-Eco-Facet
ezynda3 Sep 25, 2025
61b8061
eliminate redundant checks
ezynda3 Sep 30, 2025
c5259e4
remove useless internal func
ezynda3 Sep 30, 2025
3614694
update docs
ezynda3 Sep 30, 2025
acc7520
remove changelog
ezynda3 Sep 30, 2025
644d9de
fixes
ezynda3 Sep 30, 2025
f1b2678
update helper func names
ezynda3 Sep 30, 2025
ecc2d09
validate solana dst against NON_EVM_RECEIVER
ezynda3 Sep 30, 2025
aac20d8
document known issue with positive slippage
ezynda3 Sep 30, 2025
85a99c7
update tests
ezynda3 Sep 30, 2025
15f5101
optimizations
ezynda3 Sep 30, 2025
5745732
redeploy to staging
ezynda3 Sep 30, 2025
62fe5c9
add clarification
ezynda3 Sep 30, 2025
aa85867
remove
ezynda3 Oct 1, 2025
d2c99d4
combine helpers
ezynda3 Oct 1, 2025
c323eeb
remove extra checks
ezynda3 Oct 1, 2025
4b5fb4d
refactor
ezynda3 Oct 1, 2025
f6b2ab9
remove native token support
ezynda3 Oct 1, 2025
8d0e66a
Merge branch 'main' into LF-14918-Eco-Facet
ezynda3 Oct 1, 2025
ca999e8
fix: reject NON_EVM_ADDRESS for non-Solana destinations
ezynda3 Oct 6, 2025
8ee81f6
fix: prevent native token loss and refund excess
ezynda3 Oct 6, 2025
94b00df
fix: add lower bound validation for Solana address length
ezynda3 Oct 6, 2025
0c8f825
fix: validate prover and rewardDeadline parameters
ezynda3 Oct 6, 2025
e3249ef
fix: emit BridgeToNonEVMChain only for Solana destinations
ezynda3 Oct 6, 2025
50e26d5
refactor: inline depositAmount calculation for gas savings
ezynda3 Oct 6, 2025
dd905c0
refactor: replace magic numbers with named constants
ezynda3 Oct 6, 2025
82fbf2b
refactor: remove redundant explicit zero value in portal call
ezynda3 Oct 6, 2025
967d424
refactor: remove redundant receiverAddress from EcoData
ezynda3 Oct 6, 2025
29c9af4
fix: update demoEco.ts to use new EcoData structure
ezynda3 Oct 6, 2025
5bc35be
redeploy to staging
ezynda3 Oct 6, 2025
3ec6f57
add inline doc about native refunds
ezynda3 Oct 8, 2025
68e1008
fix typo
ezynda3 Oct 8, 2025
d8a2390
redeploy to staging
ezynda3 Oct 9, 2025
a391b5a
update internal calculations to deduct fee from passed minAmount
ezynda3 Oct 10, 2025
1bc03bc
remove unneeded var
ezynda3 Oct 10, 2025
cc74e99
Merge branch 'main' of github.com:lifinance/contracts into LF-14918-E…
ezynda3 Oct 10, 2025
f45a34a
chore: add EcoFacet and IEcoPortal v1.0.0 audit entry
ezynda3 Oct 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config/eco.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"optimism": {
"portal": "0x90F0c8aCC1E083Bcb4F487f84FC349ae8d5e28D7"
},
"base": {
"portal": "0x90F0c8aCC1E083Bcb4F487f84FC349ae8d5e28D7"
}
}
17 changes: 17 additions & 0 deletions deployments/_deployments_log_file.json
Original file line number Diff line number Diff line change
Expand Up @@ -39125,5 +39125,22 @@
]
}
}
},
"EcoFacet": {
"optimism": {
"staging": {
"1.0.0": [
{
"ADDRESS": "0xc4884225aeFe7218f9f489A5Eb8beB504ab272AA",
"OPTIMIZER_RUNS": "1000000",
"TIMESTAMP": "2025-08-27 11:52:17",
"CONSTRUCTOR_ARGS": "0x00000000000000000000000090f0c8acc1e083bcb4f487f84fc349ae8d5e28d7",
"SALT": "",
"VERIFIED": "false",
"ZK_SOLC_VERSION": ""
}
]
}
}
}
}
31 changes: 24 additions & 7 deletions deployments/optimism.diamond.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
"Name": "CelerCircleBridgeFacet",
"Version": "1.0.1"
},
"0x2Af20933E5886aFe275c0EEE4A2e65daA4E8b169": {
"Name": "CelerIMFacetMutable",
"Version": ""
},
"0x380157643592725677F165b67642448CDCAeE026": {
"Name": "HopFacet",
"Version": "2.0.0"
Expand Down Expand Up @@ -114,8 +118,8 @@
"Version": ""
},
"0x6124C65B6264bE13f059b7C3A891a5b77DA8Bd95": {
"Name": "AcrossFacetV3",
"Version": "1.0.0"
"Name": "",
"Version": ""
},
"0x4352459F6BE1C7D1278F8c34Bb598b0feeB50f8b": {
"Name": "AcrossFacetPackedV3",
Expand All @@ -141,17 +145,29 @@
"Name": "GasZipFacet",
"Version": "2.0.4"
},
"0xc2A0D799744536C621Af9B2933CdB4Ad959980bF": {
"Name": "AcrossFacetV4",
"Version": "1.0.0"
"0x91559A75bd9045681265C77922b3cAeDB3D5120d": {
"Name": "",
"Version": ""
},
"0x8962d191Ba0f2Bc29b949ACA222f8251B241190b": {
"Name": "AcrossFacetPackedV4",
"Version": "1.0.0"
"Name": "",
"Version": ""
},
"0x36e1375B0755162d720276dFF6893DF02bd49225": {
"Name": "GlacisFacet",
"Version": "1.1.0"
},
"0x0f4D0D8890bAF9036D3895315559a6F0d573e2EC": {
"Name": "",
"Version": ""
},
"0x59A1Bcaa32EdB1a233fEF945857529BBD6df247f": {
"Name": "",
"Version": ""
},
"0xc4884225aeFe7218f9f489A5Eb8beB504ab272AA": {
"Name": "EcoFacet",
"Version": "1.0.0"
}
},
"Periphery": {
Expand All @@ -161,6 +177,7 @@
"GasZipPeriphery": "",
"LidoWrapper": "",
"LiFiDEXAggregator": "",
"Patcher": "",
"Permit2Proxy": "0x808eb38763f3F51F9C47bc93Ef8d5aB7E6241F46",
"ReceiverAcrossV3": "0x3877f47B560819E96BBD7e7700a02dfACe36D696",
"ReceiverChainflip": "",
Expand Down
3 changes: 2 additions & 1 deletion deployments/optimism.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
"LidoWrapper": "0x462A9B6879770050021823D63aE62470E65Af8D4",
"Permit2Proxy": "0x808eb38763f3F51F9C47bc93Ef8d5aB7E6241F46",
"GasZipFacet": "0xfEeCe7B3e68B9cBeADB60598973704a776ac3ca1",
"GlacisFacet": "0x36e1375B0755162d720276dFF6893DF02bd49225"
"GlacisFacet": "0x36e1375B0755162d720276dFF6893DF02bd49225",
"EcoFacet": "0xc4884225aeFe7218f9f489A5Eb8beB504ab272AA"
}
118 changes: 118 additions & 0 deletions docs/EcoFacet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Eco Facet

## How it works

The Eco Facet enables cross-chain token transfers using the Eco Protocol's intent-based bridging system. It creates an intent that specifies the desired outcome on the destination chain, which solvers then fulfill in exchange for a reward. The facet supports both EVM and non-EVM destination chains, as well as optional destination calls for complex cross-chain workflows.

```mermaid
graph LR;
D{LiFiDiamond}-- DELEGATECALL -->EcoFacet;
EcoFacet -- CALL --> EcoPortal[Eco Portal]
```

## Public Methods

- `function startBridgeTokensViaEco(BridgeData calldata _bridgeData, EcoData calldata _ecoData)`
- Bridges tokens using Eco Protocol without performing any swaps
- `swapAndStartBridgeTokensViaEco(BridgeData memory _bridgeData, LibSwap.SwapData[] calldata _swapData, EcoData memory _ecoData)`
- Performs swap(s) before bridging tokens using Eco Protocol

## Eco Specific Parameters

The methods listed above take a variable labeled `_ecoData`. This data is specific to Eco Protocol and is represented as the following struct type:

```solidity
/// @dev Eco specific parameters
/// @param receiverAddress Address that will receive tokens on destination chain
/// @param nonEVMReceiver Destination address for non-EVM chains (bytes format)
/// @param receivingAssetId Address of the token to receive on destination
/// @param salt Unique identifier for the intent (prevents duplicates)
/// @param routeDeadline Timestamp by which route must be executed
/// @param destinationPortal Portal address on destination chain
/// @param prover Address of the prover contract for validation
/// @param rewardDeadline Timestamp for reward claim eligibility
/// @param solverReward Native token amount to reward the solver
/// @param destinationCalls Optional calls to execute on destination
struct EcoData {
address receiverAddress;
bytes nonEVMReceiver;
address receivingAssetId;
bytes32 salt;
uint64 routeDeadline;
address destinationPortal;
address prover;
uint64 rewardDeadline;
uint256 solverReward;
IEcoPortal.Call[] destinationCalls;
}
```

### Important Notes

- **Solver Reward**: The `solverReward` must be sent as `msg.value` with the transaction. This incentivizes solvers to fulfill the intent on the destination chain.
- **Non-EVM Destinations**: For non-EVM chains, set `receiver` in `BridgeData` to `NON_EVM_ADDRESS` (inherit from src/Helpers/LiFiData.sol) and provide the destination address in `nonEVMReceiver`.
- **Native Token Bridging**: When bridging native tokens, the bridge amount plus the solver reward must be sent as `msg.value`.
- **Token Approvals**: For ERC20 tokens, the facet will automatically approve the Eco Portal to spend the required amount.

## Swap Data

Some methods accept a `SwapData _swapData` parameter.

Swapping is performed by a swap specific library that expects an array of calldata to can be run on various DEXs (i.e. Uniswap) to make one or multiple swaps before performing another action.

The swap library can be found [here](../src/Libraries/LibSwap.sol).

## LiFi Data

Some methods accept a `BridgeData _bridgeData` parameter.

This parameter is strictly for analytics purposes. It's used to emit events that we can later track and index in our subgraphs and provide data on how our contracts are being used. `BridgeData` and the events we can emit can be found [here](../src/Interfaces/ILiFi.sol).

## Getting Sample Calls to interact with the Facet

In the following some sample calls are shown that allow you to retrieve a populated transaction that can be sent to our contract via your wallet.

All examples use our [/quote endpoint](https://apidocs.li.fi/reference/get_quote) to retrieve a quote which contains a `transactionRequest`. This request can directly be sent to your wallet to trigger the transaction.

The quote result looks like the following:

```javascript
const quoteResult = {
id: '0x...', // quote id
type: 'lifi', // the type of the quote (all lifi contract calls have the type "lifi")
tool: 'eco', // the bridge tool used for the transaction
action: {}, // information about what is going to happen
estimate: {}, // information about the estimated outcome of the call
includedSteps: [], // steps that are executed by the contract as part of this transaction, e.g. a swap step and a cross step
transactionRequest: {
// the transaction that can be sent using a wallet
data: '0x...',
to: '0x...',
value: '0x00',
from: '{YOUR_WALLET_ADDRESS}',
chainId: 100,
gasLimit: '0x...',
gasPrice: '0x...',
},
}
```

A detailed explanation on how to use the /quote endpoint and how to trigger the transaction can be found [here](https://docs.li.fi/products/more-integration-options/li.fi-api/transferring-tokens-example).

**Hint**: Don't forget to replace `{YOUR_WALLET_ADDRESS}` with your real wallet address in the examples.

### Cross Only

To get a transaction for a transfer from 5 USDC on Optimism to USDC on Base you can execute the following request:

```shell
curl 'https://li.quest/v1/quote?fromChain=OPT&fromAmount=5000000&fromToken=USDC&toChain=BAS&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
```

### Swap & Cross

To get a transaction for a transfer from 5 USDT on Optimism to USDC on Base you can execute the following request:

```shell
curl 'https://li.quest/v1/quote?fromChain=OPT&fromAmount=5000000&fromToken=USDT&toChain=BAS&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
```
Loading