Skip to content

feat: add WBTC OFT adapter#205

Draft
wesraph wants to merge 5 commits into
mainfrom
feat/wbtc-oft-adapter
Draft

feat: add WBTC OFT adapter#205
wesraph wants to merge 5 commits into
mainfrom
feat/wbtc-oft-adapter

Conversation

@wesraph
Copy link
Copy Markdown
Contributor

@wesraph wesraph commented Apr 28, 2026

Summary

Adds a WBTCOFTAdapter to the Repayer, enabling WBTC bridging via LayerZero's OFT. Mirrors the existing USDT0 adapter (#183) — same IOFT interface, same Ethereum-vs-others approval branch, initiate-only (LayerZero auto-delivers).

Closes #202.

What's added

  • Provider.WBTC_OFT (enum value 10) appended to IRoute.sol
  • contracts/utils/WBTCOFTAdapter.sol — new adapter; on Ethereum it forceApproves and the OFTAdapter pulls via transferFrom, on every other chain the native OFT burns from msg.sender directly
  • contracts/testing/TestWBTCOFT.solTestWBTC (8 decimals), TestWBTCOFTAdapter (transferFrom mode), TestWBTCOFTNative (burn mode)
  • Repayer.sol inherits WBTCOFTAdapter, takes one new constructor arg (wbtcOft), dispatches Provider.WBTC_OFT in initiateRepay
  • All four deploy scripts (deploy.ts, deployRepayer.ts, deployStandaloneRepayer.ts, upgradeRepayer.ts) get a WBTCOFT fallback to ZERO_ADDRESS and append the new constructor arg
  • network.config.ts: new WBTC_OFT provider, WBTCOFT?: string field on both NetworkConfig interfaces, populated for chains where the OFT is live
  • 4 new unit tests in test/Repayer.ts (adapter approval mode, native burn mode, token mismatch, zero-address) + 1 fork test exercising the real Ethereum OFTAdapter

Rebalancer.sol is untouched — like USDT0, WBTC OFT only flows through the Repayer.

Verified deployment topology

All addresses confirmed on-chain via cast (token(), decimals(), approvalRequired(), endpoint(), peers(...)).

Chain Address Type Approval Wired in this PR
Ethereum 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c OFTAdapter (locks canonical WBTC 0x2260…) required yes
Base 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c Native OFT none yes
BSC 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c Native OFT none yes
Optimism 0xC3f854B2970f8727D28527ECE33176faC67FeF48 MintBurnOFTAdapter none yes
Unichain 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c Native OFT none yes
Avalanche 0x0555E30da8f98308EdB960aa94C0Db47230d2B9c Native OFT none not yet (no Tokens.WBTC entry in repo)
Arbitrum, Polygon not deployed n/a

All native OFTs inherit OFTFee with defaultFeeBps = 0. minAmountLD == amountLD is intentional (no slippage); a future BitGo fee activation would revert there — that's an escalation problem, not an adapter problem.

Out of scope (deferred, mirrors how USDT0 and CCTP V2 rolled out)

  1. Route enablement: no Provider.WBTC_OFT entries are added to any Pools route list in this PR. That lands in a follow-up staging-deploy PR (same pattern as #197 for USDT0 and #201 for CCTP V2).
  2. Tokens.WBTC entries on Base/Avalanche/Unichain: don't exist yet. Required by the route-enablement PR (the adapter's runtime check oft.token() == address(token) needs Tokens.WBTC to point at the canonical OFT).
  3. BSC and Optimism Tokens.WBTC mismatch: BSC currently registers BTCB (0x7130…, 18 dec), OP registers bridged WBTC (0x68f1…); neither matches the OFT's underlying token. The route-enablement PR will need to switch these or add a separate token alias before turning on Provider.WBTC_OFT on those chains.

Verification

  • All contract values (vanity address, OFT vs OFTAdapter topology, decimals, fee state, peer wiring per destination) verified live with cast against public mainnet RPCs.
  • LayerZero EIDs cross-checked against LayerZero V2 docs and the existing LayerZeroHelper.sol.
  • Coverage baseline updated (branches 92.65 → 92.73; WBTCOFTAdapter.sol itself at 100%).
  • Existing fork-test sites (specific-fork-test/{arbitrum,ethereum,gnosis,polygon,unichain}/Repayer*.ts) updated for the new constructor arg.
  • Unrelated CI note: LiquidityPoolAave* tests fail on main and on this branch with ReserveFrozen() against the Base Aave V3 USDC reserve (recent governance freeze) — pre-existing, not introduced here.

References

