Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
bd3632f
added PolymerCCTPFacet + deploy scripts, docs, etc.
0xDEnYO Nov 10, 2025
33923d2
deployed to ARB/OPT staging
0xDEnYO Nov 10, 2025
8328e43
added demoscript (not yet finalized)
0xDEnYO Nov 10, 2025
4ca412a
update config
0xDEnYO Nov 12, 2025
bb6e94b
update deploy scripts to expect polymerFeeReceiver to be an EOA
0xDEnYO Nov 13, 2025
8ad7765
remove BSC from supported destination chains
0xDEnYO Nov 13, 2025
6310451
add calls to Polymer quote API to demoscript
0xDEnYO Nov 13, 2025
d3acf5f
rename TokenMessenger to TokenMessengerV2
0xDEnYO Nov 13, 2025
14c52fe
adjust docs
0xDEnYO Nov 13, 2025
2d1848e
rename TokenMessenger in test case
0xDEnYO Nov 13, 2025
15b0678
Merge branch 'main' of github.com:lifinance/contracts into polymer-cc…
0xDEnYO Nov 14, 2025
d9a2c3b
add testnet API
0xDEnYO Nov 14, 2025
b6f0dce
update demoScript and create helper function to log bridgeDataStruct
0xDEnYO Nov 18, 2025
b1e7618
Merge branch 'main' of github.com:lifinance/contracts into polymer-cc…
0xDEnYO Nov 18, 2025
f371607
remove bsc from config and todo comments from facet
0xDEnYO Nov 18, 2025
248dd3d
add comment in config file
0xDEnYO Nov 18, 2025
4404861
remove Polymer zksync scripts (zksync not supported)
0xDEnYO Nov 18, 2025
2393371
reorder modifiers and add onlyAllowSourceToken to swapAnd.. function
0xDEnYO Nov 18, 2025
150ae80
removed payable and refundExcessNative modifier from startBridge.. fu…
0xDEnYO Nov 18, 2025
e6bd1db
removed unused error
0xDEnYO Nov 18, 2025
605f7e1
removed ethers from demoscript
0xDEnYO Nov 19, 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
99 changes: 99 additions & 0 deletions config/polymercctp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"Note: Networks with missing polymerFeeReceiver are not supported by Polymer yet and will be added later": {},
"mainnet": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"arbitrum": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"avalanche": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"base": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"hyperevm": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
"polymerFeeReceiver": ""
},
"ink": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x2D270e6886d130D724215A266106e6832161EAEd",
"polymerFeeReceiver": ""
},
"linea": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x176211869cA2b568f2A7D4EE941E073a821EE1ff",
"polymerFeeReceiver": ""
},
"optimism": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"plume": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x222365EF19F7947e5484218551B56bb3965Aa7aF",
"polymerFeeReceiver": ""
},
"polygon": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"sei": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392",
"polymerFeeReceiver": ""
},
"sonic": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x29219dd400f2Bf60E5a23d13Be72B486D4038894",
"polymerFeeReceiver": ""
},
"unichain": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x078D782b760474a361dDA0AF3839290b0EF57AD6",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"worldchain": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0x79A02482A880bCe3F13E09da970dC34dB4cD24D1",
"polymerFeeReceiver": ""
},
"xdc": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
"polymerFeeReceiver": ""
},
"---------- TEST NETWORKS -----------": {},
"arbitrumSepolia": {
"tokenMessengerV2": "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA",
"usdc": "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
"polymerFeeReceiver": "0x3d1ed7307Ee6dEB2e1cEA9D96C33574fA2a35Bb6"
},
"baseSepolia": {
"tokenMessengerV2": "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA",
"usdc": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"polymerFeeReceiver": "0x3d1ed7307Ee6dEB2e1cEA9D96C33574fA2a35Bb6"
},
"optimismSepolia": {
"tokenMessengerV2": "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA",
"usdc": "0x5fd84259d66Cd46123540766Be93DFE6D43130D7",
"polymerFeeReceiver": "0x3d1ed7307Ee6dEB2e1cEA9D96C33574fA2a35Bb6"
},
"sepolia": {
"tokenMessengerV2": "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA",
"usdc": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
"polymerFeeReceiver": "0x3d1ed7307Ee6dEB2e1cEA9D96C33574fA2a35Bb6"
}
}
32 changes: 32 additions & 0 deletions deployments/_deployments_log_file.json
Original file line number Diff line number Diff line change
Expand Up @@ -45763,6 +45763,38 @@
]
}
}
},
"PolymerCCTPFacet": {
"optimism": {
"staging": {
"1.0.0": [
{
"ADDRESS": "0x9ae70675f7d99231A6f917CA36F45c03a17F0417",
"OPTIMIZER_RUNS": "1000000",
"TIMESTAMP": "2025-11-10 12:41:26",
"CONSTRUCTOR_ARGS": "0x00000000000000000000000028b5a0e9c621a5badaa536219b3a228c8168cf5d0000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000002b2c52b1b63c4bfc7f1a310a1734641d8e34de62",
"SALT": "",
"VERIFIED": "false",
"ZK_SOLC_VERSION": ""
}
]
}
},
"arbitrum": {
"staging": {
"1.0.0": [
{
"ADDRESS": "0x9ae70675f7d99231A6f917CA36F45c03a17F0417",
"OPTIMIZER_RUNS": "1000000",
"TIMESTAMP": "2025-11-10 12:41:58",
"CONSTRUCTOR_ARGS": "0x00000000000000000000000028b5a0e9c621a5badaa536219b3a228c8168cf5d000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000002b2c52b1b63c4bfc7f1a310a1734641d8e34de62",
"SALT": "",
"VERIFIED": "false",
"ZK_SOLC_VERSION": ""
}
]
}
}
}
}
}
35 changes: 34 additions & 1 deletion deployments/arbitrum.diamond.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,50 @@
"0x004E291b9244C811B0BE00cA2C179d54FAA5073D": {
"Name": "RelayDepositoryFacet",
"Version": "1.0.0"
},
"0xdaD5da5FB53EAe15f490Fb31F4573e56277b59CA": {
"Name": "",
"Version": ""
},
"0xaA1E88f4D0cb0a798f1FeBAfc8fAb4778629D4e7": {
"Name": "",
"Version": ""
},
"0x33EcEb68994E0499a61FAda3b49Ab243e63555F1": {
"Name": "",
"Version": ""
},
"0x7Ea86FE59Ab35d76ba2446b09104A52E95d3267e": {
"Name": "DexManagerFacet",
"Version": "1.0.1"
},
"0x4582FD200173F1717F6C53fD1531b2F6fE33Fe3D": {
"Name": "",
"Version": ""
},
"0xb3B9C1d75bCc95bcD07F0c45c50A72A513FF8515": {
"Name": "",
"Version": ""
},
"0xD9C95865a8a25614B4bbb77b1b55fa0bF207D7c2": {
"Name": "",
"Version": ""
},
"0x9ae70675f7d99231A6f917CA36F45c03a17F0417": {
"Name": "PolymerCCTPFacet",
"Version": "1.0.0"
}
},
"Periphery": {
"ERC20Proxy": "0xF6d5cf7a12d89BC0fD34E27d2237875b564A6ADf",
"Executor": "0x23f882bA2fa54A358d8599465EB471f58Cc26751",
"FeeCollector": "0x7F8E9bEBd1Dea263A36a6916B99bd84405B9654a",
"FeeForwarder": "",
"GasZipPeriphery": "",
"LidoWrapper": "",
"LiFiDEXAggregator": "",
"Patcher": "0x3971A968c03cd9640239C937F8d30D024840E691",
"Permit2Proxy": "0xb33Fe241BEd9bf5F694101D7498F63a0d060F999",
"Permit2Proxy": "0x104BD390Fed41089650Ac14aC6D9a8F3513A04cf",
"ReceiverAcrossV3": "0xe4F3DEF14D61e47c696374453CD64d438FD277F8",
"ReceiverAcrossV4": "0x8fd9e1893fdE2e52b49F2875E63277Ba5675D014",
"ReceiverChainflip": "",
Expand Down
3 changes: 2 additions & 1 deletion deployments/arbitrum.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@
"ReceiverAcrossV4": "0x8fd9e1893fdE2e52b49F2875E63277Ba5675D014",
"AcrossFacetPackedV4": "0xf536ed5A4310455FF39dBf90336e17d11550E7b4",
"Patcher": "0x18069208cA7c2D55aa0073E047dD45587B26F6D4",
"RelayDepositoryFacet": "0x004E291b9244C811B0BE00cA2C179d54FAA5073D"
"RelayDepositoryFacet": "0x004E291b9244C811B0BE00cA2C179d54FAA5073D",
"PolymerCCTPFacet": "0x9ae70675f7d99231A6f917CA36F45c03a17F0417"
}
6 changes: 5 additions & 1 deletion deployments/optimism.diamond.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
"0x2A6DB28EEe8d006d4F0781b57af3B24603b65A70": {
"Name": "WhitelistManagerFacet",
"Version": "1.0.0"
},
"0x9ae70675f7d99231A6f917CA36F45c03a17F0417": {
"Name": "PolymerCCTPFacet",
"Version": "1.0.0"
}
},
"Periphery": {
Expand All @@ -75,4 +79,4 @@
"TokenWrapper": "0xF63b27AE2Dc887b88f82E2Cc597d07fBB2E78E70"
}
}
}
}
3 changes: 2 additions & 1 deletion deployments/optimism.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@
"AcrossFacetV4": "0x91559A75bd9045681265C77922b3cAeDB3D5120d",
"ReceiverAcrossV4": "0x1d5bD612Ce761060A4bEd77b606ab7e723D4E91E",
"AcrossFacetPackedV4": "0xf536ed5A4310455FF39dBf90336e17d11550E7b4",
"WhitelistManagerFacet": "0x2A6DB28EEe8d006d4F0781b57af3B24603b65A70"
"WhitelistManagerFacet": "0x2A6DB28EEe8d006d4F0781b57af3B24603b65A70",
"PolymerCCTPFacet": "0x9ae70675f7d99231A6f917CA36F45c03a17F0417"
}
101 changes: 101 additions & 0 deletions docs/PolymerCCTPFacet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Polymer CCTP Facet

