feat(contracts-adapter): add native SYN HyperCore delivery - #4077
feat(contracts-adapter): add native SYN HyperCore delivery#4077trajan0x wants to merge 4 commits into
Conversation
Implement a separate versioned adapter and SYN-specific HyperCore composer with strict 18-to-8 decimal conversion, activation and capacity checks, and destination rollback semantics.\n\nRefs CALL-2439.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 34 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
📝 WalkthroughWalkthroughAdded ChangesHyperCore delivery
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Source as SynapseBridgeAdapterV2
participant LayerZero
participant Destination as SynapseBridgeAdapterV2
participant Composer as SynapseHyperCoreComposer
participant CoreWriter
Source->>LayerZero: Send encoded HyperCore message
LayerZero->>Destination: Deliver message
Destination->>Composer: Mint or withdraw tokens, then bridgeToHyperCore
Composer->>CoreWriter: Submit spot-send action
CoreWriter-->>Composer: Execute Core transfer
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4077 +/- ##
===================================================
+ Coverage 54.67169% 55.46595% +0.79426%
===================================================
Files 146 151 +5
Lines 4249 4464 +215
Branches 752 823 +71
===================================================
+ Hits 2323 2476 +153
- Misses 1834 1896 +62
Partials 92 92
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.
Actionable comments posted: 2
🧹 Nitpick comments (6)
packages/contracts-adapter/test/mocks/SynapseBridgeMock.sol (1)
12-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake
withdrawmove tokens as well.
mintnow transfers real balance, so destination tests can assert token state.withdrawon line 15 remains a no-op, so theWithdrawDepositbranch of_receiveHyperCoreMessagecannot be asserted the same way. The asymmetry is the root cause of the missing destinationWithdrawDepositcoverage noted onpackages/contracts-adapter/test/SBA.Dst.t.sollines 148-168.Add a transfer from the mock to
to, and fund the mock in the affected tests.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/test/mocks/SynapseBridgeMock.sol` around lines 12 - 15, Update SynapseBridgeMock.withdraw to transfer the requested token amount from the mock contract to to, matching mint’s real balance mutation; also fund the mock in the affected destination WithdrawDeposit tests so the transfer succeeds and token balances can be asserted.packages/contracts-adapter/test/SBA.Dst.t.sol (2)
90-100: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider sharing the precompile mock helpers.
mockCoreUserandmockSpotBalanceare identical to the helpers inpackages/contracts-adapter/test/SynapseHyperCoreComposer.t.sollines 210-220. Extract them into a shared test fixture so the precompile encoding is defined once.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/test/SBA.Dst.t.sol` around lines 90 - 100, Extract the duplicated mockCoreUser and mockSpotBalance helpers from the test contracts into a shared test fixture, preserving their existing precompile addresses and ABI encodings. Update both SBA.Dst and SynapseHyperCoreComposer tests to reuse the shared helpers and remove their local duplicate definitions.
148-168: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the HyperCore receive events and add a WithdrawDeposit destination case.
Two gaps exist in this test:
- The test does not assert
TokenReceivedOnHyperCoreorTokenReceived.SBA.t.soladdsexpectEventTokenReceivedOnHyperCore(lines 96-101), but no test calls it. The adapter emits both events on line 220 and line 221 ofSynapseBridgeAdapterV2.sol._receiveHyperCoreMessageserves bothMintBurnandWithdrawDeposittokens, but only theMintBurnbranch is covered here.SynapseBridgeMock.withdrawis still a no-op, so a withdraw case also needs the mock to move escrowed tokens to the Composer.💚 Proposed event assertions for the success path
vm.expectCall(composer.CORE_WRITER(), abi.encodeCall(ICoreWriter.sendRawAction, (payload))); + expectEventTokenReceivedOnHyperCore(SRC_EID, recipient, address(token), amount, MOCK_GUID); + expectEventTokenReceived(SRC_EID, recipient, address(token), amount, MOCK_GUID); endpointCallsLzReceive();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/test/SBA.Dst.t.sol` around lines 148 - 168, Extend test_receiveHyperCore_mintBurn to assert both TokenReceivedOnHyperCore and TokenReceived using the existing expectEventTokenReceivedOnHyperCore helper and the corresponding event expectation. Add a separate _receiveHyperCoreMessage test covering the WithdrawDeposit token path, and update SynapseBridgeMock.withdraw to transfer the escrowed tokens to the Composer before asserting the resulting balances and events.packages/contracts-adapter/src/SynapseBridgeAdapterV2.sol (1)
212-222: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider passing the resolved token into
_mintOrWithdraw.Line 214 resolves the local token, and
_mintOrWithdrawresolves it again on line 230. The result is one duplicated mapping lookup per HyperCore receive. A small refactor removes the duplication and makes the single resolution point explicit.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/src/SynapseBridgeAdapterV2.sol` around lines 212 - 222, Update _mintOrWithdraw and its call from _receiveHyperCoreMessage to accept and use the already-resolved local token, so _checkAndGetLocalAddress is performed only once during HyperCore message handling. Preserve the existing mint/withdraw behavior and token-related events.packages/contracts-adapter/test/SynapseHyperCoreComposer.t.sol (1)
135-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a passing same-block aggregate case.
test_bridgeToHyperCore_revert_sameBlockAggregateCapacityproves that the reservation blocks an over-capacity second delivery.test_bridgeToHyperCore_reservationResetsNextBlockproves the reset. No test proves that two deliveries in the same block succeed when capacity covers both. Without that case, an over-reserving change to lines 76-83 ofSynapseHyperCoreComposer.solwould not fail any test.Add a test with
available = CORE_AMOUNT * 2and two calls in the same block, then assert both transfers reachassetBridge.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/test/SynapseHyperCoreComposer.t.sol` around lines 135 - 171, Add a passing same-block aggregate-capacity test alongside the existing bridge capacity tests, using available = CORE_AMOUNT * 2 and two bridgeToHyperCore calls without advancing the block. Assert the composer retains no tokens and assetBridge() receives EVM_AMOUNT * 2, confirming both deliveries succeed when aggregate capacity is sufficient.packages/contracts-adapter/src/SynapseHyperCoreComposer.sol (1)
49-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDocument the recovery path for a wrong
coreIndex_.
coreIndexis immutable, andassetBridgeis derived from it on line 57. The constructor cannot verify thatcoreIndex_matches the HIP-1 index linked totoken_. On the adapter side,setHyperCoreComposerrejects a second binding for the same token (SynapseBridgeAdapterV2.solline 110). A wrongcoreIndex_therefore disables the HyperCore route for that token permanently and requires an adapter redeployment.The value is set once at deployment, so an on-chain guard is not required. Add the index verification step to the deployment gates in
SYN_HYPERCORE.md, and state that a wrong index requires a new adapter deployment.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/contracts-adapter/src/SynapseHyperCoreComposer.sol` around lines 49 - 58, Update the deployment gates in SYN_HYPERCORE.md to require verifying that coreIndex_ matches the HIP-1 index associated with token_ before deployment. Document that coreIndex and the derived assetBridge are immutable, and that an incorrect index permanently disables the token’s HyperCore route and requires deploying a new adapter.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/contracts-adapter/SYN_HYPERCORE.md`:
- Around line 30-31: Update the Composer delivery description to separate the
per-call adapter enforcement in bridgeToHyperCore from the one-time
token-binding validation performed by
SynapseBridgeAdapterV2.setHyperCoreComposer. Do not describe the token binding
as being checked during each delivery call.
In `@packages/contracts-adapter/test/SBA.Management.t.sol`:
- Around line 380-428: Extend the setHyperCoreComposer tests with a
mismatched-binding case: deploy a valid SynapseHyperCoreComposer using the
adapter address but a token different from the token passed to
adapter.setHyperCoreComposer. Add a negative test expecting
SBAV2__HyperCoreComposerInvalid with the candidate composer address, while
preserving the existing valid, invalid-binding, and ownership coverage.
---
Nitpick comments:
In `@packages/contracts-adapter/src/SynapseBridgeAdapterV2.sol`:
- Around line 212-222: Update _mintOrWithdraw and its call from
_receiveHyperCoreMessage to accept and use the already-resolved local token, so
_checkAndGetLocalAddress is performed only once during HyperCore message
handling. Preserve the existing mint/withdraw behavior and token-related events.
In `@packages/contracts-adapter/src/SynapseHyperCoreComposer.sol`:
- Around line 49-58: Update the deployment gates in SYN_HYPERCORE.md to require
verifying that coreIndex_ matches the HIP-1 index associated with token_ before
deployment. Document that coreIndex and the derived assetBridge are immutable,
and that an incorrect index permanently disables the token’s HyperCore route and
requires deploying a new adapter.
In `@packages/contracts-adapter/test/mocks/SynapseBridgeMock.sol`:
- Around line 12-15: Update SynapseBridgeMock.withdraw to transfer the requested
token amount from the mock contract to to, matching mint’s real balance
mutation; also fund the mock in the affected destination WithdrawDeposit tests
so the transfer succeeds and token balances can be asserted.
In `@packages/contracts-adapter/test/SBA.Dst.t.sol`:
- Around line 90-100: Extract the duplicated mockCoreUser and mockSpotBalance
helpers from the test contracts into a shared test fixture, preserving their
existing precompile addresses and ABI encodings. Update both SBA.Dst and
SynapseHyperCoreComposer tests to reuse the shared helpers and remove their
local duplicate definitions.
- Around line 148-168: Extend test_receiveHyperCore_mintBurn to assert both
TokenReceivedOnHyperCore and TokenReceived using the existing
expectEventTokenReceivedOnHyperCore helper and the corresponding event
expectation. Add a separate _receiveHyperCoreMessage test covering the
WithdrawDeposit token path, and update SynapseBridgeMock.withdraw to transfer
the escrowed tokens to the Composer before asserting the resulting balances and
events.
In `@packages/contracts-adapter/test/SynapseHyperCoreComposer.t.sol`:
- Around line 135-171: Add a passing same-block aggregate-capacity test
alongside the existing bridge capacity tests, using available = CORE_AMOUNT * 2
and two bridgeToHyperCore calls without advancing the block. Assert the composer
retains no tokens and assetBridge() receives EVM_AMOUNT * 2, confirming both
deliveries succeed when aggregate capacity is sufficient.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 62495297-6818-4399-9a5a-1d4909ab6b70
📒 Files selected for processing (17)
packages/contracts-adapter/SYN_HYPERCORE.mdpackages/contracts-adapter/src/SynapseBridgeAdapterV2.solpackages/contracts-adapter/src/SynapseHyperCoreComposer.solpackages/contracts-adapter/src/interfaces/ICoreWriter.solpackages/contracts-adapter/src/interfaces/ISynapseBridgeAdapterV2.solpackages/contracts-adapter/src/interfaces/ISynapseBridgeAdapterV2Errors.solpackages/contracts-adapter/src/interfaces/ISynapseHyperCoreComposer.solpackages/contracts-adapter/src/libs/HyperCoreMessage.solpackages/contracts-adapter/test/SBA.Dst.t.solpackages/contracts-adapter/test/SBA.Management.t.solpackages/contracts-adapter/test/SBA.Src.t.solpackages/contracts-adapter/test/SBA.t.solpackages/contracts-adapter/test/SynapseHyperCoreComposer.t.solpackages/contracts-adapter/test/harnesses/HyperCoreMessageHarness.solpackages/contracts-adapter/test/libs/HyperCoreMessage.t.solpackages/contracts-adapter/test/mocks/SynapseBridgeMock.solpackages/contracts-adapter/test/mocks/TestTokenDecimals.sol
Deploying sanguine-fe with
|
| Latest commit: |
756a654
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6c56f83c.sanguine-fe.pages.dev |
| Branch Preview URL: | https://codex-call-2439-syn-hypercor.sanguine-fe.pages.dev |
|
This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
Status
Draft. This is not deployment-ready and must not be used to link or fund SYN on HyperCore yet.
Tracking: CALL-2439
What changed
SynapseBridgeAdapterV2; the existing adapter and its CREATE2-derived deployments are untouchedbridgeERC20ToHyperCoreSynapseHyperCoreComposerthat:10^10scalinguint64overflow before source burn or escrow0x01000006CoreWriter spot-send actionSYN remains a SynapseBridge token. This does not convert SYN into an OFT.
Why
The LayerZero OFT Composer is built around an OFT supply path. SYN already has a SynapseBridge burn/mint and escrow/withdraw supply model. This change composes HyperCore delivery into that existing model instead of adding a second token authority.
Immediate destination failures revert the entire LayerZero receive transaction, including the SynapseBridge mint or withdrawal. HyperCore execution is asynchronous after the EVM block, so a successful EVM receipt is not treated as final delivery proof.
Verification
forge test --root packages/contracts-adapter: 125 passed, 0 failedforge coverage --root packages/contracts-adapter --report summary:forge build --root packages/contracts-adapter --sizes:git diff --check: cleanorigin/master0xc6f462c66a4694ed69fe69c79ac2f3fc8e20f184ecb86de5b0856c41dcacd9bfRequired before deployment
SynapseERC20deployment/finalizer mechanismReferences
Summary by CodeRabbit