diff --git a/.env.example b/.env.example index 440f65fc3..6028ed228 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,7 @@ ETH_NODE_URI_GRAVITY=https://rpc.gravity.xyz #[pre-commit-checker: not a secret ETH_NODE_URI_IMMUTABLEZKEVM=https://rpc.immutable.com #[pre-commit-checker: not a secret] ETH_NODE_URI_KAIA=https://klaytn.drpc.org #[pre-commit-checker: not a secret] ETH_NODE_URI_LINEA=https://rpc.linea.build #[pre-commit-checker: not a secret] +ETH_NODE_URI_LISK=https://rpc.api.lisk.com #[pre-commit-checker: not a secret] ETH_NODE_URI_MANTLE=https://rpc.mantle.xyz #[pre-commit-checker: not a secret] ETH_NODE_URI_METIS=https://metis-mainnet.public.blastapi.io #[pre-commit-checker: not a secret] ETH_NODE_URI_MODE=https://mainnet.mode.network #[pre-commit-checker: not a secret] @@ -60,6 +61,7 @@ GRAVITY_ETHERSCAN_API_KEY= IMMUTABLEZKEVM_ETHERSCAN_API_KEY= KAIA_ETHERSCAN_API_KEY= LINEA_ETHERSCAN_API_KEY= +LISK_ETHERSCAN_API_KEY= MANTLE_ETHERSCAN_API_KEY= METIS_ETHERSCAN_API_KEY= MODE_ETHERSCAN_API_KEY= diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 542a47ac2..a8fffb820 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,6 +7,7 @@ - [ ] I have performed a self-review of my code - [ ] This pull request is as small as possible and only tackles one problem - [ ] I have added tests that cover the functionality / test the bug +- [ ] For new facets: I have checked all points from this list: https://www.notion.so/lifi/New-Facet-Contract-Checklist-157f0ff14ac78095a2b8f999d655622e - [ ] I have updated any required documentation # Checklist for reviewer (DO NOT DEPLOY and contracts BEFORE CHECKING THIS!!!) diff --git a/.github/workflows/diamondEmergencyPause.yml b/.github/workflows/diamondEmergencyPause.yml index 223a664a3..8265ffcbd 100644 --- a/.github/workflows/diamondEmergencyPause.yml +++ b/.github/workflows/diamondEmergencyPause.yml @@ -65,6 +65,7 @@ jobs: ETH_NODE_URI_IMMUTABLEZKEVM: ${{ secrets.ETH_NODE_URI_IMMUTABLEZKEVM }} ETH_NODE_URI_KAIA: ${{ secrets.ETH_NODE_URI_KAIA }} ETH_NODE_URI_LINEA: ${{ secrets.ETH_NODE_URI_LINEA }} + ETH_NODE_URI_LISK: ${{ secrets.ETH_NODE_URI_LISK }} ETH_NODE_URI_MANTLE: ${{ secrets.ETH_NODE_URI_MANTLE }} ETH_NODE_URI_METIS: ${{ secrets.ETH_NODE_URI_METIS }} ETH_NODE_URI_MODE: ${{ secrets.ETH_NODE_URI_MODE }} @@ -78,6 +79,7 @@ jobs: ETH_NODE_URI_SCROLL: ${{ secrets.ETH_NODE_URI_SCROLL }} ETH_NODE_URI_SEI: ${{ secrets.ETH_NODE_URI_SEI }} ETH_NODE_URI_TAIKO: ${{ secrets.ETH_NODE_URI_TAIKO }} + ETH_NODE_URI_WORLDCHAIN: ${{ secrets.ETH_NODE_URI_WORLDCHAIN }} ETH_NODE_URI_XLAYER: ${{ secrets.ETH_NODE_URI_XLAYER }} ETH_NODE_URI_ZKSYNC: ${{ secrets.ETH_NODE_URI_ZKSYNC }} PRIVATE_KEY_PAUSER_WALLET: ${{ secrets.PRIV_KEY_PAUSER_WALLET }} diff --git a/.github/workflows/forceMergePRBypassAudit.yml b/.github/workflows/forceMergePRBypassAudit.yml new file mode 100644 index 000000000..6142d8cb0 --- /dev/null +++ b/.github/workflows/forceMergePRBypassAudit.yml @@ -0,0 +1,113 @@ +name: Force-Merge PR (Bypass Audit Requirement) +# - This git action may only be used in exceptional cases +# - Exceptional cases are for example issues in an audit-protected contract that do not touch the code itself such +# as an issue with the solidity pragma or some issue in a comment +# - it can only be executed by the CTO or the Information Security Manager/Architect +# - a valid reason must be provided in order to force-merge a given PR + +on: + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to bypass' + required: true + justification: + description: 'Reason for bypass' + required: true + +jobs: + force-merge-pr-bypass-audit: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Fetch Information Security Team Members + env: + GH_PAT: ${{ secrets.GIT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ##### Unset default GITHUB_TOKEN (insufficient permissions) + unset GITHUB_TOKEN + + ##### Authenticate with Personal Access Token + echo "::add-mask::$GH_PAT" # Mask the token + echo $GH_PAT | gh auth login --with-token + + ##### Fetch team members of 'informationsecuritymanager' team + ORG_NAME="lifinance" + TEAM_SLUG="informationsecuritymanager" + + TEAM_MEMBERS=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/orgs/$ORG_NAME/teams/$TEAM_SLUG/members" | jq -r '.[].login') + + if [[ -z "$TEAM_MEMBERS" ]]; then + echo -e "\033[31mERROR: Could not retrieve team members of $TEAM_SLUG.\033[0m" + exit 1 + fi + + echo "The following users are members of $TEAM_SLUG: $TEAM_MEMBERS" + echo "$TEAM_MEMBERS" > team_members.txt + + - name: Verify Actor's Team Membership + run: | + ##### Check if the actor is in the team members list + ACTOR="${{ github.actor }}" + TEAM_MEMBERS=$(cat team_members.txt) + + # Strict validation of actor against team members + if echo "$TEAM_MEMBERS" | while read -r member; do + [[ "$member" == "$ACTOR" ]] && exit 0 + done; then + echo -e "\033[32m$ACTOR is authorized to approve bypasses.\033[0m" + echo "CONTINUE=true" >> "$GITHUB_ENV" + else + echo -e "\033[31mERROR: $ACTOR is NOT authorized to approve bypasses\033[0m" + exit 1 + fi + + - name: Log Justification + if: env.CONTINUE == 'true' + run: | + echo "Bypass approved for PR #${{ github.event.inputs.pr_number }} by $ACTOR." + echo "Justification: ${{ github.event.inputs.justification }}" + + - name: Merge the PR + uses: actions/github-script@v7.0.1 + if: env.CONTINUE == 'true' + with: + script: | + const pr = parseInt(core.getInput('pr_number')); + const { context } = github; + console.log(`Merging PR ${pr} now`) + + // Fetch PR details + const { data: prData } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr + }); + + // Validate PR state + if (!prData.mergeable) { + throw new Error('PR is not in a mergeable state'); + } + + await github.rest.pulls.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr, + merge_method: "squash", + commit_title: `[BYPASS] ${prData.title}`, + commit_message: `Bypassed by ${context.actor}\nJustification: ${core.getInput('justification')}` + }); + + - name: Send Discord message + uses: Ilshidur/action-discord@0.3.2 + with: + args: | + :warning: '${{ github.actor }} just bypassed the audit requirement controls to force-merge PR #${{ github.event.inputs.pr_number }}.' + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_DEV_SMARTCONTRACTS }} diff --git a/config/across.json b/config/across.json index ca39ae88a..48570a8f8 100644 --- a/config/across.json +++ b/config/across.json @@ -113,6 +113,14 @@ "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f" ] }, + "lisk": { + "chainId": 1135, + "acrossSpokePool": "0x9552a0a6624A23B848060AE5901659CDDa1f83f8", + "weth": "0x4200000000000000000000000000000000000006", + "tokensToApprove": [ + "0x4200000000000000000000000000000000000006" + ] + }, "blast": { "chainId": 81457, "acrossSpokePool": "0x2D509190Ed0172ba588407D4c2df918F955Cc6E1", @@ -142,4 +150,4 @@ "0x4200000000000000000000000000000000000006" ] } -} +} \ No newline at end of file diff --git a/config/amarok.json b/config/amarok.json index e87d66b1f..f8bdb2aa5 100644 --- a/config/amarok.json +++ b/config/amarok.json @@ -108,6 +108,12 @@ "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f" ] }, + "lisk": { + "chainId": 1135, + "connextHandler": "0x0000000000000000000000000000000000000000", + "domain": "", + "tokensToApprove": [] + }, "mantle": { "chainId": 5000, "connextHandler": "0x0000000000000000000000000000000000000000", diff --git a/config/dexs.json b/config/dexs.json index 20c4114f1..013b0a66e 100644 --- a/config/dexs.json +++ b/config/dexs.json @@ -502,6 +502,13 @@ "0x6b2c0c7be2048daa9b5527982c29f48062b34d58", "0x57df6092665eb6058DE53939612413ff4B09114E" ], + "lisk": [ + "0x603a538477d44064eA5A5d8C345b4Ff6fca1142a", + "0x2321F1a63A683a1F3634Dbe1CbA0d657D5F56d54", + "0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1", + "0x76aE215b11797b32397d878e6f3E65081ff58b13", + "0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155" + ], "mantle": [ "0xD9F4e85489aDCD0bAF0Cd63b4231c6af58c26745", "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64", diff --git a/config/gaszip.json b/config/gaszip.json index ca5f7da45..f4142d294 100644 --- a/config/gaszip.json +++ b/config/gaszip.json @@ -11,6 +11,7 @@ "gnosis": "0x2a37D63EAdFe4b4682a3c28C1c2cD4F109Cc2762", "gravity": "0x6Efc6Ead40786bD87A884382b6EA4BcA3C985e99", "linea": "0xA60768b03eB14d940F6c9a8553329B7F9037C91b", + "lisk": "0xA60768b03eB14d940F6c9a8553329B7F9037C91b", "mantle": "0x2a37D63EAdFe4b4682a3c28C1c2cD4F109Cc2762", "metis": "0x2a37D63EAdFe4b4682a3c28C1c2cD4F109Cc2762", "mode": "0x2a37D63EAdFe4b4682a3c28C1c2cD4F109Cc2762", diff --git a/config/networks.json b/config/networks.json index 725fd2ea7..a21cbdfbf 100644 --- a/config/networks.json +++ b/config/networks.json @@ -323,6 +323,24 @@ "safeWebUrl": "https://app.safe.global/transactions/queue?safe=linea:0xdf61270fDC1A892874Fd3C0143A0A4CBA74F4EF1", "gasZipChainId": 59 }, + "lisk": { + "name": "Lisk", + "chainId": 1135, + "nativeAddress": "0x0000000000000000000000000000000000000000", + "nativeCurrency": "ETH", + "wrappedNativeAddress": "0x4200000000000000000000000000000000000006", + "status": "active", + "type": "mainnet", + "rpcUrl": "https://rpc.api.lisk.com", + "verificationType": "blockscout", + "explorerUrl": "https://blockscout.lisk.com", + "explorerApiUrl": "https://blockscout.lisk.com/api", + "multicallAddress": "0xcA11bde05977b3631167028862bE2a173976CA11", + "safeApiUrl": "https://transaction-lisk.safe.optimism.io/api", + "safeAddress": "0x86E02d7383D6a045848b0a1A842996AC9E943113", + "safeWebUrl": "https://safe.optimism.io/home?safe=lisk:0x86E02d7383D6a045848b0a1A842996AC9E943113", + "gasZipChainId": 238 + }, "mantle": { "name": "mantle", "chainId": 5000, @@ -565,7 +583,7 @@ "wrappedNativeAddress": "0x4200000000000000000000000000000000000006", "status": "inactive", "type": "mainnet", - "rpcUrl": "https://worldchain-mainnet.g.alchemy.com/public", + "rpcUrl": "https://worldchain-mainnet.gateway.tenderly.co", "verificationType": "etherscan", "explorerUrl": "https://worldscan.org", "explorerApiUrl": "https://api.worldscan.org/api", @@ -629,4 +647,4 @@ "safeWebUrl": "", "gasZipChainId": 0 } -} +} \ No newline at end of file diff --git a/config/sigs.json b/config/sigs.json index 042d9107b..d927ab4bf 100644 --- a/config/sigs.json +++ b/config/sigs.json @@ -151,6 +151,7 @@ "0xc4af5a74", "0x03b87e5f", "0x0d5f0e3b", - "0x08298b5a" + "0x08298b5a", + "0xff84aafa" ] -} \ No newline at end of file +} diff --git a/config/stargate.json b/config/stargate.json index 9a4f1053b..2a659494b 100644 --- a/config/stargate.json +++ b/config/stargate.json @@ -31,6 +31,7 @@ "kaia": "0x0000000000000000000000000000000000000000", "velas": "0x0000000000000000000000000000000000000000", "linea": "0x1a44076050125825900e736c501f859c50fE728c", + "lisk": "0x0000000000000000000000000000000000000000", "metis": "0x1a44076050125825900e736c501f859c50fE728c", "mode": "0x1a44076050125825900e736c501f859c50fE728c", "mantle": "0x1a44076050125825900e736c501f859c50fE728c", @@ -224,6 +225,7 @@ "bsc-testnet": "0x0000000000000000000000000000000000000000", "lineatest": "0x0000000000000000000000000000000000000000", "linea": "0xeCc19E177d24551aA7ed6Bc6FE566eCa726CC8a9", + "lisk": "0x0000000000000000000000000000000000000000", "metis": "0xeCc19E177d24551aA7ed6Bc6FE566eCa726CC8a9", "mode": "0x0000000000000000000000000000000000000000", "mantle": "0x296F55F8Fb28E498B858d0BcDA06D955B2Cb3f97", @@ -266,6 +268,7 @@ "bsc-testnet": "0x0000000000000000000000000000000000000000", "lineatest": "0x0000000000000000000000000000000000000000", "linea": "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", + "lisk": "0x0000000000000000000000000000000000000000", "mantle": "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", "metis": "0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590", "scroll": "0x36d4686e19c052787D7f24E6913cEbC025714895", diff --git a/config/symbiosis.json b/config/symbiosis.json index cc769bddf..ed09db678 100644 --- a/config/symbiosis.json +++ b/config/symbiosis.json @@ -35,6 +35,10 @@ "metaRouter": "0xcE8f24A58D85eD5c5A6824f7be1F8d4711A0eb4C", "gateway": "0xAdB2d3b711Bb8d8Ea92ff70292c466140432c278" }, + "gravity": { + "metaRouter": "0xcE8f24A58D85eD5c5A6824f7be1F8d4711A0eb4C", + "gateway": "0xAdB2d3b711Bb8d8Ea92ff70292c466140432c278" + }, "linea": { "metaRouter": "0x9A31bAC4b3B958C835C243800B474818D04393dd", "gateway": "0x83f71AabdDBb9F0E3B6462Cc7635b6fFAD0f2f2e" @@ -83,4 +87,4 @@ "metaRouter": "0x7057aB3fB2BeE9c18e0cDe4240DE4ff7f159E365", "gateway": "0xa0079829B9F1Edc5DD0DE3eC104f281745C4bD81" } -} \ No newline at end of file +} diff --git a/config/tokenwrapper.json b/config/tokenwrapper.json index 50224e167..471e6039a 100644 --- a/config/tokenwrapper.json +++ b/config/tokenwrapper.json @@ -30,6 +30,7 @@ "celo": "0x471ece3750da237f93b8e339c536989b8978a438", "avalanche": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7", "linea": "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f", + "lisk": "0x4200000000000000000000000000000000000006", "blast": "0x4300000000000000000000000000000000000004", "worldchain": "0x4200000000000000000000000000000000000006", "taiko": "0xA51894664A773981C6C112C43ce576f315d5b1B6", diff --git a/deployments/_deployments_log_file.json b/deployments/_deployments_log_file.json index bc1c618b0..052cb2015 100644 --- a/deployments/_deployments_log_file.json +++ b/deployments/_deployments_log_file.json @@ -704,6 +704,20 @@ } ] } + }, + "lisk": { + "production": { + "2.0.0": [ + { + "ADDRESS": "0x57FdfF2e36De6c8a8Cde297B150Ae291132Eae8d", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:23.651Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "DiamondLoupeFacet": { @@ -1398,6 +1412,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xA1a4d577709dC4A70CA38F1D41562fab3aD09D3f", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:24.128Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "OwnershipFacet": { @@ -2091,6 +2119,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x81Ae738700D8f1e5BB2A200584174cDf17Fb5455", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:24.830Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "DexManagerFacet": { @@ -3072,6 +3114,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.1": [ + { + "ADDRESS": "0xE154389c1bAE241F220661131b7AfDc1514C55c7", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:25.125Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "AccessManagerFacet": { @@ -3766,6 +3822,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x314E1E760316050B0D6338bCf3d689b8D301F593", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:25.519Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "WithdrawFacet": { @@ -4446,6 +4516,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xfA009cd56d35AE3BbdF975135b0BAE9b403c7da1", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:25.844Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "PeripheryRegistryFacet": { @@ -5139,6 +5223,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x54ECfbAaeb49c864a9c45C70B785ca6C70c66453", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:26.132Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "LiFiDiamond": { @@ -5807,6 +5905,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:27.951Z", + "CONSTRUCTOR_ARGS": "0x00000000000000000000000011f11121df7256c40339393b0fb045321022ce4400000000000000000000000057fdff2e36de6c8a8cde297b150ae291132eae8d", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "LiFiDiamondImmutable": { @@ -7532,6 +7644,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xd2B3b3605e630232c13111458Ae3a97d13c8F477", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:26.451Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "HopFacetOptimized": { @@ -9002,6 +9128,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.1": [ + { + "ADDRESS": "0x14Dd70456Bfe4Cd8b605f7A0d24b3A74aCe99713", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:26.777Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "MultichainFacet": { @@ -10882,6 +11022,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x98750e70Cf1313D9702f0f57D399DD0bA05d16E0", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:29.375Z", + "CONSTRUCTOR_ARGS": "0x00000000000000000000000011f11121df7256c40339393b0fb045321022ce44", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "Executor": { @@ -11750,6 +11904,20 @@ } ] } + }, + "lisk": { + "production": { + "2.0.0": [ + { + "ADDRESS": "0xd9318fFE1EbbfA71049A443e623Be566067C9D6B", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:29.736Z", + "CONSTRUCTOR_ARGS": "0x00000000000000000000000098750e70cf1313d9702f0f57d399dd0ba05d16e0", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "FeeCollector": { @@ -12419,6 +12587,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:30.068Z", + "CONSTRUCTOR_ARGS": "0x00000000000000000000000008647cc950813966142a416d40c382e2c5db73bb", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "Receiver": { @@ -13643,6 +13825,20 @@ } ] } + }, + "lisk": { + "production": { + "2.0.2": [ + { + "ADDRESS": "0xD9e3837E42198aaFc13cb51536d7c31f590aD6Fd", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:30.366Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000156cebba59deb2cb23742f70dcb0a11cc775591f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d9318ffe1ebbfa71049a443e623be566067c9d6b00000000000000000000000000000000000000000000000000000000000186a0", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "ServiceFeeCollector": { @@ -19205,6 +19401,20 @@ } ] } + }, + "lisk": { + "production": { + "1.1.0": [ + { + "ADDRESS": "0xe6C6A35684308f2DaadbeeA50B62CFEaAFaa407E", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:27.568Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "CalldataVerificationFacet": { @@ -19937,6 +20147,20 @@ } ] } + }, + "lisk": { + "production": { + "1.1.2": [ + { + "ADDRESS": "0x1feB868BF64AdC552E051fB7387681F78b988a81", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:27.218Z", + "CONSTRUCTOR_ARGS": "0x", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "LiFuelFeeCollector": { @@ -20790,6 +21014,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.1": [ + { + "ADDRESS": "0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:30.746Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000c71284231a726a18ac85c94d75f9fe17a185beaf", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "AcrossFacetPacked": { @@ -21505,6 +21743,20 @@ } ] } + }, + "gravity": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xbb44687E13B0DdB11682FA9299F5F982Ba3cc029", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-09 17:40:50", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000ce8f24a58d85ed5c5a6824f7be1f8d4711a0eb4c000000000000000000000000adb2d3b711bb8d8ea92ff70292c466140432c278", + "SALT": "", + "VERIFIED": "true" + } + ] + } } }, "MayanBridgeFacet": { @@ -22062,6 +22314,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x603a538477d44064eA5A5d8C345b4Ff6fca1142a", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:31.141Z", + "CONSTRUCTOR_ARGS": "0x0000000000000000000000004200000000000000000000000000000000000006", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "GasRebateDistributor": { @@ -22744,6 +23010,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.1": [ + { + "ADDRESS": "0xBa713B18c806EcdEEE49FAec623dE2D872192872", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-11-25 10:30:44", + "CONSTRUCTOR_ARGS": "0x0000000000000000000000000000000000000000000000000000000000000000", + "SALT": "", + "VERIFIED": "true" + } + ] + } } }, "StargateFacetV2": { @@ -23894,6 +24174,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x2321F1a63A683a1F3634Dbe1CbA0d657D5F56d54", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:31.571Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d38743b48d26743c0ec6898d699394fbc94657ee", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "EmergencyPauseFacet": { @@ -24420,6 +24714,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.1": [ + { + "ADDRESS": "0xF6Eff8df65Fc4a4c1528761Aa727b5471956A844", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:28.266Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000d38743b48d26743c0ec6898d699394fbc94657ee", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "AcrossFacetV3": { @@ -24612,6 +24920,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xB5dD83183fD7CCF859b227CA83663a034d5B2f92", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:28.661Z", + "CONSTRUCTOR_ARGS": "0x0000000000000000000000009552a0a6624a23b848060ae5901659cdda1f83f80000000000000000000000004200000000000000000000000000000000000006", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "ReceiverAcrossV3": { @@ -24925,6 +25247,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0xD263a23453CB9A77860ed6393A2B9a55AF70EFAb", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:32.000Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000156cebba59deb2cb23742f70dcb0a11cc775591f000000000000000000000000d9318ffe1ebbfa71049a443e623be566067c9d6b0000000000000000000000009552a0a6624a23b848060ae5901659cdda1f83f800000000000000000000000000000000000000000000000000000000000186a0", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "AcrossFacetPackedV3": { @@ -25227,6 +25563,20 @@ } ] } + }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x90ADbFc03002aaA3d9FEdf2517D593CfD93e6c57", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-02T08:02:29.037Z", + "CONSTRUCTOR_ARGS": "0x0000000000000000000000009552a0a6624a23b848060ae5901659cdda1f83f8000000000000000000000000420000000000000000000000000000000000000600000000000000000000000011f11121df7256c40339393b0fb045321022ce44", + "SALT": "", + "VERIFIED": true + } + ] + } } }, "Permit2Proxy": { @@ -25684,6 +26034,20 @@ ] } }, + "lisk": { + "production": { + "2.0.0": [ + { + "ADDRESS": "0xb40044Bf27c2448e05e1f34ED83Ca4A3DfA54D19", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-04T12:47:31.763Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000a60768b03eb14d940f6c9a8553329b7f9037c91b", + "SALT": "", + "VERIFIED": true + } + ] + } + }, "worldchain": { "production": { "2.0.0": [ @@ -25978,6 +26342,20 @@ ] } }, + "lisk": { + "production": { + "1.0.0": [ + { + "ADDRESS": "0x76aE215b11797b32397d878e6f3E65081ff58b13", + "OPTIMIZER_RUNS": "1000000", + "TIMESTAMP": "2024-12-04T12:47:32.171Z", + "CONSTRUCTOR_ARGS": "0x000000000000000000000000a60768b03eb14d940f6c9a8553329b7f9037c91b0000000000000000000000002321f1a63a683a1f3634dbe1cba0d657d5f56d5400000000000000000000000086e02d7383d6a045848b0a1a842996ac9e943113", + "SALT": "", + "VERIFIED": true + } + ] + } + }, "worldchain": { "production": { "1.0.0": [ diff --git a/deployments/gravity.diamond.json b/deployments/gravity.diamond.json index dca76a341..729f675f6 100644 --- a/deployments/gravity.diamond.json +++ b/deployments/gravity.diamond.json @@ -68,6 +68,10 @@ "0x325DA62543447A48c7b044C5642B87CeA88B0fd3": { "Name": "", "Version": "" + }, + "0xbb44687E13B0DdB11682FA9299F5F982Ba3cc029": { + "Name": "SymbiosisFacet", + "Version": "1.0.0" } }, "Periphery": { @@ -85,4 +89,4 @@ "TokenWrapper": "0x7fA60f4A59Dd8285C5Fcd8fd2A92A2Ca45ef8a0C" } } -} +} \ No newline at end of file diff --git a/deployments/gravity.json b/deployments/gravity.json index d7707e159..9fc2897f9 100644 --- a/deployments/gravity.json +++ b/deployments/gravity.json @@ -23,5 +23,6 @@ "Receiver": "0x2DeB3bFa2b19024A0c1Ba299b6b79276f1F77b14", "EmergencyPauseFacet": "0x6F2baA7cd5F156CA1B132F7FF11E0fa2aD775F61", "GasZipFacet": "0xF5c923a087fb3c554579e2DD10AB6E37E0f6F849", - "GasZipPeriphery": "0x9a21E33F1a78b17DAd32010CeDB9Fd2F071C17d3" + "GasZipPeriphery": "0x9a21E33F1a78b17DAd32010CeDB9Fd2F071C17d3", + "SymbiosisFacet": "0xbb44687E13B0DdB11682FA9299F5F982Ba3cc029" } \ No newline at end of file diff --git a/deployments/lisk.diamond.json b/deployments/lisk.diamond.json new file mode 100644 index 000000000..dbce21a66 --- /dev/null +++ b/deployments/lisk.diamond.json @@ -0,0 +1,84 @@ +{ + "LiFiDiamond": { + "Facets": { + "0x57FdfF2e36De6c8a8Cde297B150Ae291132Eae8d": { + "Name": "DiamondCutFacet", + "Version": "2.0.0" + }, + "0xA1a4d577709dC4A70CA38F1D41562fab3aD09D3f": { + "Name": "DiamondLoupeFacet", + "Version": "1.0.0" + }, + "0x81Ae738700D8f1e5BB2A200584174cDf17Fb5455": { + "Name": "OwnershipFacet", + "Version": "1.0.0" + }, + "0xfA009cd56d35AE3BbdF975135b0BAE9b403c7da1": { + "Name": "WithdrawFacet", + "Version": "1.0.0" + }, + "0xE154389c1bAE241F220661131b7AfDc1514C55c7": { + "Name": "DexManagerFacet", + "Version": "1.0.1" + }, + "0x314E1E760316050B0D6338bCf3d689b8D301F593": { + "Name": "AccessManagerFacet", + "Version": "1.0.0" + }, + "0x54ECfbAaeb49c864a9c45C70B785ca6C70c66453": { + "Name": "PeripheryRegistryFacet", + "Version": "1.0.0" + }, + "0x14Dd70456Bfe4Cd8b605f7A0d24b3A74aCe99713": { + "Name": "LIFuelFacet", + "Version": "1.0.1" + }, + "0xd2B3b3605e630232c13111458Ae3a97d13c8F477": { + "Name": "GenericSwapFacet", + "Version": "1.0.0" + }, + "0xBa713B18c806EcdEEE49FAec623dE2D872192872": { + "Name": "GenericSwapFacetV3", + "Version": "1.0.1" + }, + "0xe6C6A35684308f2DaadbeeA50B62CFEaAFaa407E": { + "Name": "StandardizedCallFacet", + "Version": "1.1.0" + }, + "0x1feB868BF64AdC552E051fB7387681F78b988a81": { + "Name": "CalldataVerificationFacet", + "Version": "1.1.2" + }, + "0xF6Eff8df65Fc4a4c1528761Aa727b5471956A844": { + "Name": "EmergencyPauseFacet", + "Version": "1.0.1" + }, + "0xB5dD83183fD7CCF859b227CA83663a034d5B2f92": { + "Name": "AcrossFacetV3", + "Version": "1.0.0" + }, + "0x90ADbFc03002aaA3d9FEdf2517D593CfD93e6c57": { + "Name": "AcrossFacetPackedV3", + "Version": "1.0.0" + }, + "0xb40044Bf27c2448e05e1f34ED83Ca4A3DfA54D19": { + "Name": "GasZipFacet", + "Version": "2.0.0" + } + }, + "Periphery": { + "ERC20Proxy": "0x98750e70Cf1313D9702f0f57D399DD0bA05d16E0", + "Executor": "0xd9318fFE1EbbfA71049A443e623Be566067C9D6B", + "FeeCollector": "0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155", + "GasZipPeriphery": "0x76aE215b11797b32397d878e6f3E65081ff58b13", + "LiFiDEXAggregator": "0x2321F1a63A683a1F3634Dbe1CbA0d657D5F56d54", + "LiFuelFeeCollector": "0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1", + "Permit2Proxy": "", + "ReceiverAcrossV3": "0xD263a23453CB9A77860ed6393A2B9a55AF70EFAb", + "Receiver": "0xD9e3837E42198aaFc13cb51536d7c31f590aD6Fd", + "ReceiverStargateV2": "", + "RelayerCelerIM": "", + "TokenWrapper": "0x603a538477d44064eA5A5d8C345b4Ff6fca1142a" + } + } +} \ No newline at end of file diff --git a/deployments/lisk.json b/deployments/lisk.json new file mode 100644 index 000000000..ee8533b6e --- /dev/null +++ b/deployments/lisk.json @@ -0,0 +1,28 @@ +{ + "DiamondCutFacet": "0x57FdfF2e36De6c8a8Cde297B150Ae291132Eae8d", + "DiamondLoupeFacet": "0xA1a4d577709dC4A70CA38F1D41562fab3aD09D3f", + "GenericSwapFacetV3": "0xBa713B18c806EcdEEE49FAec623dE2D872192872", + "OwnershipFacet": "0x81Ae738700D8f1e5BB2A200584174cDf17Fb5455", + "DexManagerFacet": "0xE154389c1bAE241F220661131b7AfDc1514C55c7", + "AccessManagerFacet": "0x314E1E760316050B0D6338bCf3d689b8D301F593", + "WithdrawFacet": "0xfA009cd56d35AE3BbdF975135b0BAE9b403c7da1", + "PeripheryRegistryFacet": "0x54ECfbAaeb49c864a9c45C70B785ca6C70c66453", + "GenericSwapFacet": "0xd2B3b3605e630232c13111458Ae3a97d13c8F477", + "LIFuelFacet": "0x14Dd70456Bfe4Cd8b605f7A0d24b3A74aCe99713", + "CalldataVerificationFacet": "0x1feB868BF64AdC552E051fB7387681F78b988a81", + "StandardizedCallFacet": "0xe6C6A35684308f2DaadbeeA50B62CFEaAFaa407E", + "LiFiDiamond": "0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE", + "EmergencyPauseFacet": "0xF6Eff8df65Fc4a4c1528761Aa727b5471956A844", + "AcrossFacetV3": "0xB5dD83183fD7CCF859b227CA83663a034d5B2f92", + "AcrossFacetPackedV3": "0x90ADbFc03002aaA3d9FEdf2517D593CfD93e6c57", + "ERC20Proxy": "0x98750e70Cf1313D9702f0f57D399DD0bA05d16E0", + "Executor": "0xd9318fFE1EbbfA71049A443e623Be566067C9D6B", + "FeeCollector": "0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155", + "Receiver": "0xD9e3837E42198aaFc13cb51536d7c31f590aD6Fd", + "LiFuelFeeCollector": "0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1", + "TokenWrapper": "0x603a538477d44064eA5A5d8C345b4Ff6fca1142a", + "LiFiDEXAggregator": "0x2321F1a63A683a1F3634Dbe1CbA0d657D5F56d54", + "ReceiverAcrossV3": "0xD263a23453CB9A77860ed6393A2B9a55AF70EFAb", + "GasZipFacet": "0xb40044Bf27c2448e05e1f34ED83Ca4A3DfA54D19", + "GasZipPeriphery": "0x76aE215b11797b32397d878e6f3E65081ff58b13" +} \ No newline at end of file diff --git a/foundry-zksync/.gitignore b/foundry-zksync/.gitignore new file mode 100644 index 000000000..831a32ae7 --- /dev/null +++ b/foundry-zksync/.gitignore @@ -0,0 +1,2 @@ +forge +cast diff --git a/foundry-zksync/Dockerfile b/foundry-zksync/Dockerfile deleted file mode 100644 index e4a190bcf..000000000 --- a/foundry-zksync/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM ubuntu - -WORKDIR /foundry - -RUN apt update && apt install -y wget jq -RUN wget https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz -RUN tar -xzvf ./foundry_nightly_linux_amd64.tar.gz - -RUN mv ./forge /usr/local/bin/forge -RUN mv ./cast /usr/local/bin/cast - -CMD ["forge"] diff --git a/foundry.toml b/foundry.toml index beb127594..f613dae73 100644 --- a/foundry.toml +++ b/foundry.toml @@ -42,6 +42,7 @@ gravity = "${ETH_NODE_URI_GRAVITY}" immutablezkevm = "${ETH_NODE_URI_IMMUTABLEZKEVM}" kaia = "${ETH_NODE_URI_KAIA}" linea = "${ETH_NODE_URI_LINEA}" +lisk = "${ETH_NODE_URI_LISK}" moonbeam = "${ETH_NODE_URI_MOONBEAM}" moonriver = "${ETH_NODE_URI_MOONRIVER}" nova = "${ETH_NODE_URI_NOVA}" @@ -89,6 +90,7 @@ gravity = { key = "${GRAVITY_ETHERSCAN_API_KEY}", url = "https://explorer.gravit immutablezkevm = { key = "${IMMUTABLEZKEVM_ETHERSCAN_API_KEY}", url = "https://explorer.immutable.com/api", chain = "13371", verifier = "blockscout" } kaia = { key = "${KAIA_ETHERSCAN_API_KEY}", url = "https://api-cypress.klaytnscope.com/api", chain = "8217", verifier = "blockscout" } linea = { key = "${LINEA_ETHERSCAN_API_KEY}", url = "https://api.lineascan.build/api", chain = "59144" } +lisk = { key = "${LISK_ETHERSCAN_API_KEY}", url = "https://blockscout.lisk.com/api", chain = "1135", verifier = "blockscout" } mantle = { key = "${MANTLE_ETHERSCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/5000/etherscan", chain = "5000" } metis = { key = "${METIS_ETHERSCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan", chain = "1088" } mode = { key = "${MODE_ETHERSCAN_API_KEY}", url = "https://api.routescan.io/v2/network/mainnet/evm/34443/etherscan", chain = "34443" } diff --git a/networks b/networks index 498fbd496..af8e0eedb 100644 --- a/networks +++ b/networks @@ -16,6 +16,7 @@ gravity immutablezkevm kaia linea +lisk mantle metis mode diff --git a/script/deploy/_targetState.json b/script/deploy/_targetState.json index 3e0f65e09..cb50b4b72 100644 --- a/script/deploy/_targetState.json +++ b/script/deploy/_targetState.json @@ -1376,7 +1376,6 @@ } } }, - "rootstocks": {}, "cronos": { "production": { "LiFiDiamond": { diff --git a/script/deploy/deploySingleContract.sh b/script/deploy/deploySingleContract.sh index f4a08c373..b7c1e73da 100755 --- a/script/deploy/deploySingleContract.sh +++ b/script/deploy/deploySingleContract.sh @@ -207,11 +207,10 @@ deploySingleContract() { rm -fr ./out rm -fr ./zkout # Clean zksync cache - docker run --rm -it --volume .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge cache clean + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge cache clean - # Run zksync specific fork of forge from Docker so as not to pollute the - # local foundry forge setup - docker run --rm -it --volume .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge build --zksync + # Run zksync specific fork of forge + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge build --zksync fi # execute script @@ -224,8 +223,8 @@ deploySingleContract() { doNotContinueUnlessGasIsBelowThreshold "$NETWORK" if [[ $NETWORK == "zksync" ]]; then - # Deploy zksync scripts using the zksync specific fork of forge from Docker - RAW_RETURN_DATA=$(docker run --rm -it --volume .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync -e DEPLOYSALT=$DEPLOYSALT -e NETWORK=$NETWORK -e FILE_SUFFIX=$FILE_SUFFIX -e PRIVATE_KEY=$(getPrivateKey "$NETWORK" "$ENVIRONMENT") foundry-zksync forge script "$FULL_SCRIPT_PATH" -f $NETWORK --json --broadcast --skip-simulation --slow --zksync) + # Deploy zksync scripts using the zksync specific fork of forge + RAW_RETURN_DATA=$(FOUNDRY_PROFILE=zksync DEPLOYSALT=$DEPLOYSALT NETWORK=$NETWORK FILE_SUFFIX=$FILE_SUFFIX PRIVATE_KEY=$(getPrivateKey "$NETWORK" "$ENVIRONMENT") ./foundry-zksync/forge script "$FULL_SCRIPT_PATH" -f $NETWORK --json --broadcast --skip-simulation --slow --zksync) else # try to execute call RAW_RETURN_DATA=$(DEPLOYSALT=$DEPLOYSALT CREATE3_FACTORY_ADDRESS=$CREATE3_FACTORY_ADDRESS NETWORK=$NETWORK FILE_SUFFIX=$FILE_SUFFIX DEFAULT_DIAMOND_ADDRESS_DEPLOYSALT=$DEFAULT_DIAMOND_ADDRESS_DEPLOYSALT DEPLOY_TO_DEFAULT_DIAMOND_ADDRESS=$DEPLOY_TO_DEFAULT_DIAMOND_ADDRESS PRIVATE_KEY=$(getPrivateKey "$NETWORK" "$ENVIRONMENT") DIAMOND_TYPE=$DIAMOND_TYPE forge script "$FULL_SCRIPT_PATH" -f $NETWORK --json --broadcast --skip-simulation --legacy) @@ -234,7 +233,7 @@ deploySingleContract() { RETURN_CODE=$? # print return data only if debug mode is activated - echoDebug "RAW_RETURN_DATA: $RAW_RETURN_DATA" + # echoDebug "RAW_RETURN_DATA: $RAW_RETURN_DATA" # check return data for error message (regardless of return code as this is not 100% reliable) if [[ $RAW_RETURN_DATA == *"\"logs\":[]"* && $RAW_RETURN_DATA == *"\"returns\":{}"* ]]; then diff --git a/script/deploy/healthCheck.ts b/script/deploy/healthCheck.ts index 7300eca46..77dbd1c7d 100644 --- a/script/deploy/healthCheck.ts +++ b/script/deploy/healthCheck.ts @@ -3,6 +3,8 @@ import { consola } from 'consola' import { $, spinner } from 'zx' import { defineCommand, runMain } from 'citty' import * as chains from 'viem/chains' +import * as path from 'path' +import * as fs from 'fs' import { Address, Chain, @@ -16,11 +18,10 @@ import { } from 'viem' import { Network, + networks, getViemChainForNetworkName, type NetworksObject, } from '../utils/viemScriptHelpers' -import data from '../../config/networks.json' -const networks: NetworksObject = data as NetworksObject const SAFE_THRESHOLD = 3 @@ -65,10 +66,6 @@ const main = defineCommand({ }, }, async run({ args }) { - const { getViemChainForNetworkName, networks } = await import( - '../utils/viemScriptHelpers' - ) - if ((await $`${louperCmd}`.exitCode) !== 0) { const answer = await consola.prompt( 'Louper CLI is required but not installed. Would you like to install it now?', @@ -180,7 +177,7 @@ const main = defineCommand({ $.quiet = true const facetsResult = - await $`${louperCmd} inspect diamond -a ${diamondAddress} -n ${chainNameMappings[network]} --json` + await $`${louperCmd} inspect diamond -a ${diamondAddress} -n ${network} --json` const registeredFacets = JSON.parse(facetsResult.stdout).facets.map( (f: { name: string }) => f.name @@ -245,6 +242,7 @@ const main = defineCommand({ address: deployedContracts['LiFiDiamond'], abi: parseAbi([ 'function approvedDexs() external view returns (address[])', + 'function isFunctionApproved(bytes4) external returns (bool)', ]), client: publicClient, }) @@ -281,6 +279,53 @@ const main = defineCommand({ `Found ${numMissing} missing dex${numMissing === 1 ? '' : 's'}` ) + // ╭─────────────────────────────────────────────────────────╮ + // │ Check approved sigs │ + // ╰─────────────────────────────────────────────────────────╯ + + consola.box('Checking DEX signatures approved in diamond...') + // Check if function signatures are approved + const { sigs } = await import(`../../config/sigs.json`) + + // Function to split array into chunks + const chunkArray = (array: T[], chunkSize: number): T[][] => { + const chunks: T[][] = [] + for (let i = 0; i < array.length; i += chunkSize) { + chunks.push(array.slice(i, i + chunkSize)) + } + return chunks + } + + const batchSize = 20 + const sigBatches = chunkArray(sigs, batchSize) + + const sigsToApprove: Hex[] = [] + + for (const batch of sigBatches) { + const calls = batch.map((sig: string) => { + return { + ...dexManager, + functionName: 'isFunctionApproved', + args: [sig], + } + }) + + const results = await publicClient.multicall({ contracts: calls }) + + for (let i = 0; i < results.length; i++) { + if (results[i].status !== 'success' || !results[i].result) { + console.log('Function not approved:', batch[i]) + sigsToApprove.push(batch[i] as Hex) + } + } + } + + if (sigsToApprove.length > 0) { + logError(`Missing ${sigsToApprove.length} DEX signatures`) + } else { + consola.success('No missing signatures.') + } + // ╭─────────────────────────────────────────────────────────╮ // │ Check contract ownership │ // ╰─────────────────────────────────────────────────────────╯ @@ -325,6 +370,33 @@ const main = defineCommand({ publicClient ) + // ╭─────────────────────────────────────────────────────────╮ + // │ Check emergency pause config │ + // ╰─────────────────────────────────────────────────────────╯ + consola.box('Checking emergency pause config...') + const filePath: string = path.join( + '.github', + 'workflows', + 'diamondEmergencyPause.yml' + ) + + try { + const fileContent: string = fs.readFileSync(filePath, 'utf8') + + const networkUpper: string = network.toUpperCase() + const pattern = new RegExp( + `ETH_NODE_URI_${networkUpper}\\s*:\\s*\\$\\{\\{\\s*secrets\\.ETH_NODE_URI_${networkUpper}\\s*\\}\\}` + ) + + const exists: boolean = pattern.test(fileContent) + + if (!exists) { + logError(`Missing ETH_NODE_URI config for ${network} in ${filePath}`) + } + } catch (error: any) { + logError(`Error checking workflow file: ${error.message}`) + } + // ╭─────────────────────────────────────────────────────────╮ // │ Check access permissions │ // ╰─────────────────────────────────────────────────────────╯ @@ -424,9 +496,9 @@ const main = defineCommand({ }, }) -const logError = (string: string) => { - consola.error(string) - errors.push(string) +const logError = (msg: string) => { + consola.error(msg) + errors.push(msg) } const getOwnableContract = (address: Address, client: PublicClient) => { diff --git a/script/deploy/safe/propose-to-safe.ts b/script/deploy/safe/propose-to-safe.ts index 6a3239a02..e6331a02d 100644 --- a/script/deploy/safe/propose-to-safe.ts +++ b/script/deploy/safe/propose-to-safe.ts @@ -10,7 +10,12 @@ import { } from '@safe-global/safe-core-sdk-types' import * as chains from 'viem/chains' import { getSafeUtilityContracts, safeAddresses, safeApiUrls } from './config' -import { getViemChainForNetworkName } from '../../utils/viemScriptHelpers' +import { + NetworksObject, + getViemChainForNetworkName, +} from '../../utils/viemScriptHelpers' +import data from '../../../config/networks.json' +const networks: NetworksObject = data as NetworksObject import consola from 'consola' const retry = async (func: () => Promise, retries = 3): Promise => { @@ -69,12 +74,12 @@ const main = defineCommand({ const config: SafeApiKitConfig = { chainId: BigInt(chain.id), - txServiceUrl: safeApiUrls[args.network.toLowerCase()], + txServiceUrl: networks[args.network.toLowerCase()].safeApiUrl, } const safeService = new SafeApiKit(config) - const safeAddress = safeAddresses[args.network.toLowerCase()] + const safeAddress = networks[args.network.toLowerCase()].safeAddress const rpcUrl = args.rpcUrl || chain.rpcUrls.default.http[0] const provider = new ethers.JsonRpcProvider(rpcUrl) diff --git a/script/helperFunctions.sh b/script/helperFunctions.sh index 8573d540d..cf04eb762 100755 --- a/script/helperFunctions.sh +++ b/script/helperFunctions.sh @@ -1427,8 +1427,8 @@ function verifyContract() { # only show output if DEBUG flag is activated if [[ "$DEBUG" == *"true"* ]]; then if [[ $NETWORK == "zksync" ]]; then - # Verify using foundry-zksync from docker image - docker run --rm -it -v .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge verify-contract --zksync --watch --chain 324 "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" + # Verify using foundry-zksync + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge verify-contract --zksync --watch --chain 324 "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" else forge verify-contract --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" fi @@ -1436,8 +1436,8 @@ function verifyContract() { # TODO: add code that automatically identifies blockscout verification else if [[ $NETWORK == "zksync" ]]; then - # Verify using foundry-zksync from docker image - docker run --rm -it -v .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 + # Verify using foundry-zksync + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 else forge verify-contract --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 fi @@ -1446,15 +1446,15 @@ function verifyContract() { # only show output if DEBUG flag is activated if [[ "$DEBUG" == *"true"* ]]; then if [[ $NETWORK == "zksync" ]]; then - # Verify using foundry-zksync from docker image - docker run --rm -it -v .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" + # Verify using foundry-zksync + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" else forge verify-contract --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" fi else if [[ $NETWORK == "zksync" ]]; then - # Verify using foundry-zksync from docker image - docker run --rm -it -v .:/foundry -u $(id -u):$(id -g) -e FOUNDRY_PROFILE=zksync foundry-zksync forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 + # Verify using foundry-zksync + FOUNDRY_PROFILE=zksync ./foundry-zksync/forge verify-contract --zksync --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 else forge verify-contract --watch --chain "$CHAIN_ID" "$ADDRESS" "$FULL_PATH" --constructor-args $ARGS --skip-is-verified-check -e "${!API_KEY}" >/dev/null 2>&1 fi @@ -3677,6 +3677,146 @@ function updateDiamondLogs() { done playNotificationSound } + +# Function: install_foundry_zksync +# Description: Downloads and installs the zkSync version of foundry tools (forge and cast) +# Arguments: +# $1 - Installation directory (optional, defaults to ./foundry-zksync) +# FOUNDRY_ZKSYNC_VERSION - Environment variable to specify version +# Example Versions: +# FOUNDRY_ZKSYNC_VERSION="nightly-082b6a3610be972dd34aff9439257f4d85ddbf15" +# Returns: +# 0 - Success +# 1 - Failure (with error message) +install_foundry_zksync() { + # Foundry ZKSync version + local FOUNDRY_ZKSYNC_VERSION="nightly-082b6a3610be972dd34aff9439257f4d85ddbf15" + # Allow custom installation directory or use default + local install_dir="${1:-./foundry-zksync}" + + # Verify that FOUNDRY_ZKSYNC_VERSION is set + if [ -z "${FOUNDRY_ZKSYNC_VERSION}" ]; then + echo "Error: FOUNDRY_ZKSYNC_VERSION is not set" + return 1 + fi + + echo "Using Foundry zkSync version: ${FOUNDRY_ZKSYNC_VERSION}" + + # Check if binaries already exist and are executable + # -x tests if a file exists and has execute permissions + if [ -x "${install_dir}/forge" ] && [ -x "${install_dir}/cast" ]; then + echo "forge and cast binaries already exist in ${install_dir} and are executable" + echo "Skipping download and installation" + return 0 + fi + + # Detect operating system + # $OSTYPE is a bash variable that contains the operating system type + local os + if [[ "$OSTYPE" == "darwin"* ]]; then + os="darwin" + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + os="linux" + else + echo "Unsupported operating system" + return 1 + fi + + # Detect CPU architecture + # uname -m returns the machine hardware name + local arch + case $(uname -m) in + x86_64) # Intel/AMD 64-bit + arch="amd64" + ;; + arm64|aarch64) # ARM 64-bit (e.g., Apple Silicon, AWS Graviton) + arch="arm64" + ;; + *) + echo "Unsupported architecture: $(uname -m)" + return 1 + ;; + esac + + # Construct download URL using the specified version + local base_url="https://github.com/matter-labs/foundry-zksync/releases/download/${FOUNDRY_ZKSYNC_VERSION}" + local filename="foundry_nightly_${os}_${arch}.tar.gz" + local download_url="${base_url}/${filename}" + + # Create installation directory if it doesn't exist + # -p flag creates parent directories if needed + mkdir -p "$install_dir" + + # Print detection results + echo "Detected OS: $os" + echo "Detected Architecture: $arch" + echo "Downloading from: $download_url" + echo "Installing to: $install_dir" + + # Download the file using curl or wget, whichever is available + # command -v checks if a command exists + # &> /dev/null redirects both stdout and stderr to null + if command -v curl &> /dev/null; then + # -L flag follows redirects, -o specifies output file + curl -L -o "${install_dir}/${filename}" "$download_url" + elif command -v wget &> /dev/null; then + # -O specifies output file + wget -O "${install_dir}/${filename}" "$download_url" + else + echo "Neither curl nor wget is installed" + return 1 + fi + + # Check if download was successful + # $? contains the return status of the last command + if [ $? -ne 0 ]; then + echo "Download failed" + return 1 + fi + + echo "Download completed successfully" + + # Extract the archive + # -x extract, -z gzip, -f file + echo "Extracting files..." + tar -xzf "${install_dir}/${filename}" -C "$install_dir" + + if [ $? -ne 0 ]; then + echo "Extraction failed" + return 1 + fi + + # Make binaries executable + # +x adds execute permission + echo "Setting executable permissions..." + chmod +x "${install_dir}/forge" "${install_dir}/cast" + + if [ $? -ne 0 ]; then + echo "Failed to set executable permissions" + return 1 + fi + + # Clean up by removing the downloaded archive + echo "Cleaning up..." + rm "${install_dir}/${filename}" + + if [ $? -ne 0 ]; then + echo "Cleanup failed" + return 1 + fi + + # Verify that binaries are executable + # This is a final check to ensure everything worked + if [ ! -x "${install_dir}/forge" ] || [ ! -x "${install_dir}/cast" ]; then + echo "Installation completed but binaries are not executable. Please check permissions." + return 1 + fi + + echo "Installation completed successfully" + echo "Binaries are executable and ready to use" + return 0 +} + # <<<<<< helpers to set/update deployment files/logs/etc # test cases for helper functions diff --git a/script/scriptMaster.sh b/script/scriptMaster.sh index bb35525d1..5e7e32773 100755 --- a/script/scriptMaster.sh +++ b/script/scriptMaster.sh @@ -134,15 +134,8 @@ scriptMaster() { if [[ $NETWORK == "zksync" ]]; then # Use zksync specific scripts DEPLOY_SCRIPT_DIRECTORY="script/deploy/zksync/" - # Check if the foundry-zksync docker image exists - if docker images --format '{{.Repository}}:{{.Tag}}' | grep -q '^foundry-zksync:latest$'; then - echo "The 'foundry-zksync' image already exists. Skipping build." - else - # If it doesn't exist we need to build it - echo "The 'foundry-zksync' image does not exist. Building it now..." - docker build -t foundry-zksync ./foundry-zksync - echo "The 'foundry-zksync' image has been built successfully." - fi + # Check if the foundry-zksync binaries exist, if not fetch them + install_foundry_zksync fi # get user-selected deploy script and contract from list diff --git a/script/tasks/diamondSyncSigs.ts b/script/tasks/diamondSyncSigs.ts index 9374b91b5..814e93b1b 100644 --- a/script/tasks/diamondSyncSigs.ts +++ b/script/tasks/diamondSyncSigs.ts @@ -96,11 +96,23 @@ const main = defineCommand({ // Get list of function signatures to approve const sigsToApprove: Hex[] = [] + let multicallSuccess = true for (let i = 0; i < results.length; i++) { - if (!results[i].result) { - console.log('Function not approved:', sigs[i]) - sigsToApprove.push(sigs[i] as Hex) - } + if (results[i].status == 'success') { + if (!results[i].result) { + console.log('Function not approved:', sigs[i]) + sigsToApprove.push(sigs[i] as Hex) + } + } else multicallSuccess = false + } + + if (!multicallSuccess) { + consola.error( + `The multicall failed, could not check all currently registered signatures. Please use a different RPC for this network and try to run the script again.` + ) + // returning a success code here cause otherwise the wrapping bash script will always run the "old approach" + // and we still end up re-approving all signatures again and again + process.exit(0) } // Instantiate wallet (write enabled) client diff --git a/script/tasks/diamondUpdatePeriphery.sh b/script/tasks/diamondUpdatePeriphery.sh index 56391f034..728a7aafd 100755 --- a/script/tasks/diamondUpdatePeriphery.sh +++ b/script/tasks/diamondUpdatePeriphery.sh @@ -126,7 +126,7 @@ function diamondUpdatePeriphery() { LAST_CALL=1 fi else - echo "[info] contract $CONTRACT not found in target state file > no action required" + warning "contract $CONTRACT not found in target state file. ACTION REQUIRED: Update target state file and try again if this contract should be included." fi done diff --git a/script/utils/fetch-missing-deployments.ts b/script/utils/fetch-missing-deployments.ts index 72d4ab3a9..3e8ed5243 100644 --- a/script/utils/fetch-missing-deployments.ts +++ b/script/utils/fetch-missing-deployments.ts @@ -80,8 +80,9 @@ async function updateDeploymentLogs(network: string) { ADDRESS: contractAddress, OPTIMIZER_RUNS: data.result[0].Runs || 0, TIMESTAMP: new Date().toISOString(), - CONSTRUCTOR_ARGS: - `0x${data.result[0].ConstructorArguments}` || '0x', + CONSTRUCTOR_ARGS: data.result[0].ConstructorArguments + ? normalizeBytes(data.result[0].ConstructorArguments) + : '0x', SALT: '', VERIFIED: true, }, @@ -92,7 +93,6 @@ async function updateDeploymentLogs(network: string) { } } catch (error) { console.error(`Error processing ${contractName}:`, error) - continue } } @@ -105,6 +105,11 @@ async function updateDeploymentLogs(network: string) { } } +const normalizeBytes = (bytes: string): string => { + if (bytes.startsWith('0x')) return bytes + return `0x${bytes}` +} + // Get network from command line arguments const network = process.argv[2] if (!network) { diff --git a/script/utils/viemScriptHelpers.ts b/script/utils/viemScriptHelpers.ts index 357febe82..3057c812e 100644 --- a/script/utils/viemScriptHelpers.ts +++ b/script/utils/viemScriptHelpers.ts @@ -30,7 +30,8 @@ const colors = { red: '\x1b[31m', green: '\x1b[32m', } -const networks: NetworksObject = networksConfig + +export const networks: NetworksObject = networksConfig export const getViemChainForNetworkName = (networkName: string): Chain => { const network = networks[networkName]