Context
PR #953 lands _disableInitializers() on L2WormholeGateway and L2TBTC but defers it on L2BTCRedeemerWormhole.sol. Adding the constructor pushes the creation bytecode past a size threshold that triggers a bug in @openzeppelin/hardhat-upgrades@1.22.0 / @openzeppelin/upgrades-core@1.20.0: the plugin's version-matching loop splices unrelated link references into our bytecode and corrupts the hex-validity check, breaking every deployProxy call in the test suite.
See inline `NOTE` in https://github.com/threshold-network/tbtc-v2/blob/feature/evm-l2-fee-waivers/solidity/contracts/cross-chain/wormhole/L2BTCRedeemerWormhole.sol for details.
Impact
Residual: an attacker can initialize the implementation contract directly and become its `owner`. The contracts use a transparent proxy, so user funds are unaffected; this only creates an orphan logic-contract shell that could cause phishing/confusion.
Fix
Once `@openzeppelin/hardhat-upgrades` is upgraded past the bug:
- Restore the constructor:
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
- Re-add the `L2BTCRedeemerWormhole` describe block that was removed from
solidity/test/cross-chain/wormhole/L2ImplementationInitializerLock.test.ts.
- Remove the `NOTE` block in the contract source.
The test suite in PR #953 already exercises the lock for the other two L2 contracts, so the regression coverage pattern is established.
Context
PR #953 lands
_disableInitializers()onL2WormholeGatewayandL2TBTCbut defers it onL2BTCRedeemerWormhole.sol. Adding the constructor pushes the creation bytecode past a size threshold that triggers a bug in@openzeppelin/hardhat-upgrades@1.22.0/@openzeppelin/upgrades-core@1.20.0: the plugin's version-matching loop splices unrelated link references into our bytecode and corrupts the hex-validity check, breaking everydeployProxycall in the test suite.See inline `NOTE` in https://github.com/threshold-network/tbtc-v2/blob/feature/evm-l2-fee-waivers/solidity/contracts/cross-chain/wormhole/L2BTCRedeemerWormhole.sol for details.
Impact
Residual: an attacker can initialize the implementation contract directly and become its `owner`. The contracts use a transparent proxy, so user funds are unaffected; this only creates an orphan logic-contract shell that could cause phishing/confusion.
Fix
Once `@openzeppelin/hardhat-upgrades` is upgraded past the bug:
solidity/test/cross-chain/wormhole/L2ImplementationInitializerLock.test.ts.The test suite in PR #953 already exercises the lock for the other two L2 contracts, so the regression coverage pattern is established.