🔨 contracts: support hyperlane on redeployer - #860
Conversation
🦋 Changeset detectedLatest commit: fe87fd2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds Hyperlane/mailbox infrastructure via deploy accounts, remappings, and dependency updates. Introduces HypEXA script contract with router deployment via CREATE3/proxy, aggregation hook/ISM composition, timelock-based BRIDGE_ROLE scheduling, and pausable component rotation. Updates Redeployer to deploy EXA implementation, perform two-phase initialization, and migrate proxy admin to ProxyAdmin via ProxyAdminMigrator. Adds comprehensive forked HypEXA tests covering multi-hop round-trips, authorization, pausing, and rotation flows. Refreshes gas snapshots and adds new Redeployer tests validating proxy admin migration and ERC20 preservation. ChangesHypEXA and Redeployer integration
Sequence DiagramsequenceDiagram
autonumber
participant User as "User/Script"
participant Redeployer as "Redeployer"
participant HypEXA as "HypEXA"
participant ProxyAdmin as "ProxyAdmin"
participant ProxyAdminMigrator as "ProxyAdminMigrator"
participant EXA as "EXA Token"
participant Timelock as "TimelockController"
participant Router as "HypXERC20 Router"
participant Mailbox as "Hyperlane Mailbox"
User->>Redeployer: deployEXA(proxy)
Redeployer->>Redeployer: deployEXAImpl() if needed
Redeployer->>ProxyAdmin: upgradeAndCall(impl, initialize)
ProxyAdmin->>EXA: initialize()
Redeployer->>ProxyAdmin: upgradeAndCall(impl, initialize2(timelock))
ProxyAdmin->>EXA: initialize2(timelock)
Redeployer->>ProxyAdmin: upgradeAndCall(delegate to ProxyAdminMigrator)
ProxyAdmin->>ProxyAdminMigrator: migrate(proxyAdmin, exa)
ProxyAdminMigrator->>ProxyAdminMigrator: write ERC1967 slots
User->>HypEXA: deployRouter(token, remoteDomains)
HypEXA->>Router: CREATE3 deploy + aggregation setup
Router-->>HypEXA: router deployed
User->>HypEXA: proposeBridgeRole(token, salt)
HypEXA->>Timelock: schedule(grantRole(BRIDGE_ROLE, router))
Timelock-->>HypEXA: operation pending
User->>Router: transferRemote(amount, domain, payload)
Router->>Mailbox: sendMessage(payload)
Mailbox->>Router: process/handle → mint if BRIDGE_ROLE granted
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the project's interoperability by integrating Hyperlane, a cross-chain communication protocol. The changes enable the EXA token to be bridged and managed across different blockchain domains, expanding its utility and reach. This involved updating core dependencies, modifying deployment processes to include Hyperlane-specific components, and adding comprehensive tests to ensure the robustness of the new cross-chain capabilities. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #860 +/- ##
==========================================
+ Coverage 71.64% 72.06% +0.41%
==========================================
Files 247 248 +1
Lines 9596 9761 +165
Branches 3088 3133 +45
==========================================
+ Hits 6875 7034 +159
- Misses 2459 2465 +6
Partials 262 262
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
♻️ Duplicate comments (3)
contracts/script/Redeployer.s.sol (3)
96-149:⚠️ Potential issue | 🟠 MajorRun
forge fmton this file to unblock CI.The pipeline is currently failing
nx run@exactly/plugin:test:fmtdue to formatting differences in this file.As per coding guidelines
**/*.sol: Follow Solhint rules strictly and use Forge fmt for code formatting.
113-121:⚠️ Potential issue | 🟠 MajorFail fast when EXA implementation is missing before
upgradeEXA.Line 120 upgrades to
address(exa)without checking code presence, which defers failure to a less actionable downstream revert.Proposed fix
function upgradeEXA(address proxy) external { address admin = acct("admin"); + if (address(exa).code.length == 0) revert EXAImplementationNotDeployed(); ProxyAdmin p = ProxyAdmin(address(uint160(uint256( vm.load(proxy, bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)) )))); vm.broadcast(p.owner()); p.upgradeAndCall( ITransparentUpgradeableProxy(proxy), address(exa), abi.encodeCall(EXA.initialize2, (admin)) ); } @@ error ProxyAdminNotDeployed(); error TargetNonceTooLow(); +error EXAImplementationNotDeployed();
124-130: 🛠️ Refactor suggestion | 🟠 MajorAlign CREATE3 salt derivation with
token(or removetokenfrom the API).Line 129 hardcodes
"HypEXA"even though the function accepts atoken; that creates deterministic-slot collisions for multi-token use, and Line 145 resolves that same fixed slot.Proposed refactor
function deployRouter(address token) external returns (HypXERC20 router) { @@ - keccak256(abi.encode("HypEXA")), + keccak256(abi.encode("HypEXA", token)), @@ function setupRouter(address token, uint32 remoteDomain) external { address admin = acct("admin"); - address router = CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("HypEXA"))); + address router = CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("HypEXA", token)));Also applies to: 145-145
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
.changeset/beige-sails-worry.mdcontracts/.gas-snapshotcontracts/deploy.jsoncontracts/script/Redeployer.s.solcontracts/test/HypEXA.t.sol
There was a problem hiding this comment.
♻️ Duplicate comments (3)
contracts/script/Redeployer.s.sol (3)
121-127: 🛠️ Refactor suggestion | 🟠 Major
deployRouterignorestokenin the deterministic salt, making reuse collision-prone.The function accepts
tokenbut always uses the fixed"HypEXA"slot. Reusing it for another token collides on the same CREATE3 address.Proposed refactor
- keccak256(abi.encode("HypEXA")), + keccak256(abi.encode("HypEXA", token)), @@ - address router = CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("HypEXA"))); + address router = CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("HypEXA", token)));Also applies to: 142-142
140-146:⚠️ Potential issue | 🟠 Major
setupRoutershould fail fast if the deterministic router address is not deployed.
getDeployedcan resolve an address before code exists. Without a code-length guard, role/config steps can silently target an undeployed address path.Proposed fix
function setupRouter(address token, uint32 remoteDomain) external { address admin = acct("admin"); address router = CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("HypEXA"))); + if (router.code.length == 0) revert RouterNotDeployed(); vm.startBroadcast(admin); EXA(token).grantRole(keccak256("BRIDGE_ROLE"), router); HypXERC20(router).enrollRemoteRouter(remoteDomain, bytes32(uint256(uint160(router)))); vm.stopBroadcast(); } @@ error TargetNonceTooLow(); +error RouterNotDeployed();
113-119:⚠️ Potential issue | 🟠 Major
upgradeEXAshould guard against missing EXA implementation deployment.The upgrade path uses
address(exa)directly; adding an explicit code-length guard gives a clearer, earlier failure mode.Proposed fix
function upgradeEXA(address proxy) external { address admin = acct("admin"); + if (address(exa).code.length == 0) revert EXAImplementationNotDeployed(); ProxyAdmin p = ProxyAdmin(address(uint160(uint256(vm.load(proxy, bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)))))); vm.broadcast(p.owner()); p.upgradeAndCall(ITransparentUpgradeableProxy(proxy), address(exa), abi.encodeCall(EXA.initialize2, (admin))); } @@ error TargetNonceTooLow(); +error EXAImplementationNotDeployed();
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
.changeset/beige-sails-worry.mdcontracts/.gas-snapshotcontracts/deploy.jsoncontracts/script/Redeployer.s.solcontracts/test/HypEXA.t.sol
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
contracts/script/Redeployer.s.sol (1)
192-210:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFail fast before the 3-step
deployEXAmigration to avoid partial state.Line 199 and Line 200 already mutate the proxy before Line 206 performs admin migration. If
protocol("ProxyAdmin")(Line 209) or timelock config is invalid, the last tx reverts and leaves a partially-updated proxy (new impl/initialization, old admin).Proposed hardening
function deployEXA(address proxy) external { address admin = acct("admin"); + address timelock = protocol("TimelockController"); + address nextProxyAdmin = protocol("ProxyAdmin"); + if (timelock.code.length == 0) revert InvalidAdmin(timelock); + if (nextProxyAdmin.code.length == 0) revert InvalidAdmin(nextProxyAdmin); vm.startBroadcast(admin); exa = EXA(CREATE3_FACTORY.getDeployed(admin, keccak256(abi.encode("EXA")))); if (address(exa).code.length == 0) { exa = EXA(CREATE3_FACTORY.deploy(keccak256(abi.encode("EXA")), vm.getCode("EXA.sol:EXA"))); } proxyAdmin.upgradeAndCall(ITransparentUpgradeableProxy(proxy), address(exa), abi.encodeCall(EXA.initialize, ())); proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(proxy), address(exa), - abi.encodeCall(EXA.initialize2, (protocol("TimelockController"))) + abi.encodeCall(EXA.initialize2, (timelock)) ); proxyAdmin.upgradeAndCall( ITransparentUpgradeableProxy(proxy), address(new ProxyAdminMigrator()), - abi.encodeCall(ProxyAdminMigrator.migrate, (protocol("ProxyAdmin"), address(exa))) + abi.encodeCall(ProxyAdminMigrator.migrate, (nextProxyAdmin, address(exa))) ); vm.stopBroadcast(); }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2fdffe6b-51aa-41ba-a48b-a2f338a37b19
📒 Files selected for processing (3)
contracts/.gas-snapshotcontracts/script/Redeployer.s.solcontracts/test/Redeployer.t.sol
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b35f8681a3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
fa7112f to
b58a398
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b58a398dbd
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b55cb9c239
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
co-authored-by: Gerardo Nardelli <patitonardelli@gmail.com>
Summary by CodeRabbit