Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d99d926
prepare deployment for arc testnet
0xDEnYO Mar 5, 2026
285a1ab
deployed core setup
0xDEnYO Mar 5, 2026
fa9ca22
script fixes
0xDEnYO Mar 5, 2026
64dd968
adds custom handling for missing feePayer error
0xDEnYO Mar 5, 2026
d8ec7bf
deployed LiFiIntentEscrowFacet
0xDEnYO Mar 9, 2026
4f8569e
Merge branch 'main' of github.com:lifinance/contracts into deploy-net…
0xDEnYO Mar 9, 2026
e956e5d
remove fake private key to silence pre-commit warning
0xDEnYO Mar 9, 2026
6568355
Merge branch 'main' of github.com:lifinance/contracts into deploy-net…
0xDEnYO Mar 25, 2026
b7c1a01
update config
0xDEnYO Mar 25, 2026
d5ac8c6
deploy PolymerFacet
0xDEnYO Mar 25, 2026
93cee3c
Merge branch 'main' of github.com:lifinance/contracts into deploy-net…
0xDEnYO Mar 26, 2026
60c4753
diamond log updated
0xDEnYO Mar 26, 2026
fc1aca6
Merge branch 'main' of github.com:lifinance/contracts into deploy-net…
0xDEnYO Mar 26, 2026
8a83da5
added arc testnet to PolymerCCTPFacet
0xDEnYO Mar 26, 2026
a810cb7
deployed updated PolymerCCTPFacet (with arc testnet support) to optim…
0xDEnYO Mar 26, 2026
ffd7f46
update diamond log
0xDEnYO Mar 30, 2026
e3dfad9
Merge branch 'deploy-network-arc-testnet' of github.com:lifinance/con…
0xDEnYO Mar 30, 2026
3bafeaf
Merge branch 'main' of github.com:lifinance/contracts into deploy-net…
0xDEnYO Mar 30, 2026
80c0548
Add missing Polymer chain id mappings. Used for testing.
gvladika Mar 30, 2026
cd405fc
arctestnet logs updates after new PolymerCCTPFacet update
mirooon Mar 30, 2026
47aa041
Merge branch 'main' into deploy-network-arc-testnet
mirooon Mar 31, 2026
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
21 changes: 21 additions & 0 deletions config/networks.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,27 @@
"deployedWithSolcVersion": "0.8.29",
"create3Factory": "0xDe367507f70A1f57a7203bD7A88ced24A79fb53d"
},
"arctestnet": {
"name": "arctestnet",
"chainId": 5042002,
"nativeAddress": "0x3600000000000000000000000000000000000000",
"nativeCurrency": "USDC",
"wrappedNativeAddress": "0x0000000000000000000000000000000000000001",
"status": "active",
"type": "testnet",
"rpcUrl": "https://rpc.testnet.arc.network/",
"verificationType": "blockscout",
"explorerUrl": "https://testnet.arcscan.app",
"explorerApiUrl": "https://testnet.arcscan.app/api",
"multicallAddress": "0xca11bde05977b3631167028862be2a173976ca11",
"safeAddress": "0x74FF5a888bcBf6dA92b57acc2690F95763728b66",
"gasZipChainId": 0,
"isZkEVM": false,
"deployedWithEvmVersion": "cancun",
"deployedWithSolcVersion": "0.8.29",
"create3Factory": "0xDe367507f70A1f57a7203bD7A88ced24A79fb53d",
"castSendAsync": true
},
"avalanche": {
"name": "avalanche",
"chainId": 43114,
Expand Down
1 change: 1 addition & 0 deletions config/permit2Proxy.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"apechain": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"arbitrum": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"arbitrumnova": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"arctestnet": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"aurora": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"avalanche": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"base": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
Expand Down
6 changes: 6 additions & 0 deletions config/polymercctp.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"Note: Networks with missing polymerFeeReceiver are not supported by Polymer yet and will be added later": {},
"addresses for tokenMessengerV2 can be found here: https://developers.circle.com/cctp/references/contract-addresses": {},
"mainnet": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
Expand All @@ -10,6 +11,11 @@
"usdc": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"arctestnet": {
"tokenMessengerV2": "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA",
"usdc": "0x3600000000000000000000000000000000000000",
"polymerFeeReceiver": "0x64ED4dE33769349F8C4bD6e8d1866f19D29bef79"
},
"avalanche": {
"tokenMessengerV2": "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d",
"usdc": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
Expand Down
40 changes: 40 additions & 0 deletions config/whitelist.json
Original file line number Diff line number Diff line change
Expand Up @@ -5182,6 +5182,46 @@
]
}
],
"arctestnet": [
{
"name": "FeeCollector",
"address": "0x949343d563394016CE0c52bB6511DFE5aEec8e8a",
"selectors": [
{
"selector": "0xe0cbc5f2",
"signature": "collectNativeFees(uint256,uint256,address)"
},
{
"selector": "0xeedd56e1",
"signature": "collectTokenFees(address,uint256,uint256,address)"
}
]
},
{
"name": "FeeForwarder",
"address": "0xD23FB66108971325f302bF0f209216D705adF987",
"selectors": [
{
"selector": "0x0e8ae67f",
"signature": "forwardNativeFees((address,uint256)[])"
},
{
"selector": "0x332d746b",
"signature": "forwardERC20Fees(address,(address,uint256)[])"
}
]
},
{
"name": "LiFiDEXAggregator",
"address": "0x3089b3b207E051b2c035c6163874732a18F28bbd",
"selectors": [
{
"selector": "0x2646478b",
"signature": "processRoute(address,uint256,address,uint256,address,bytes)"
}
]
}
],
"arbitrumnova": [
{
"name": "FeeCollector",
Expand Down
75 changes: 75 additions & 0 deletions deployments/arctestnet.diamond.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"LiFiDiamond": {
"Facets": {
"0x81Aa26F9c9b9d5DE24b61b36dD602da7755aC769": {
"Name": "DiamondCutFacet",
"Version": "1.0.0"
},
"0xe60F67d9963977C929eF6Dc465c9874290F746aa": {
"Name": "DiamondLoupeFacet",
"Version": "1.0.0"
},
"0x037E643C2ABf0A065eB19554b096CFc11328de33": {
"Name": "AccessManagerFacet",
"Version": "1.0.0"
},
"0xe44bd998661194534CAAEa44dAb7512e7Fc11D52": {
"Name": "CalldataVerificationFacet",
"Version": "1.3.1"
},
"0xF610Ad5028e9ac3b0E3bBF0761d3EFae994F341e": {
"Name": "EmergencyPauseFacet",
"Version": "1.0.1"
},
"0xCC66A5dBcD2528E93FFA515a849132e9C3F2F5A2": {
"Name": "GenericSwapFacet",
"Version": "1.0.0"
},
"0xbc140b5ecE539c2A73878badC5014F33F5fe0d83": {
"Name": "GenericSwapFacetV3",
"Version": "1.0.2"
},
"0x23Abcd6a3B11A161B044EEe5448ACc1c71a280A0": {
"Name": "OwnershipFacet",
"Version": "1.0.0"
},
"0xffdF032efC87a5ae95a133637d8F10A5C8e9AC0c": {
"Name": "PeripheryRegistryFacet",
"Version": "1.0.0"
},
"0xb0AF986eACb968B7bf0116C0AC1769D47E97cb40": {
"Name": "WhitelistManagerFacet",
"Version": "1.1.0"
},
"0xf8c32B42ddA2CEE4085Bb762FaaA83f34FE6Ad7A": {
"Name": "WithdrawFacet",
"Version": "1.0.0"
},
"0x71e7fF4A8186CC3DA73e39BFd918Bb27DFb688c2": {
"Name": "LiFiIntentEscrowFacet",
"Version": "1.0.1"
},
"0x9a01A05F3Ce4B36c88bfE40F546D4F856B177875": {
"Name": "PolymerCCTPFacet",
"Version": "2.0.1"
}
},
"Periphery": {
"ERC20Proxy": "0x27139fC566d78e743Fb8B0E845069676DaA94aEd",
"Executor": "0x7e0fD1839BC95c2F91E6934e823EA4C30F48DAD2",
"FeeCollector": "0x949343d563394016CE0c52bB6511DFE5aEec8e8a",
"FeeForwarder": "0xD23FB66108971325f302bF0f209216D705adF987",
"GasZipPeriphery": "",
"LiFiDEXAggregator": "0x3089b3b207E051b2c035c6163874732a18F28bbd",
"LidoWrapper": "",
"Patcher": "",
"Permit2Proxy": "0x36C800D4472fBb888D034Aa74778f481aEE01FEc",
"ReceiverAcrossV3": "",
"ReceiverAcrossV4": "",
"ReceiverChainflip": "",
"ReceiverOIF": "",
"ReceiverStargateV2": "",
"TokenWrapper": ""
}
}
}
23 changes: 23 additions & 0 deletions deployments/arctestnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"AccessManagerFacet": "0x037E643C2ABf0A065eB19554b096CFc11328de33",
"CalldataVerificationFacet": "0xe44bd998661194534CAAEa44dAb7512e7Fc11D52",
"DiamondCutFacet": "0x81Aa26F9c9b9d5DE24b61b36dD602da7755aC769",
"DiamondLoupeFacet": "0xe60F67d9963977C929eF6Dc465c9874290F746aa",
"EmergencyPauseFacet": "0xF610Ad5028e9ac3b0E3bBF0761d3EFae994F341e",
"GenericSwapFacet": "0xCC66A5dBcD2528E93FFA515a849132e9C3F2F5A2",
"GenericSwapFacetV3": "0xbc140b5ecE539c2A73878badC5014F33F5fe0d83",
"OwnershipFacet": "0x23Abcd6a3B11A161B044EEe5448ACc1c71a280A0",
"PeripheryRegistryFacet": "0xffdF032efC87a5ae95a133637d8F10A5C8e9AC0c",
"WhitelistManagerFacet": "0xb0AF986eACb968B7bf0116C0AC1769D47E97cb40",
"WithdrawFacet": "0xf8c32B42ddA2CEE4085Bb762FaaA83f34FE6Ad7A",
"LiFiDiamond": "0xFf70F4A1d11995621854F3692acF286d8aCd04b2",
"ERC20Proxy": "0x27139fC566d78e743Fb8B0E845069676DaA94aEd",
"Executor": "0x7e0fD1839BC95c2F91E6934e823EA4C30F48DAD2",
"FeeCollector": "0x949343d563394016CE0c52bB6511DFE5aEec8e8a",
"FeeForwarder": "0xD23FB66108971325f302bF0f209216D705adF987",
"LiFiDEXAggregator": "0x3089b3b207E051b2c035c6163874732a18F28bbd",
"Permit2Proxy": "0x36C800D4472fBb888D034Aa74778f481aEE01FEc",
"LiFiTimelockController": "0xBBE888016df347C799de8e7787A239aa105F4ce8",
"LiFiIntentEscrowFacet": "0x71e7fF4A8186CC3DA73e39BFd918Bb27DFb688c2",
"PolymerCCTPFacet": "0x9a01A05F3Ce4B36c88bfE40F546D4F856B177875"
}
4 changes: 4 additions & 0 deletions deployments/optimism.diamond.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
"0x5Fe3dA44896a5F576188a5A2d61594047D8C3a59": {
"Name": "WhitelistRecoveryFacet",
"Version": "1.0.2"
},
"0x17508BC3E587683E6f98bE89b5fDC28521611138": {
"Name": "PolymerCCTPFacet",
"Version": "2.0.1"
}
},
"Periphery": {
Expand Down
2 changes: 1 addition & 1 deletion deployments/optimism.staging.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@
"ReceiverAcrossV4": "0x1d5bD612Ce761060A4bEd77b606ab7e723D4E91E",
"AcrossFacetPackedV4": "0xf536ed5A4310455FF39dBf90336e17d11550E7b4",
"WhitelistManagerFacet": "0x2A6DB28EEe8d006d4F0781b57af3B24603b65A70",
"PolymerCCTPFacet": "0x12B47a94737D8c45793CFC8690716B600E1C2D31",
"PolymerCCTPFacet": "0x17508BC3E587683E6f98bE89b5fDC28521611138",
"WhitelistRecoveryFacet": "0x5Fe3dA44896a5F576188a5A2d61594047D8C3a59"
}
2 changes: 2 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ abstract = "${ETH_NODE_URI_ABSTRACT}"
apechain = "${ETH_NODE_URI_APECHAIN}"
arbitrum = "${ETH_NODE_URI_ARBITRUM}"
arbitrumnova = "${ETH_NODE_URI_ARBITRUMNOVA}"
arctestnet = "${ETH_NODE_URI_ARCTESTNET}"
avalanche = "${ETH_NODE_URI_AVALANCHE}"
base = "${ETH_NODE_URI_BASE}"
berachain = "${ETH_NODE_URI_BERACHAIN}"
Expand Down Expand Up @@ -120,6 +121,7 @@ abstract = { key = "${NO_ETHERSCAN_API_KEY_REQUIRED}", url = "https://abscan.org
apechain = { key = "${MAINNET_ETHERSCAN_API_KEY}", url = "https://api.etherscan.io/v2/api?chainid=33139", chain = "33139" }
arbitrum = { key = "${MAINNET_ETHERSCAN_API_KEY}", url = "https://api.etherscan.io/v2/api?chainid=42161", chain = "42161" }
arbitrumnova = { key = "${NO_ETHERSCAN_API_KEY_REQUIRED}", url = "https://arbitrum-nova.blockscout.com/api", chain = "42170", verifier = "blockscout" }
arctestnet = { key = "${NO_ETHERSCAN_API_KEY_REQUIRED}", url = "https://testnet.arcscan.app/api", chain = "5042002", verifier = "blockscout" }
avalanche = { key = "${MAINNET_ETHERSCAN_API_KEY}", url = "https://api.etherscan.io/v2/api?chainid=43114", chain = "43114" }
base = { key = "${MAINNET_ETHERSCAN_API_KEY}", url = "https://api.etherscan.io/v2/api?chainid=8453", chain = "8453" }
berachain = { key = "${MAINNET_ETHERSCAN_API_KEY}", url = "https://api.etherscan.io/v2/api?chainid=80094", chain = "80094" }
Expand Down
1 change: 1 addition & 0 deletions script/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface INetwork {
safeWebUrl?: string
create3Factory?: string
devNotes?: string
castSendAsync?: boolean
/**
* Custom verification flags to pass to forge verify-contract command.
* Format: JSON object where keys are flag names and values are flag values (or null for flags without values).
Expand Down
28 changes: 28 additions & 0 deletions script/deploy/_targetState.json
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,34 @@
}
}
},
"arctestnet": {
"production": {
"LiFiDiamond": {
"AccessManagerFacet": "1.0.0",
"CalldataVerificationFacet": "1.3.1",
"DiamondCutFacet": "1.0.0",
"DiamondLoupeFacet": "1.0.0",
"EmergencyPauseFacet": "1.0.1",
"GasZipFacet": "2.0.5",
"GenericSwapFacet": "1.0.0",
"GenericSwapFacetV3": "1.0.2",
"LiFiTimelockController": "1.0.1",
"OwnershipFacet": "1.0.0",
"PeripheryRegistryFacet": "1.0.0",
"WithdrawFacet": "1.0.0",
"LiFiDiamond": "1.0.0",
"ERC20Proxy": "1.1.0",
"Executor": "2.1.0",
"FeeCollector": "1.0.1",
"FeeForwarder": "1.0.0",
"GasZipPeriphery": "1.0.2",
"LiFiDEXAggregator": "1.12.0",
"TokenWrapper": "1.2.1",
"Permit2Proxy": "1.0.4",
"LiFiIntentEscrowFacet": "1.0.1"
}
}
},
"tempo": {
"production": {
"LiFiDiamond": {
Expand Down
7 changes: 7 additions & 0 deletions script/deploy/deployAllContracts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ deployAllContracts() {
checkFailure $? "deploy contract $DIAMOND_CONTRACT_NAME to network $NETWORK"
echo "[info] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $DIAMOND_CONTRACT_NAME successfully deployed"

# add DiamondLoupeFacet to diamond
# this one facet is done separately because in many networks we had problems deploying it as part of the core facets update
echo ""
echo ""
echo "[info] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> now adding DiamondLoupeFacet to diamond contract"
diamondUpdateFacet "$NETWORK" "$ENVIRONMENT" "$DIAMOND_CONTRACT_NAME" "UpdateDiamondLoupeFacet" false

Comment on lines +187 to +193
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fail fast if UpdateDiamondLoupeFacet fails.

On Line 192, the new diamondUpdateFacet call is not checked. If it fails but UpdateCoreFacets succeeds, Stage 3 can still appear successful with a partial facet update.

Suggested fix
     echo "[info] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> now adding DiamondLoupeFacet to diamond contract"
     diamondUpdateFacet "$NETWORK" "$ENVIRONMENT" "$DIAMOND_CONTRACT_NAME" "UpdateDiamondLoupeFacet" false
+    checkFailure $? "add DiamondLoupeFacet to $DIAMOND_CONTRACT_NAME on network $NETWORK"
+    echo "[info] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DiamondLoupeFacet update completed"

As per coding guidelines .cursor/rules/002-architecture.mdc, selector/facet update steps are critical invariants and should be explicitly cross-checked.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@script/deploy/deployAllContracts.sh` around lines 187 - 193, The
diamondUpdateFacet call for "UpdateDiamondLoupeFacet" is not being checked,
allowing Stage 3 to appear successful on partial updates; modify the script
where diamondUpdateFacet "$NETWORK" "$ENVIRONMENT" "$DIAMOND_CONTRACT_NAME"
"UpdateDiamondLoupeFacet" false is invoked to immediately verify its exit status
(e.g., check $? or use set -e around the call) and on failure log an error and
exit non‑zero so the deployment fails fast; ensure this mirrors the handling
used for the UpdateCoreFacets step so the facet update is treated as a critical
invariant.

# update diamond with core facets
echo ""
echo ""
Expand Down
24 changes: 11 additions & 13 deletions script/deploy/facets/UpdateDiamondLoupeFacet.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ contract DeployScript is UpdateScriptBase {
);

buildInitialCut(loupeSelectors, diamondLoupeAddress);
// Encode cutData before delete cut so production flow can propose to Safe
if (cut.length > 0) {
cutData = abi.encodeWithSelector(
DiamondCutFacet.diamondCut.selector,
cut,
address(0),
""
);
emit log("DiamondCutCalldata: ");
emit log_bytes(cutData);
}
vm.startBroadcast(deployerPrivateKey);
if (cut.length > 0) {
cutter.diamondCut(cut, address(0), "");
Expand All @@ -43,19 +54,6 @@ contract DeployScript is UpdateScriptBase {
delete cut;
}

// Prepare full diamondCut calldata and log for debugging purposes
if (cut.length > 0) {
cutData = abi.encodeWithSelector(
DiamondCutFacet.diamondCut.selector,
cut,
address(0),
""
);

emit log("DiamondCutCalldata: ");
emit log_bytes(cutData);
}

if (noBroadcast) {
return (facets, cutData);
}
Expand Down
24 changes: 24 additions & 0 deletions script/helperFunctions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3578,6 +3578,30 @@ function getRpcUrlFromNetworksJson() {

echo "$RPC_URL"
}

# getCastSendAsync: Return "true" if cast send should use --async for this network (avoids receipt
# deserialization errors when RPC returns receipts missing fields like feePayer). Used by universalSendRaw.
# Usage: getCastSendAsync NETWORK
# Returns: "true" or "false"
function getCastSendAsync() {
local NETWORK="${1:-}"
if [[ -z "$NETWORK" ]]; then
echo "false"
return
fi
checkNetworksJsonFilePath 2>/dev/null || {
echo "false"
return
}
local VAL
VAL=$(jq -r --arg network "$NETWORK" '.[$network].castSendAsync // false' "$NETWORKS_JSON_FILE_PATH" 2>/dev/null)
if [[ "$VAL" == "true" ]]; then
echo "true"
else
echo "false"
fi
}

function playNotificationSound() {
if [[ "$NOTIFICATION_SOUNDS" == *"true"* ]]; then
afplay ./script/deploy/resources/notification.mp3
Expand Down
Loading
Loading