Polymer CCTP Facet provides functionality for bridging USDC through Polymer's CCTP (Cross-Chain Transfer Protocol) integration. CCTP is a permissionless on-chain utility that can burn native USDC on a source chain and mint native USDC of the same amount on a destination chain.

## How it works

The Polymer CCTP Facet works by forwarding transfers directly to Polymer's TokenMessenger contract, which is an implementation of Circle's CCTP protocol. The facet handles USDC transfers and supports both EVM and non-EVM destination chains.

```mermaid
graph LR;
D{LiFiDiamond}-- DELEGATECALL -->PolymerCCTPFacet;
PolymerCCTPFacet -- CALL --> TM(TokenMessenger)
```

## Public Methods

- `function startBridgeTokensViaPolymerCCTP(BridgeData memory _bridgeData, PolymerCCTPData calldata _polymerData)`
- Simply bridges USDC using Polymer CCTP
- `function swapAndStartBridgeTokensViaPolymerCCTP(BridgeData memory _bridgeData, SwapData[] calldata _swapData, PolymerCCTPData calldata _polymerData)`
- Performs swap(s) before bridging USDC using Polymer CCTP

## Polymer CCTP Specific Parameters

The methods listed above take a variable labeled `_polymerData`. This data is specific to Polymer CCTP and is represented as the following struct type:

```solidity
struct PolymerCCTPData {
// Token fee taken in USDC by the facet (optional; should be zero for slow path )
uint256 polymerTokenFee;
// maximum fee to paid on the destination domain through the difference between burned tokens on src chain and minted token on dest chain, specified in units of burnToken
uint256 maxCCTPFee;
// Should only be nonzero if submitting to a nonEVM chain
bytes32 nonEVMReceiver;
// the minimum finality at which a burn message will be attested to, will be passed directly to tokenMessenger.depositForBurn method.
// 1000 = fast path, 2000 = standard path
uint32 minFinalityThreshold;
}
```

## 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: 'polymercctp', // 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 20 USDC on Ethereum to USDC on Base you can execute the following request:

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

### Swap & Cross

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

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