From 97f0bfb8354f4208b58c5492964123c53e2eccbf Mon Sep 17 00:00:00 2001 From: Nicolas Lecouflet Date: Wed, 18 Jun 2025 14:30:56 +0200 Subject: [PATCH 1/5] feat: multichain script --- .env.example | 2 - .github/workflows/ci-deep.yml | 6 +- .github/workflows/ci.yml | 6 +- .github/workflows/coverage.yml | 6 +- .gitignore | 1 + bun.lockb | Bin 207752 -> 207760 bytes foundry.toml | 111 +++++++++++++--------------- package.json | 2 +- scripts/DistributionCreator.s.sol | 106 ++++++++++++++++++++++++++ scripts/utils/Base.s.sol | 7 +- test/unit/DistributionCreator.t.sol | 2 +- 11 files changed, 177 insertions(+), 72 deletions(-) diff --git a/.env.example b/.env.example index 058cde75..50871ed5 100644 --- a/.env.example +++ b/.env.example @@ -11,10 +11,8 @@ DEPLOY_SALT="" # Localhost (chainId: X) LOCALHOST_NODE_URI="http://127.0.0.1:8545" -LOCALHOST_MNEMONIC="" LOCALHOST_ETHERSCAN_API_KEY="" # (chainId: ) _NODE_URI="" -_MNEMONIC="" _ETHERSCAN_API_KEY="" diff --git a/.github/workflows/ci-deep.yml b/.github/workflows/ci-deep.yml index f445eced..5c5cfed2 100644 --- a/.github/workflows/ci-deep.yml +++ b/.github/workflows/ci-deep.yml @@ -89,9 +89,9 @@ jobs: - name: Run Foundry tests run: bun foundry:test env: - ETH_NODE_URI_OPTIMISM: ${{ secrets.ETH_NODE_URI_OPTIMISM }} - ETH_NODE_URI_ARBITRUM: ${{ secrets.ETH_NODE_URI_ARBITRUM }} - ETH_NODE_URI_MAINNET: ${{ secrets.ETH_NODE_URI_MAINNET }} + OPTIMISM_NODE_URI: ${{ secrets.ETH_NODE_URI_OPTIMISM }} + ARBITRUM_NODE_URI: ${{ secrets.ETH_NODE_URI_ARBITRUM }} + BASE_NODE_URI: ${{ secrets.ETH_NODE_URI_MAINNET }} FOUNDRY_FUZZ_RUNS: ${{ github.event.inputs.fuzzRuns || '10000' }} - name: 'Add test summary' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d786e7e6..55341953 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,9 +72,9 @@ jobs: run: bun foundry:test env: FOUNDRY_FUZZ_RUNS: '5000' - ETH_NODE_URI_OPTIMISM: ${{ secrets.ETH_NODE_URI_OPTIMISM }} - ETH_NODE_URI_ARBITRUM: ${{ secrets.ETH_NODE_URI_ARBITRUM }} - ETH_NODE_URI_MAINNET: ${{ secrets.ETH_NODE_URI_MAINNET }} + OPTIMISM_NODE_URI: ${{ secrets.ETH_NODE_URI_OPTIMISM }} + ARBITRUM_NODE_URI: ${{ secrets.ETH_NODE_URI_ARBITRUM }} + BASE_NODE_URI: ${{ secrets.ETH_NODE_URI_MAINNET }} - name: 'Add test summary' run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 0126b89b..9d32172e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -24,9 +24,9 @@ jobs: - name: 'Generate the coverage report using the unit and the integration tests' run: 'bun ci:coverage' env: - ETH_NODE_URI_OPTIMISM: ${{ secrets.ETH_NODE_URI_OPTIMISM }} - ETH_NODE_URI_ARBITRUM: ${{ secrets.ETH_NODE_URI_ARBITRUM }} - ETH_NODE_URI_MAINNET: ${{ secrets.ETH_NODE_URI_MAINNET }} + OPTIMISM_NODE_URI: ${{ secrets.ETH_NODE_URI_OPTIMISM }} + ARBITRUM_NODE_URI: ${{ secrets.ETH_NODE_URI_ARBITRUM }} + BASE_NODE_URI: ${{ secrets.ETH_NODE_URI_MAINNET }} - name: 'Upload coverage report to Codecov' uses: 'codecov/codecov-action@v3' diff --git a/.gitignore b/.gitignore index d18d8467..2ea17176 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ bin /out /zkout /cache-forge +/transactions diff --git a/bun.lockb b/bun.lockb index 197a6492bff4ca48892e9a2429390a63d0f125a2..86781f774ab645e5df285239f6e2cd063c91b9e2 100755 GIT binary patch delta 365 zcmeCU&NBgs^pr#w7HO?|box$MT-pJhLZ^~~IpLdMvQPSO4QGEer3k zO$@m8am`byQVCJv7fasFvxuGc;zA2U{f%RF9mf2H#Z5J8hgTP#<=FnTfU#tn*aCJY z1`vqhhtOO$#YM?_)3e!`47bl7BzU{VK4 zZ||SLw2+ZA1FH1LcFRdjITN)_jP%VcEKQSB4UCM^($b90QcRN!(o&L)jT6lbQ!G-G aQ;aN(k`oOL5-p|&PG^$d{#u!NE;|5qKX?@Y delta 366 zcmbPmou}hE&jdZCl`+Yw(i4rUPh55?uyXaD??3JMk^b3_lbPP>c3gKqvg(J{#()Av zz9aG$%!~{mP?GSGdGk3%sTxL=$$^UMlLZ_(H%rdzx#SSEdChil>-*7*j;?i`Q6{!s zs3$36@AP*kP2Pw7o5yW6=O?58hZE|Bl}Y=>Ki5uFPg|WP-Bjdf+O=7v=8DKumW1t3 z3m8kL3C&<<0^1Y9523kirsuOW8E#*~&a{J_vjHl)VS6e+Q!ppz0||(#Bij#3FmVfT z{?LH%ou*&aU~*;EfNhAQ__->6O)qD%*~UM4O0@0%uOv! i42+Wv%nXc-lPnC9lBO#jW|En{U 0) { + console.log(""); + console.log("Failed chains details:"); + for (uint256 i = 0; i < failedCount; i++) { + console.log( + "- %s (Chain ID: %s) - Reason: %s", + failedChains[i].network, + failedChains[i].chainId, + failedChains[i].reason + ); + } + } + + console.log(""); + console.log("Multichain fee setting completed!"); + } +} diff --git a/scripts/utils/Base.s.sol b/scripts/utils/Base.s.sol index 6f23005b..eaf29281 100644 --- a/scripts/utils/Base.s.sol +++ b/scripts/utils/Base.s.sol @@ -58,6 +58,11 @@ abstract contract BaseScript is Script { vm.stopBroadcast(); } + modifier fork(string memory network) { + vm.createSelectFork(vm.rpcUrl(network)); + _; + } + function _serializeJson( uint256 chainId, address to, @@ -89,6 +94,6 @@ abstract contract BaseScript is Script { } string memory finalJson = vm.serializeBytes(json, "data", data); - vm.writeJson(finalJson, "./transaction.json"); + vm.writeJson(finalJson, string.concat("./transactions/", vm.toString(chainId), ".json")); } } diff --git a/test/unit/DistributionCreator.t.sol b/test/unit/DistributionCreator.t.sol index 0f67b16c..437dd833 100644 --- a/test/unit/DistributionCreator.t.sol +++ b/test/unit/DistributionCreator.t.sol @@ -950,7 +950,7 @@ contract DistributionCreatorForkTest is Test { DistributionCreator public creator; function setUp() public { - vm.createSelectFork(vm.envString("ETH_NODE_URI_ARBITRUM")); + vm.createSelectFork(vm.envString("ARBITRUM_NODE_URI")); creator = DistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd); } From f8d937d9b162b81367f636298a2de49e7368c188 Mon Sep 17 00:00:00 2001 From: Nicolas Lecouflet Date: Wed, 25 Jun 2025 16:44:35 +0200 Subject: [PATCH 2/5] feat: bump sdk --- bun.lockb | Bin 207760 -> 207760 bytes package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bun.lockb b/bun.lockb index 86781f774ab645e5df285239f6e2cd063c91b9e2..84413a0d4d327df0c23dd96dffae37d8d9171394 100755 GIT binary patch delta 226 zcmV<803H93*9?%?43I7$X;bPLPxYv22l(iLCHKyGO~3$PY5Rbi@erXAx;Xi0u}*p+ z0S2?lA$NNaI`=@k?*p(e;*?uNRCfpalTe+Q0V|VHAt#d%K?$=No{Z8!*t1eWZN)^) zF0nG8RZK`&7-_syy}-)2gp)Utyc+Q()}DSQvDB0lS_x`=2;>G+R=fh93q65^>1YBk zP{g@dx8-mFG`ImXw;Cw|l=><&FE}(bH90dgHZ?OaW@0!wV`5`4Vlg;oHZ(XmH#9Y5 cIALLAH#9IaGM6F40vwm1lmZU70we>D2S;#Ps{jB1 delta 224 zcmV<603ZL5*9?%?43I7$6`^t}s^ZJsR$gYnEOA0~aGY1O=?9YdCXr8M*G6riu}*p+ zlVBkTlMo^Zv)CbMdzZYJ0T7cAA_$XMosa=4lTjfjlMq1(vl*U@(m({|gJZvmXkMvT zOSE>dyDKZzo=zIHq1* Date: Mon, 11 Aug 2025 09:02:05 +0200 Subject: [PATCH 3/5] feat: chain utils --- bun.lock | 5 +- foundry.toml | 4 +- helpers/foundryMultiChainScript.sh | 4 +- package.json | 1 + scripts/Disputer.s.sol | 58 ++++++ scripts/DistributionCreator.s.sol | 105 +--------- scripts/Distributor.s.sol | 66 ++++++ scripts/utils/ChainUtils.s.sol | 316 +++++++++++++++++++++++++++++ 8 files changed, 457 insertions(+), 102 deletions(-) create mode 100644 scripts/utils/ChainUtils.s.sol diff --git a/bun.lock b/bun.lock index 16075e12..f490beab 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "name": "merkl-contracts", "devDependencies": { "@angleprotocol/sdk": "^2.41.43", + "@merkl/registry": "latest", "@openzeppelin/contracts": "^4.9.0", "@openzeppelin/contracts-upgradeable": "4.9.0", "forge-std": "github:foundry-rs/forge-std#v1.9.4", @@ -96,7 +97,7 @@ "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], - "@merkl/registry": ["@merkl/registry@0.1.14", "", {}, "sha512-rs0QrZlPHeGPhZN7e0FX5vXu8AGMTE2EWPtg1Ir0ciTTNlc3ZKQ0so4gw3sPP2orhiXn9RuUy3KAMj+0YWakSQ=="], + "@merkl/registry": ["@merkl/registry@0.1.88", "", {}, "sha512-Oabu5U0yFWuo7PYOj2AGhx4cdntXf5EIuHtdouTWEEIy3SedlP37eOaoKu+6rxa9iRE/HvXg9l/SzGr2OKYo4w=="], "@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], @@ -998,6 +999,8 @@ "typechain/glob": ["glob@7.1.7", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ=="], + "utils/@merkl/registry": ["@merkl/registry@0.1.14", "", {}, "sha512-rs0QrZlPHeGPhZN7e0FX5vXu8AGMTE2EWPtg1Ir0ciTTNlc3ZKQ0so4gw3sPP2orhiXn9RuUy3KAMj+0YWakSQ=="], + "web3-utils/@ethereumjs/util": ["@ethereumjs/util@8.1.0", "", { "dependencies": { "@ethereumjs/rlp": "^4.0.1", "ethereum-cryptography": "^2.0.0", "micro-ftch": "^0.3.1" } }, "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA=="], "web3-utils/ethereum-cryptography": ["ethereum-cryptography@2.2.1", "", { "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", "@scure/bip32": "1.4.0", "@scure/bip39": "1.3.0" } }, "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg=="], diff --git a/foundry.toml b/foundry.toml index 7977cc44..236e3a1c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,7 +9,7 @@ cache_path = 'cache-forge' gas_reports = ["*"] optimizer_runs = 100 fs_permissions = [ - { access = "read", path = "./node_modules/@angleprotocol/sdk/dist/src/registry/registry.json" }, + { access = "read", path = "./node_modules/@merkl/registry/dist/src/registry.json" }, { access = "write", path = "./transactions" }, ] solc = "0.8.25" @@ -27,7 +27,7 @@ cache_path = 'cache-forge' gas_reports = ["*"] optimizer_runs = 100 fs_permissions = [ - { access = "read", path = "./node_modules/@angleprotocol/sdk/dist/src/registry/registry.json" }, + { access = "read", path = "./node_modules/@merkl/registry/dist/src/registry.json" }, { access = "write", path = "./transaction.json" }, { access = "write", path = "./transactions.json" } ] diff --git a/helpers/foundryMultiChainScript.sh b/helpers/foundryMultiChainScript.sh index f200242d..d6e9c2e0 100755 --- a/helpers/foundryMultiChainScript.sh +++ b/helpers/foundryMultiChainScript.sh @@ -9,7 +9,7 @@ function usage { # Get list of chain IDs where DistributionCreator is deployed function get_available_chains() { - local registry_file="node_modules/@angleprotocol/sdk/dist/src/registry/registry.json" + local registry_file="node_modules/@merkl/registry/dist/src/registry.json" if [ ! -f "$registry_file" ]; then echo "Registry file not found!" exit 1 @@ -113,7 +113,7 @@ function main { fi # Path to the registry file - registry_file="node_modules/@angleprotocol/sdk/dist/src/registry/registry.json" + registry_file="node_modules/@merkl/registry/dist/src/registry.json" if [ ! -f "$registry_file" ]; then echo "Registry file not found!" diff --git a/package.json b/package.json index 00bc003f..6529adb3 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "url": "https://github.com/AngleProtocol/merkl-contracts/issues" }, "devDependencies": { + "@merkl/registry": "latest", "@angleprotocol/sdk": "^2.41.43", "@openzeppelin/contracts": "^4.9.0", "@openzeppelin/contracts-upgradeable": "4.9.0", diff --git a/scripts/Disputer.s.sol b/scripts/Disputer.s.sol index 259dd095..d3fdc35c 100644 --- a/scripts/Disputer.s.sol +++ b/scripts/Disputer.s.sol @@ -8,6 +8,9 @@ import { JsonReader } from "@utils/JsonReader.sol"; import { BaseScript } from "./utils/Base.s.sol"; import { Disputer } from "../contracts/Disputer.sol"; import { Distributor } from "../contracts/Distributor.sol"; +import { MockToken } from "../contracts/mock/MockToken.sol"; +import { TokensUtils } from "./utils/TokensUtils.sol"; +import { CreateXConstants } from "./utils/CreateXConstants.sol"; // Base contract with shared constants and utilities contract DisputerScript is BaseScript, JsonReader { @@ -210,3 +213,58 @@ contract ToggleDispute is DisputerScript { console.log("Toggled dispute for:", _reason); } } + +contract DeployWithCreate is DisputerScript, TokensUtils, CreateXConstants { + function run(address disputeToken) external broadcast { + uint256 chainId = block.chainid; + address distributor = readAddress(chainId, "Distributor"); + + deployDisputer(distributor, disputeToken); + } + + function deployDisputer(address distributor, address disputeToken) public returns (address) { + console.log("\n=== Deploying Disputer ==="); + + bytes32 salt = vm.envBytes32("DEPLOY_SALT"); + + // Check if CREATEX contract is deployed + address disputer; + // if (CREATEX.code.length == 0) { + address CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + // if (CREATE2_DEPLOYER.code.length != 0) { + + // // Deploy using the standard Deterministic CREATE2 deployer and a deterministic salt + // disputer = address(new Disputer{ salt: salt }(broadcaster, DISPUTER_WHITELIST, Distributor(distributor))); + // } else { + // // Classic deployment if CREATE2 deployer is not deployed + // // disputer = address(new Disputer(broadcaster, DISPUTER_WHITELIST, Distributor(distributor))); + // } + // } else { + // Deploy using CreateX + // Create initialization bytecode + bytes + memory bytecode = hex"60806040523480156200001157600080fd5b506040516200137738038062001377833981016040819052620000349162000322565b6200003f33620001b3565b600180546001600160a01b0319166001600160a01b0383169081179091556040805163c748d26160e01b8152905163c748d261916004808201926020929091908290030181865afa15801562000099573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000bf91906200041f565b60405163095ea7b360e01b81526001600160a01b0383811660048301526000196024830152919091169063095ea7b3906044016020604051808303816000875af115801562000112573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000138919062000446565b50815160005b818110156200019d576001600260008684815181106200016257620001626200046a565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790556001016200013e565b50620001a98462000203565b5050505062000480565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6200020d62000286565b6001600160a01b038116620002785760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6200028381620001b3565b50565b6000546001600160a01b03163314620002e25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200026f565b565b6001600160a01b03811681146200028357600080fd5b80516200030781620002e4565b919050565b634e487b7160e01b600052604160045260246000fd5b6000806000606084860312156200033857600080fd5b83516200034581620002e4565b602085810151919450906001600160401b03808211156200036557600080fd5b818701915087601f8301126200037a57600080fd5b8151818111156200038f576200038f6200030c565b8060051b604051601f19603f83011681018181108582111715620003b757620003b76200030c565b60405291825284820192508381018501918a831115620003d657600080fd5b938501935b82851015620003ff57620003ef85620002fa565b84529385019392850192620003db565b8097505050505050506200041660408501620002fa565b90509250925092565b6000602082840312156200043257600080fd5b81516200043f81620002e4565b9392505050565b6000602082840312156200045957600080fd5b815180151581146200043f57600080fd5b634e487b7160e01b600052603260045260246000fd5b610ee780620004906000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80639b19251a11610081578063ca85e5d01161005b578063ca85e5d0146101bb578063e43252d7146101ce578063f2fde38b146101e157600080fd5b80639b19251a14610155578063bfe1092814610188578063c1075329146101a857600080fd5b806375619ab5116100b257806375619ab5146100eb5780638ab1d681146100fe5780638da5cb5b1461011157600080fd5b80631c20fadd146100ce578063715018a6146100e3575b600080fd5b6100e16100dc366004610c1d565b6101f4565b005b6100e161029b565b6100e16100f9366004610c5e565b6102af565b6100e161010c366004610c5e565b61055e565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610178610163366004610c5e565b60026020526000908152604090205460ff1681565b604051901515815260200161014c565b60015461012b9073ffffffffffffffffffffffffffffffffffffffff1681565b6100e16101b6366004610c82565b6105b2565b6100e16101c9366004610cdd565b610659565b6100e16101dc366004610c5e565b6109f2565b6100e16101ef366004610c5e565b610a49565b6101fc610b05565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102959190610dac565b50505050565b6102a3610b05565b6102ad6000610b86565b565b6102b7610b05565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c748d2616040518163ffffffff1660e01b8152600401602060405180830381865afa158015610324573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103489190610dce565b6001546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000602482015291169063095ea7b3906044016020604051808303816000875af11580156103c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e49190610dac565b50600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117909155604080517fc748d261000000000000000000000000000000000000000000000000000000008152905163c748d261916004808201926020929091908290030181865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190610dce565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6024830152919091169063095ea7b3906044016020604051808303816000875af1158015610536573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055a9190610dac565b5050565b610566610b05565b73ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6105ba610b05565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610614576040519150601f19603f3d011682016040523d82523d6000602084013e610619565b606091505b5050905080610654576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b3360009081526002602052604090205460ff166106a2576040517f584a793800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600154604080517fc748d261000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c748d2619160048083019260209291908290030181865afa158015610712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107369190610dce565b90506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166309454ba36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cb9190610deb565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190610deb565b9050818110156109645773ffffffffffffffffffffffffffffffffffffffff83166323b872dd33306108918587610e04565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff938416600482015292909116602483015260448201526064016020604051808303816000875af115801561090a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092e9190610dac565b610964576040517fb1eb39bb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546040517f2a25dd4100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632a25dd41906109ba908790600401610e44565b600060405180830381600087803b1580156109d457600080fd5b505af11580156109e8573d6000803e3d6000fd5b5050505050505050565b6109fa610b05565b73ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b610a51610b05565b73ffffffffffffffffffffffffffffffffffffffff8116610af9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610b0281610b86565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610af0565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b0257600080fd5b600080600060608486031215610c3257600080fd5b8335610c3d81610bfb565b92506020840135610c4d81610bfb565b929592945050506040919091013590565b600060208284031215610c7057600080fd5b8135610c7b81610bfb565b9392505050565b60008060408385031215610c9557600080fd5b8235610ca081610bfb565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610cef57600080fd5b813567ffffffffffffffff80821115610d0757600080fd5b818401915084601f830112610d1b57600080fd5b813581811115610d2d57610d2d610cae565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610d7357610d73610cae565b81604052828152876020848701011115610d8c57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610dbe57600080fd5b81518015158114610c7b57600080fd5b600060208284031215610de057600080fd5b8151610c7b81610bfb565b600060208284031215610dfd57600080fd5b5051919050565b81810381811115610e3e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60006020808352835180602085015260005b81811015610e7257858101830151858201604001528201610e56565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea26469706673582212202c48aee5de4959ef518786fa36afffd4b4a0c2f4af9e25741d18037fdf60170b64736f6c63430008180033000000000000000000000000a9ddd91249dfdd450e81e1c56ab60e1a6265170100000000000000000000000000000000000000000000000000000000000000600000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000ea05f9001fbdea6d4280879f283ff9d0b282060e0000000000000000000000000dd2ea40a3561c309c03b96108e78d06e8a1a99b000000000000000000000000f4c94b2fdc2efa4ad4b831f312e7ef74890705da"; + + // Deploy using the specified CREATE2 deployer and a deterministic salt + bytes memory callData = abi.encodeWithSignature("deployCreate2(bytes32,bytes)", salt, bytecode); + (bool success, bytes memory returnData) = CREATEX.call(callData); + + require(success, "CREATE2 deployment failed"); + disputer = address(uint160(uint256(bytes32(returnData)))); + + console.log("Disputer:", disputer); + + // // Transfer ownership to multisig + // console.log("Transferred Disputer ownership to multisig:", multisig); + // Disputer(disputer).transferOwnership(multisig); + + // // Send dispute tokens to disputer + // uint256 amount = 100 * 10 ** MockToken(disputeToken).decimals(); + // if (MockToken(disputeToken).balanceOf(broadcaster) >= amount) { + // transferERC20Tokens(disputer, 100 * 10 ** MockToken(disputeToken).decimals(), disputeToken); + // console.log("Sent dispute tokens to disputer:", 100 * 10 ** MockToken(disputeToken).decimals()); + // } + + return address(disputer); + } +} diff --git a/scripts/DistributionCreator.s.sol b/scripts/DistributionCreator.s.sol index 0e92958d..fdc60687 100644 --- a/scripts/DistributionCreator.s.sol +++ b/scripts/DistributionCreator.s.sol @@ -183,8 +183,8 @@ contract RecoverFees is DistributionCreatorScript { contract SetUserFeeRebate is DistributionCreatorScript { function run() external { // MODIFY THESE VALUES TO SET YOUR DESIRED USER AND REBATE - address user = address(0x59A1A709c84C125F135C126ac46bE2A11b6f1bA4); - uint256 rebate = 250_000_000; + address user = address(0xFc6960197CDF33B6bfa0569E3fbe539947DDfa44); + uint256 rebate = 750000000; _run(user, rebate); } @@ -361,106 +361,17 @@ contract CreateCampaign is DistributionCreatorScript { function run() external broadcast { bytes memory campaignData; // MODIFY THESE VALUES TO SET YOUR DESIRED CAMPAIGN PARAMETERS - // address targetToken = address(0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba); - // uint32 campaignType = 22; - // uint32 subCampaignType = 0; - // uint256 tokenId = 0; - // address[] memory whitelist = new address[](0); - // address[] memory blacklist = new address[](0); - // string memory url = "https://app.hyperdrive.box/market/100/0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba"; - // bytes[] memory hooks = new bytes[](0); - // string memory apr = "1"; - // bool targetTokenPricing = true; - // bool rewardTokenPricing = false; - // bytes memory campaignData = abi.encode( - // targetToken, - // subCampaignType, - // tokenId, - // whitelist, - // blacklist, - // url, - // hooks, - // apr, - // targetTokenPricing, - // rewardTokenPricing - // ); - // // - - // address targetToken = address(0x324395D5d835F84a02A75Aa26814f6fD22F25698); - // uint32 campaignType = 21; - // uint32 subCampaignType = 2; - // uint256 tokenId = 0; - // address[] memory whitelist = new address[](0); - // address[] memory blacklist = new address[](0); - // string memory url = "https://app.hyperdrive.box/market/1/0x324395D5d835F84a02A75Aa26814f6fD22F25698"; - // bytes[] memory hooks = new bytes[](0); - // campaignData = abi.encode(targetToken, subCampaignType, tokenId, whitelist, blacklist, url, hooks); - // address rewardToken = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); - - address targetToken = address(0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba); - uint32 campaignType = 21; - uint32 subCampaignType = 2; - uint256 tokenId = 0; - address[] memory whitelist = new address[](0); - address[] memory blacklist = new address[](0); - string memory url = "https://app.hyperdrive.box/market/100/0xEe9BFf933aDD313C4289E98dA80fEfbF9d5Cd9Ba"; - bytes[] memory hooks = new bytes[](0); - campaignData = abi.encode(targetToken, subCampaignType, tokenId, whitelist, blacklist, url, hooks); - address rewardToken = address(0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d); - - // - - // address targetToken = address(0x004626A008B1aCdC4c74ab51644093b155e59A23); - // uint32 campaignType = 1; - // address[] memory whitelist = new address[](0); - // address[] memory blacklist = new address[](0); - // string memory url = ""; - // bytes[] memory forwarders = new bytes[](0); - // bytes[] memory hooks = new bytes[](0); - // bytes memory campaignData = abi.encode(targetToken, whitelist, blacklist, url, forwarders, hooks, hex""); - - // uint32 campaignType = 26; - // { - // address baseToken = address(0); - // address quoteToken = 0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34; - // uint256 poolIdx = 420; - // bool isOutOfRangeIncentivized = false; - // uint32 weightFees = 2000; - // uint32 weightToken0 = 3000; - // uint32 weightToken1 = 5000; - // address[] memory whitelist = new address[](0); - // address[] memory blacklist = new address[](0); - // string - // memory url = "https://ambient.finance/trade/market/chain=0x783&tokenA=0x0000000000000000000000000000000000000000&tokenB=0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34"; - // bytes[] memory hooks = new bytes[](0); - // bytes[] memory forwarders = new bytes[](0); - // campaignData = abi.encode( - // baseToken, - // quoteToken, - // poolIdx, - // isOutOfRangeIncentivized, - // weightFees, - // weightToken0, - // weightToken1, - // whitelist, - // blacklist, - // url, - // forwarders, - // hooks, - // hex"" - // ); - // } - // END + address rewardToken = address(0xB63B9f0eb4A6E6f191529D71d4D88cc8900Df2C9); CampaignParameters memory campaign = CampaignParameters({ campaignId: bytes32(0), creator: address(0), rewardToken: rewardToken, - amount: 5000 * 10 ** (IERC20Metadata(rewardToken).decimals()), - campaignType: campaignType, - startTimestamp: 1740063600, - duration: 30 days, - campaignData: campaignData + amount: 9867825382083116891581, + campaignType: 56, + startTimestamp: 1752764400, + duration: 385200, + campaignData: hex"00000000000000000000000084bbc0be5a6f831a4e2c28a2f3b892c70acaa5b3000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000009fee01e948353e0897968a3ea955815aaa49f58d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }); _run(campaign); } diff --git a/scripts/Distributor.s.sol b/scripts/Distributor.s.sol index f4afb71d..9bc109ed 100644 --- a/scripts/Distributor.s.sol +++ b/scripts/Distributor.s.sol @@ -6,10 +6,13 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { JsonReader } from "@utils/JsonReader.sol"; import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { ChainUtils, IMultiChainScript } from "./utils/ChainUtils.s.sol"; import { BaseScript } from "./utils/Base.s.sol"; import { Distributor, MerkleTree } from "../contracts/Distributor.sol"; import { IAccessControlManager } from "../contracts/interfaces/IAccessControlManager.sol"; +import { AccessControlManager } from "../contracts/AccessControlManager.sol"; // Base contract with shared utilities contract DistributorScript is BaseScript, JsonReader {} @@ -324,3 +327,66 @@ contract BuildUpgradeToPayload is DistributorScript { return readAddress(chainId, key); } } + +contract DisputeCheck is DistributorScript, ChainUtils { + function run() external broadcast { + uint256 chainId = block.chainid; + address _distributor = readAddress(chainId, "Distributor"); + address _core = readAddress(chainId, "CoreMerkl"); + address _multisig = readAddress(chainId, "Multisig"); + address _proxyAdmin = readAddress(chainId, "ProxyAdmin"); + + // Now we can call verifyRegistryAddresses directly! + verifyRegistryAddresses(_distributor, _core, _multisig, _proxyAdmin); + + uint256 disputeAmount = Distributor(_distributor).disputeAmount(); + address disputeToken = address(Distributor(_distributor).disputeToken()); + console.log("Dispute amount:", disputeAmount); + console.log("Dispute token:", disputeToken); + + // deployCreateX(); + if (disputeAmount == 0 && disputeToken == address(0)) { + disputeAmount = 100 * 10 ** 6; + disputeToken = address(0x79A02482A880bCE3F13e09Da970dC34db4CD24d1); // worldchain 480 + + bytes memory setDisputeTokenPayload = abi.encodeWithSelector( + Distributor.setDisputeToken.selector, + disputeToken + ); + + // address safe = readAddress(chainId, "AngleLabs"); + // console.log("Safe address: %s", safe); + address safe = readAddress(chainId, "Multisig"); + _serializeJson( + chainId, + _distributor, // target address (the DistributionCreator proxy) + 0, // value + setDisputeTokenPayload, // setFees call + Operation.Call, // standard call (not delegate) + hex"", // signature + safe // safe address + ); + // Distributor(distributor).setDisputeAmount(disputeAmount); + // Distributor(distributor).setDisputeToken(IERC20(disputeToken)); + // Distributor(distributor).setDisputePeriod(1); + } + } +} + +// New MultiChain version of the existing DisputeCheck +contract DisputeCheckMultiChain is DistributorScript, ChainUtils { + function run() external { + // Run dispute check across all chains without using address(this) + bytes memory emptyData = ""; + executeAcrossChains(address(0), emptyData, false); + } + + // Override the executeScript function to run our dispute check logic + function executeScript( + address /* scriptContract */, + bytes memory /* data */ + ) internal override returns (bool success, string memory errorReason) { + new DisputeCheck().run(); + return (true, ""); + } +} diff --git a/scripts/utils/ChainUtils.s.sol b/scripts/utils/ChainUtils.s.sol new file mode 100644 index 00000000..b17ca988 --- /dev/null +++ b/scripts/utils/ChainUtils.s.sol @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.17; + +import { console } from "forge-std/console.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { JsonReader } from "@utils/JsonReader.sol"; +import { BaseScript } from "./Base.s.sol"; + +// Interface for scripts that can be executed across chains +interface IMultiChainScript { + function executeOnChain() external; + function executeOnChain(bytes calldata data) external; +} + +contract ChainUtils is JsonReader { + struct FailedChain { + string network; + uint256 chainId; + string reason; + } + + struct ExecutionResult { + string network; + uint256 chainId; + bool success; + string reason; + bytes returnData; + } + + // Events for better tracking + event ChainExecutionStarted(string network, uint256 chainId); + event ChainExecutionCompleted(string network, uint256 chainId, bool success); + event ChainExecutionFailed(string network, uint256 chainId, string reason); + + function externalReadAddress(uint256 chainId, string memory key) public view returns (address) { + return readAddress(chainId, key); + } + + // Registry verification function + function verifyRegistryAddresses( + address _distributor, + address _core, + address _multisig, + address _proxyAdmin + ) public view { + bytes memory coreData; + (bool success, bytes memory returnData) = _distributor.staticcall(abi.encodeWithSignature("core()")); + if (success) { + coreData = returnData; + } else { + (bool success2, bytes memory returnData2) = _distributor.staticcall( + abi.encodeWithSignature("accessControlManager()") + ); + require(success2, "Invalid accessControlManager()"); + coreData = returnData2; + } + + // We need to skip the first 12 bytes (function selector + padding) to get the address + address core = address(uint160(uint256(bytes32(coreData)))); + bytes32 proxyAdminData = vm.load(core, 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103); + address proxyAdmin = address(uint160(uint256(proxyAdminData))); + address multisig = ProxyAdmin(proxyAdmin).owner(); + + if (core != _core) { + console.log("Core merkl mismatch for chain", block.chainid); + } + + if (proxyAdmin != _proxyAdmin) { + console.log("Proxy admin mismatch for chain", block.chainid); + } + + if (multisig != _multisig) { + console.log("Multisig mismatch for chain", block.chainid); + } + } + + // Multi-chain execution logic (can be used by script contracts that inherit this) + function executeAcrossChains(address scriptContract, bytes memory data, bool verificationOnly) internal { + // Get all networks from foundry.toml + string[2][] memory networks = vm.rpcUrls(); + + // Track results + ExecutionResult[] memory results = new ExecutionResult[](networks.length); + uint256 totalChains = 0; + uint256 successCount = 0; + uint256 failedCount = 0; + + if (verificationOnly) { + console.log("=== MULTICHAIN VERIFICATION STARTED ==="); + } else { + console.log("=== MULTICHAIN EXECUTION STARTED ==="); + } + + for (uint256 i = 0; i < networks.length; i++) { + string memory network = networks[i][0]; + + // Skip localhost, fork, and zksync + if ( + keccak256(abi.encodePacked(network)) == keccak256(abi.encodePacked("localhost")) || + keccak256(abi.encodePacked(network)) == keccak256(abi.encodePacked("fork")) || + keccak256(abi.encodePacked(network)) == keccak256(abi.encodePacked("zksync")) + ) { + continue; + } + + // Create fork for this network + bool forkSuccess = true; + try vm.createSelectFork(network) { + // Fork creation succeeded + } catch { + forkSuccess = false; + console.log("[FAILED] Failed to create fork for network:", network); + } + + if (forkSuccess) { + uint256 chainId = block.chainid; + emit ChainExecutionStarted(network, chainId); + + results[totalChains] = ExecutionResult({ + network: network, + chainId: chainId, + success: false, + reason: "", + returnData: "" + }); + + if (verificationOnly) { + // Perform registry verification + address _distributor = readAddress(chainId, "Distributor"); + address _core = readAddress(chainId, "CoreMerkl"); + address _multisig = readAddress(chainId, "Multisig"); + address _proxyAdmin = readAddress(chainId, "ProxyAdmin"); + + verifyRegistryAddresses(_distributor, _core, _multisig, _proxyAdmin); + results[totalChains].success = true; + successCount++; + console.log("[SUCCESS] Verification completed for", network); + console.log("Chain ID:", chainId); + } else { + // Execute script + (bool scriptSuccess, string memory errorReason) = executeScript(scriptContract, data); + + if (scriptSuccess) { + results[totalChains].success = true; + successCount++; + emit ChainExecutionCompleted(network, chainId, true); + console.log("[SUCCESS] Script execution completed for", network); + console.log("Chain ID:", chainId); + } else { + results[totalChains].reason = errorReason; + failedCount++; + emit ChainExecutionFailed(network, chainId, errorReason); + console.log("[FAILED] Script execution failed for", network); + console.log("Chain ID:", chainId); + console.log("Reason:", errorReason); + } + } + + totalChains++; + } + } + + // Display summary + displaySummary(results, totalChains, successCount, failedCount, verificationOnly); + } + + // Execute a specific script with error handling + function executeScript( + address scriptContract, + bytes memory data + ) internal virtual returns (bool success, string memory errorReason) { + if (scriptContract == address(0)) { + return (false, "Script contract cannot be zero address"); + } + + // Try different execution methods based on what the script supports + if (data.length > 0) { + // Try to call with data first + (bool success1, ) = scriptContract.call(abi.encodeWithSignature("executeOnChain(bytes)", data)); + if (success1) { + return (true, ""); + } + } + + // Fall back to parameterless execution + (bool success2, ) = scriptContract.call(abi.encodeWithSignature("executeOnChain()")); + + if (success2) { + return (true, ""); + } + + // If both fail, try calling the run() function directly + (bool success3, ) = scriptContract.call(abi.encodeWithSignature("run()")); + if (success3) { + return (true, ""); + } + + return (false, "All script execution methods failed"); + } + + // Execute script on a single chain + function executeOnSingleChain( + string calldata network, + address scriptContract, + bytes memory data + ) internal returns (bool success, string memory errorReason) { + try vm.createSelectFork(network) { + uint256 chainId = block.chainid; + console.log("Executing script on", network); + console.log("Chain ID:", chainId); + + return executeScript(scriptContract, data); + } catch { + return (false, "Failed to create fork for network"); + } + } + + function displaySummary( + ExecutionResult[] memory results, + uint256 totalChains, + uint256 successCount, + uint256 failedCount, + bool verificationOnly + ) internal pure { + console.log(""); + if (verificationOnly) { + console.log("=== MULTICHAIN VERIFICATION SUMMARY ==="); + } else { + console.log("=== MULTICHAIN EXECUTION SUMMARY ==="); + } + console.log("Total chains processed:", totalChains); + console.log("Successful chains:", successCount); + console.log("Failed chains:", failedCount); + + if (failedCount > 0) { + console.log(""); + console.log("Failed chains details:"); + for (uint256 i = 0; i < totalChains; i++) { + if (!results[i].success) { + console.log("- Network:", results[i].network); + console.log(" Chain ID:", results[i].chainId); + console.log(" Reason:", results[i].reason); + } + } + } + + console.log(""); + if (verificationOnly) { + console.log("Multichain verification completed!"); + } else { + console.log("Multichain execution completed!"); + } + } +} + +// Script contract for running ChainUtils operations +contract ChainUtilsScript is BaseScript, ChainUtils { + // Original verification-only run function + function run() external { + runVerification(); + } + + // Execute script across all chains + function runScript(address scriptContract) external { + bytes memory emptyData = ""; + executeAcrossChains(scriptContract, emptyData, false); + } + + function runScript(address scriptContract, bytes memory data) external { + executeAcrossChains(scriptContract, data, false); + } + + // Execute script on a single specific chain + function runScriptOnChain(string calldata network, address scriptContract) external { + bytes memory emptyData = ""; + (bool success, string memory errorReason) = executeOnSingleChain(network, scriptContract, emptyData); + + if (success) { + console.log("[SUCCESS] Script executed successfully on", network); + } else { + console.log("[FAILED] Script failed on", network); + console.log("Reason:", errorReason); + } + } + + function runScriptOnChain(string calldata network, address scriptContract, bytes memory data) external { + (bool success, string memory errorReason) = executeOnSingleChain(network, scriptContract, data); + + if (success) { + console.log("[SUCCESS] Script executed successfully on", network); + } else { + console.log("[FAILED] Script failed on", network); + console.log("Reason:", errorReason); + } + } + + // Verify registries across all chains + function runVerification() public { + bytes memory emptyData = ""; + executeAcrossChains(address(0), emptyData, true); + } + + // Verify registry on a single chain + function runVerificationOnChain(string calldata network) external { + vm.createSelectFork(network); + uint256 chainId = block.chainid; + + address _distributor = readAddress(chainId, "Distributor"); + address _core = readAddress(chainId, "CoreMerkl"); + address _multisig = readAddress(chainId, "Multisig"); + address _proxyAdmin = readAddress(chainId, "ProxyAdmin"); + + verifyRegistryAddresses(_distributor, _core, _multisig, _proxyAdmin); + console.log("[SUCCESS] Registry verification completed for", network); + } +} From f2655e4c4e575c3bba33922c61518bb28b11d821 Mon Sep 17 00:00:00 2001 From: Nicolas Lecouflet Date: Thu, 9 Oct 2025 09:20:52 +0200 Subject: [PATCH 4/5] fix: ci --- scripts/DistributionCreator.s.sol | 1 - scripts/deployPullTokenWrapperWithAllow.s.sol | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/DistributionCreator.s.sol b/scripts/DistributionCreator.s.sol index f719f8a0..58fd3b1d 100644 --- a/scripts/DistributionCreator.s.sol +++ b/scripts/DistributionCreator.s.sol @@ -226,7 +226,6 @@ contract SetRewardTokenMinAmounts is DistributionCreatorScript { uint256 chainId = block.chainid; address creatorAddress = readAddress(chainId, "DistributionCreator"); - address creatorAddress = 0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd; DistributionCreator(creatorAddress).setRewardTokenMinAmounts(_tokens, _amounts); console.log("Minimum amounts updated for %s tokens", _tokens.length); diff --git a/scripts/deployPullTokenWrapperWithAllow.s.sol b/scripts/deployPullTokenWrapperWithAllow.s.sol index 77fc5556..d107caba 100644 --- a/scripts/deployPullTokenWrapperWithAllow.s.sol +++ b/scripts/deployPullTokenWrapperWithAllow.s.sol @@ -41,7 +41,12 @@ contract DeployPullTokenWrapperWithAllow is BaseScript { // Initialize PullTokenWrapperWithAllow(address(proxy)).initialize(underlying, distributionCreator, minter, name, symbol); - DistributionCreator(distributionCreator).setRewardTokenMinAmounts([address(proxy)], [1e18]); // Set the minimum amount for the token wrapper + address[] tokens; + tokens[0] = address(proxy); + + uint256[] amounts; + amounts[0] = 1e18; + DistributionCreator(distributionCreator).setRewardTokenMinAmounts(tokens, amounts); // Set the minimum amount for the token wrapper vm.stopBroadcast(); } From d811bb6190e7d42d1f99c3c88067d24733192c15 Mon Sep 17 00:00:00 2001 From: Nicolas Lecouflet Date: Thu, 9 Oct 2025 09:22:36 +0200 Subject: [PATCH 5/5] fix: ci --- scripts/deployPullTokenWrapperWithAllow.s.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/deployPullTokenWrapperWithAllow.s.sol b/scripts/deployPullTokenWrapperWithAllow.s.sol index d107caba..750f38ab 100644 --- a/scripts/deployPullTokenWrapperWithAllow.s.sol +++ b/scripts/deployPullTokenWrapperWithAllow.s.sol @@ -41,10 +41,10 @@ contract DeployPullTokenWrapperWithAllow is BaseScript { // Initialize PullTokenWrapperWithAllow(address(proxy)).initialize(underlying, distributionCreator, minter, name, symbol); - address[] tokens; + address[] memory tokens; tokens[0] = address(proxy); - uint256[] amounts; + uint256[] memory amounts; amounts[0] = 1e18; DistributionCreator(distributionCreator).setRewardTokenMinAmounts(tokens, amounts); // Set the minimum amount for the token wrapper