wesraph added 4 commits April 28, 2026 12:00
Aave V3 governance froze the WETH reserve on Base around block 44890000.
The unit tests touch Aave V3 borrow/repay paths through LiquidityPoolAave
and LiquidityPoolAaveLongTerm, which all revert with `ReserveFrozen()`
when forking from current head.

Pinning the default Base fork to block 44880000 (the last block before the
freeze) restores 29 previously-failing tests without changing any
production code. Verified locally that all unit, fork, script, and
coverage suites pass at the pinned block.
Each chain has its own block-number space, so applying a single
FORK_BLOCK_NUMBER across every fork target breaks tests that fork
from a different chain (e.g. test:ethereum at block 44.8M reverts
because that block does not exist on Ethereum yet).

Only honour the env var when neither DRY_RUN nor FORK_TEST is set —
the same condition that picks the default Base fork URL.
@wesraph wesraph marked this pull request as ready for review April 28, 2026 14:46
@wesraph wesraph requested review from MakMuftic and lastperson April 28, 2026 14:46
@mpetrunic mpetrunic requested a review from Copilot April 29, 2026 12:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for bridging WBTC via LayerZero OFT through the Repayer, following the existing USDT0 OFT adapter pattern (initiate-only flow).

Changes:

  • Introduces WBTCOFTAdapter and wires it into Repayer via a new constructor arg (wbtcOft) and Provider.WBTC_OFT dispatch.
  • Extends config + scripts to carry WBTCOFT addresses (with ZERO_ADDRESS fallback) and updates fork/unit tests accordingly.
  • Adds mock contracts + unit/fork tests for both “approval-required (adapter)” and “native burn” OFT behaviors.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated no comments.

Show a summary per file
File Description
contracts/utils/WBTCOFTAdapter.sol New LayerZero OFT-based adapter implementing WBTC initiate flow (ETH approval vs non-ETH no-approval).
contracts/Repayer.sol Adds WBTCOFTAdapter inheritance, constructor param, and Provider.WBTC_OFT dispatch in initiateRepay.
contracts/interfaces/IRoute.sol Appends Provider.WBTC_OFT and centralizes InvalidToken() error on the interface.
contracts/utils/USDT0Adapter.sol Removes redundant local InvalidToken() in favor of IRoute.InvalidToken().
contracts/testing/TestWBTCOFT.sol Adds WBTC/OFT mocks for both transferFrom (adapter) and burn (native) send modes.
contracts/testing/TestRepayer.sol Extends test repayer constructor to pass through wbtcOft.
test/Repayer.ts Updates deployments for new constructor arg and adds unit tests for WBTC OFT paths + revert cases.
specific-fork-test/ethereum/RepayerWBTCOFT.ts New Ethereum fork test exercising real WBTC OFTAdapter behavior.
specific-fork-test/ethereum/Repayer.ts Updates repayer deployment for new constructor arg.
specific-fork-test/ethereum/RepayerUSDT0.ts Updates repayer deployment for new constructor arg.
specific-fork-test/ethereum/RepayerGnosisOmnibridge.ts Updates repayer deployment for new constructor arg.
specific-fork-test/gnosis/RepayerGnosisOmnibridge.ts Updates repayer deployment for new constructor arg.
specific-fork-test/unichain/RepayerUSDT0.ts Updates repayer deployment for new constructor arg.
specific-fork-test/polygon/RepayerUSDT0.ts Updates repayer deployment for new constructor arg.
specific-fork-test/arbitrum/RepayerUSDT0.ts Updates repayer deployment for new constructor arg.
scripts/deploy.ts Adds WBTCOFT fallback + appends new constructor arg in deployment.
scripts/deployRepayer.ts Adds WBTCOFT fallback + appends new constructor arg in deployment.
scripts/deployStandaloneRepayer.ts Adds WBTCOFT fallback + appends new constructor arg in deployment.
scripts/upgradeRepayer.ts Adds WBTCOFT fallback + appends new constructor arg for upgrades.
scripts/common.ts Adds numeric ProviderSolidity.WBTC_OFT = 10n and reverse mapping.
network.config.ts Adds Provider.WBTC_OFT and WBTCOFT?: string across configs + populates addresses for supported chains.
hardhat.config.ts Adjusts fork blockNumber usage so it only applies to the default Base fork (not FORK_TEST/DRY_RUN).
.env.example Documents/pins FORK_BLOCK_NUMBER for Base fork stability.
coverage-baseline.json Updates coverage baseline to reflect added coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mpetrunic
Copy link
Copy Markdown
Member

maybe icebox for now since across uses different tokens

@mpetrunic mpetrunic marked this pull request as draft May 19, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement WBTC OFT adapter

4 participants