From 03b7a2d714807bd66e23a7982513bc0a26ac68e8 Mon Sep 17 00:00:00 2001 From: Daniel Blaecker Date: Wed, 15 Jul 2026 10:51:00 +0700 Subject: [PATCH 1/3] feat(LibBytes): add address<->bytes32 conversion helpers (EXSC-618) Consolidate the address<->bytes32 cast pattern duplicated across ~10 facets into LibBytes (v1.1.0): - toBytes32(address): widening, lossless - toAddress(bytes32): checked narrowing, reverts NotAnAddress on dirty high bits - toAddressUnchecked(bytes32): raw truncation for intentional/guarded cases Also replace toHexString's require-string with a custom error. Add unit tests. Leave breadcrumb comments at the 21 existing call sites (checked/unchecked per audit); each is migrated the next time its facet is touched, so this PR makes no facet behavior change. Co-Authored-By: Claude Opus 4.8 --- src/Facets/AcrossFacetPackedV4.sol | 5 +++ src/Facets/AcrossFacetV4.sol | 1 + src/Facets/AcrossV4SwapFacet.sol | 3 ++ src/Facets/AllBridgeFacet.sol | 3 ++ src/Facets/CalldataVerificationFacet.sol | 1 + src/Facets/CelerCircleBridgeFacet.sol | 1 + src/Facets/GlacisFacet.sol | 1 + src/Facets/LiFiIntentEscrowFacet.sol | 1 + src/Facets/LiFiIntentEscrowFacetV2.sol | 1 + src/Facets/NEARIntentsFacet.sol | 1 + src/Facets/PolymerCCTPFacet.sol | 1 + src/Facets/StargateFacetV2.sol | 1 + src/Libraries/LibBytes.sol | 33 +++++++++++++-- src/Periphery/ReceiverOIF.sol | 1 + test/solidity/Libraries/LibBytes.t.sol | 52 +++++++++++++++++++++++- 15 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/Facets/AcrossFacetPackedV4.sol b/src/Facets/AcrossFacetPackedV4.sol index 5170dfd4d8..c362a9184e 100644 --- a/src/Facets/AcrossFacetPackedV4.sol +++ b/src/Facets/AcrossFacetPackedV4.sol @@ -190,6 +190,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { // pull tokens from msg.sender LibAsset.transferFromERC20( + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address(uint160(uint256(sendingAssetId))), msg.sender, address(this), @@ -229,6 +230,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { ) external { // Deposit assets LibAsset.transferFromERC20( + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address(uint160(uint256(sendingAssetId))), msg.sender, address(this), @@ -357,6 +359,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { // Check if receiver is EVM address (20 bytes) or non-EVM (longer) // If the first 12 bytes are zero, it's likely an EVM address if (bytes12(data[44:56]) == bytes12(0)) { + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.receiver = address( uint160(uint256(bytes32(data[44:76]))) ); @@ -398,12 +401,14 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { } bridgeData.transactionId = bytes32(data[4:12]); // we truncate intentionally to save gas (not dangerous) + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.sendingAssetId = address( uint160(uint256(bytes32(data[76:108]))) ); // sendingAssetId // Check if receiver is EVM address (20 bytes) or non-EVM (longer) // If the first 12 bytes are zero, it's likely an EVM address if (bytes12(data[44:56]) == bytes12(0)) { + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.receiver = address( uint160(uint256(bytes32(data[44:76]))) ); diff --git a/src/Facets/AcrossFacetV4.sol b/src/Facets/AcrossFacetV4.sol index e244704d2e..22fc8a1a53 100644 --- a/src/Facets/AcrossFacetV4.sol +++ b/src/Facets/AcrossFacetV4.sol @@ -265,6 +265,7 @@ contract AcrossFacetV4 is function _convertAddressToBytes32( address _address ) internal pure returns (bytes32) { + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 return bytes32(uint256(uint160(_address))); } } diff --git a/src/Facets/AcrossV4SwapFacet.sol b/src/Facets/AcrossV4SwapFacet.sol index 988aef46e3..7273d3e9c6 100644 --- a/src/Facets/AcrossV4SwapFacet.sol +++ b/src/Facets/AcrossV4SwapFacet.sol @@ -359,6 +359,7 @@ contract AcrossV4SwapFacet is // Validate asset matches for ERC20 flows bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId); + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address decodedInputToken = address( uint160(uint256(params.inputToken)) ); @@ -609,6 +610,7 @@ contract AcrossV4SwapFacet is _validateAmount(quote.amount, _bridgeData.minAmount); // Validate burnToken matches bridgeData asset (native is already excluded by msg.value check above) + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address burnToken = address(uint160(uint256(quote.burnToken))); if (burnToken != _bridgeData.sendingAssetId) { revert InformationMismatch(); @@ -826,6 +828,7 @@ contract AcrossV4SwapFacet is function _convertAddressToBytes32( address _address ) internal pure returns (bytes32) { + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 return bytes32(uint256(uint160(_address))); } } diff --git a/src/Facets/AllBridgeFacet.sol b/src/Facets/AllBridgeFacet.sol index 873398d56d..594e88f5a3 100644 --- a/src/Facets/AllBridgeFacet.sol +++ b/src/Facets/AllBridgeFacet.sol @@ -155,6 +155,7 @@ contract AllBridgeFacet is } else { // destination chain is EVM // make sure that bridgeData and allBridgeData receiver addresses match + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( _bridgeData.receiver != address(uint160(uint256(_allBridgeData.recipient))) @@ -172,6 +173,7 @@ contract AllBridgeFacet is if (_allBridgeData.payFeeWithSendingAsset) { // pay fee with sending asset ALLBRIDGE.swapAndBridge( + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.sendingAssetId))), _bridgeData.minAmount, _allBridgeData.recipient, @@ -184,6 +186,7 @@ contract AllBridgeFacet is } else { // pay fee with native asset ALLBRIDGE.swapAndBridge{ value: _allBridgeData.fees }( + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.sendingAssetId))), _bridgeData.minAmount, _allBridgeData.recipient, diff --git a/src/Facets/CalldataVerificationFacet.sol b/src/Facets/CalldataVerificationFacet.sol index 336ac7cb2a..51b6786e97 100644 --- a/src/Facets/CalldataVerificationFacet.sol +++ b/src/Facets/CalldataVerificationFacet.sol @@ -395,6 +395,7 @@ contract CalldataVerificationFacet { } // Convert callToBytes32 to address type and compare them + // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address callToAddressFromBytes32 = address( uint160(uint256(callToBytes32)) ); diff --git a/src/Facets/CelerCircleBridgeFacet.sol b/src/Facets/CelerCircleBridgeFacet.sol index 8a4246a908..81a3426ea5 100644 --- a/src/Facets/CelerCircleBridgeFacet.sol +++ b/src/Facets/CelerCircleBridgeFacet.sol @@ -125,6 +125,7 @@ contract CelerCircleBridgeFacet is CIRCLE_BRIDGE_PROXY.depositForBurn( _bridgeData.minAmount, uint64(_bridgeData.destinationChainId), + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.receiver))), USDC, _celerCircleData.maxFee, diff --git a/src/Facets/GlacisFacet.sol b/src/Facets/GlacisFacet.sol index b4d6b6a558..6339ebd93c 100644 --- a/src/Facets/GlacisFacet.sol +++ b/src/Facets/GlacisFacet.sol @@ -131,6 +131,7 @@ contract GlacisFacet is } else { // destination chain is EVM // make sure that bridgeData and glacisData receiver addresses match + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( _bridgeData.receiver != address(uint160(uint256(_glacisData.receiverAddress))) diff --git a/src/Facets/LiFiIntentEscrowFacet.sol b/src/Facets/LiFiIntentEscrowFacet.sol index 73788d75e4..0a56653bc6 100644 --- a/src/Facets/LiFiIntentEscrowFacet.sol +++ b/src/Facets/LiFiIntentEscrowFacet.sol @@ -202,6 +202,7 @@ contract LiFiIntentEscrowFacet is } else { // Check if the receiver is the same according to bridgeData and LIFIIntentData // Note: We already know 0 <= _bridgeData.receiver < recipient != 0 thus _bridgeData.receiver != 0. + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 if (recipient != bytes32(uint256(uint160(_bridgeData.receiver)))) { revert InvalidReceiver(); } diff --git a/src/Facets/LiFiIntentEscrowFacetV2.sol b/src/Facets/LiFiIntentEscrowFacetV2.sol index b4285a4f88..49be096eed 100644 --- a/src/Facets/LiFiIntentEscrowFacetV2.sol +++ b/src/Facets/LiFiIntentEscrowFacetV2.sol @@ -204,6 +204,7 @@ contract LiFiIntentEscrowFacetV2 is } else { // Check if the receiver is the same according to bridgeData and LIFIIntentData // Note: We already know 0 <= _bridgeData.receiver < recipient != 0 thus _bridgeData.receiver != 0. + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 if (recipient != bytes32(uint256(uint160(_bridgeData.receiver)))) { revert InvalidReceiver(); } diff --git a/src/Facets/NEARIntentsFacet.sol b/src/Facets/NEARIntentsFacet.sol index a31698129a..c9eaa4f4c4 100644 --- a/src/Facets/NEARIntentsFacet.sol +++ b/src/Facets/NEARIntentsFacet.sol @@ -275,6 +275,7 @@ contract NEARIntentsFacet is ILiFi.BridgeData memory _bridgeData, NEARIntentsData calldata _nearData ) internal view { + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32 receiverBytes32 = _bridgeData.receiver == NON_EVM_ADDRESS ? _nearData.nonEVMReceiver : bytes32(uint256(uint160(_bridgeData.receiver))); diff --git a/src/Facets/PolymerCCTPFacet.sol b/src/Facets/PolymerCCTPFacet.sol index f295d471f7..1ba70624e0 100644 --- a/src/Facets/PolymerCCTPFacet.sol +++ b/src/Facets/PolymerCCTPFacet.sol @@ -286,6 +286,7 @@ contract PolymerCCTPFacet is TOKEN_MESSENGER.depositForBurn( bridgeAmount, _chainIdToDomainId(destinationChainId), + // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.receiver))), USDC, UNRESTRICTED_DESTINATION_CALLER, diff --git a/src/Facets/StargateFacetV2.sol b/src/Facets/StargateFacetV2.sol index 67915534c9..e5340e90ab 100644 --- a/src/Facets/StargateFacetV2.sol +++ b/src/Facets/StargateFacetV2.sol @@ -111,6 +111,7 @@ contract StargateFacetV2 is ILiFi, ReentrancyGuard, SwapperV2, Validatable { ) revert InformationMismatch(); // ensure that receiver addresses match in case of no destination call + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( !_bridgeData.hasDestinationCall && (_bridgeData.receiver != diff --git a/src/Libraries/LibBytes.sol b/src/Libraries/LibBytes.sol index e2eb72e6a6..c35fcdda75 100644 --- a/src/Libraries/LibBytes.sol +++ b/src/Libraries/LibBytes.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.17; -/// @custom:version 1.0.0 +/// @custom:version 1.1.0 library LibBytes { // solhint-disable no-inline-assembly @@ -9,6 +9,8 @@ library LibBytes { error SliceOverflow(); error SliceOutOfBounds(); error AddressOutOfBounds(); + error HexLengthInsufficient(); + error NotAnAddress(bytes32 value); bytes16 private constant _SYMBOLS = "0123456789abcdef"; @@ -121,8 +123,33 @@ library LibBytes { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } - // solhint-disable-next-line gas-custom-errors - require(value == 0, "Strings: hex length insufficient"); + if (value != 0) revert HexLengthInsufficient(); return string(buffer); } + + /// @notice Left-zero-pads an address into bytes32. Widening — always lossless. + /// @param _addr The address to convert. + /// @return The bytes32 representation of the address. + function toBytes32(address _addr) internal pure returns (bytes32) { + return bytes32(uint256(uint160(_addr))); + } + + /// @notice Narrows a left-zero-padded bytes32 to an address, reverting if the + /// top 96 bits are set (checked downcast). + /// @param _value The bytes32 value to convert. + /// @return The address representation of the bytes32. + function toAddress(bytes32 _value) internal pure returns (address) { + if (uint256(_value) >> 160 != 0) revert NotAnAddress(_value); + return address(uint160(uint256(_value))); + } + + /// @notice Narrows a bytes32 to an address by truncation, keeping only the low + /// 160 bits. Use ONLY where dropping the high bits is intentional. + /// @param _value The bytes32 value to convert. + /// @return The address representation of the low 160 bits. + function toAddressUnchecked( + bytes32 _value + ) internal pure returns (address) { + return address(uint160(uint256(_value))); + } } diff --git a/src/Periphery/ReceiverOIF.sol b/src/Periphery/ReceiverOIF.sol index 092fa2a8bb..f5fa63c2d6 100644 --- a/src/Periphery/ReceiverOIF.sol +++ b/src/Periphery/ReceiverOIF.sol @@ -90,6 +90,7 @@ contract ReceiverOIF is ILiFi, WithdrawablePeriphery, IOutputCallback { _swapAndCompleteBridgeTokens( transactionId, swapData, + // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address(uint160(uint256(token))), payable(receiver), amount diff --git a/test/solidity/Libraries/LibBytes.t.sol b/test/solidity/Libraries/LibBytes.t.sol index 4ebba9183b..eea622e7c7 100644 --- a/test/solidity/Libraries/LibBytes.t.sol +++ b/test/solidity/Libraries/LibBytes.t.sol @@ -28,6 +28,20 @@ contract LibBytesHarness { ) external pure returns (string memory) { return LibBytes.toHexString(_value, _length); } + + function toBytes32(address _addr) external pure returns (bytes32) { + return LibBytes.toBytes32(_addr); + } + + function toAddress(bytes32 _value) external pure returns (address) { + return LibBytes.toAddress(_value); + } + + function toAddressUnchecked( + bytes32 _value + ) external pure returns (address) { + return LibBytes.toAddressUnchecked(_value); + } } contract LibBytesTest is Test { @@ -90,8 +104,44 @@ contract LibBytesTest is Test { } function testRevert_toHexString_LengthInsufficient() public { - vm.expectRevert("Strings: hex length insufficient"); + vm.expectRevert(LibBytes.HexLengthInsufficient.selector); harness.toHexString(uint256(0x1234), 1); } + + function test_toBytes32_LeftZeroPadsAddress() public { + address addr = address(0x1234567890AbcdEF1234567890aBcdef12345678); + + assertEq(harness.toBytes32(addr), bytes32(uint256(uint160(addr)))); + } + + function test_toAddress_bytes32_RoundTrips() public { + address addr = address(0x1234567890AbcdEF1234567890aBcdef12345678); + + assertEq(harness.toAddress(harness.toBytes32(addr)), addr); + } + + function test_toAddress_bytes32_ZeroValue() public { + assertEq(harness.toAddress(bytes32(0)), address(0)); + } + + function testRevert_toAddress_bytes32_HighBitsSet() public { + bytes32 dirty = bytes32( + (uint256(1) << 160) | + uint160(0x1234567890AbcdEF1234567890aBcdef12345678) + ); + + vm.expectRevert( + abi.encodeWithSelector(LibBytes.NotAnAddress.selector, dirty) + ); + + harness.toAddress(dirty); + } + + function test_toAddressUnchecked_TruncatesHighBits() public { + address addr = address(0x1234567890AbcdEF1234567890aBcdef12345678); + bytes32 dirty = bytes32((uint256(1) << 160) | uint160(addr)); + + assertEq(harness.toAddressUnchecked(dirty), addr); + } } From 189b86d21dc0f9af779567c8767ea0c05da86121 Mon Sep 17 00:00:00 2001 From: Daniel Blaecker Date: Wed, 15 Jul 2026 12:21:45 +0700 Subject: [PATCH 2/3] chore(rules): add [CONV:ADDR-BYTES32] pointing new code at LibBytes helpers (EXSC-618) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New convention so future facets use LibBytes.toBytes32 / toAddress (checked) / toAddressUnchecked instead of hand-rolling address<->bytes32 casts — which keeps call sites free of the Olympix unsafe-downcast finding (centralised in LibBytes). Co-Authored-By: Claude Opus 4.8 --- .agents/rules/100-solidity-basics.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.agents/rules/100-solidity-basics.md b/.agents/rules/100-solidity-basics.md index 2273b64f2e..de96627ee1 100644 --- a/.agents/rules/100-solidity-basics.md +++ b/.agents/rules/100-solidity-basics.md @@ -22,6 +22,15 @@ paths: - Functions/vars camelCase; constants & immutables are CONSTANT_CASE. - Function params use leading underscore (e.g., `_amount`). +## Address ⇄ bytes32 Conversions ([CONV:ADDR-BYTES32]) + +- Use the `LibBytes` helpers; never hand-roll the cast: + - `LibBytes.toBytes32(addr)` — address → bytes32 (widening, lossless). + - `LibBytes.toAddress(b)` — bytes32 → address, **checked** (reverts `NotAnAddress` if the top 96 bits are set). This is the default. + - `LibBytes.toAddressUnchecked(b)` — bytes32 → address by truncation; only where dropping the high bits is intentional / already guarded. +- A raw `bytes32(uint256(uint160(x)))` / `address(uint160(uint256(x)))` in new code is flagged by the Olympix `unsafe-downcast` detector. The helper centralises the (dismissed) finding so call sites stay clean. +- Numeric narrowing (`uintN(...)`) is out of scope here — tracked separately (EXSC-617). + ## NatSpec Requirements ([CONV:NATSPEC]) - Contracts & interfaces must include: From 0fbe4b5f92a5cee5b3825ed565ac57985ace284f Mon Sep 17 00:00:00 2001 From: Daniel Blaecker Date: Thu, 16 Jul 2026 07:50:30 +0700 Subject: [PATCH 3/3] chore(breadcrumbs): reference EXSC-626 in LibBytes migration TODOs (EXSC-618) The 21 `// TODO: migrate to LibBytes` breadcrumbs now cite the dedicated tracking ticket (EXSC-626) so they are greppable and closable, per review feedback on #2055. Co-Authored-By: Claude Opus 4.8 --- src/Facets/AcrossFacetPackedV4.sol | 10 +++++----- src/Facets/AcrossFacetV4.sol | 2 +- src/Facets/AcrossV4SwapFacet.sol | 6 +++--- src/Facets/AllBridgeFacet.sol | 6 +++--- src/Facets/CalldataVerificationFacet.sol | 2 +- src/Facets/CelerCircleBridgeFacet.sol | 2 +- src/Facets/GlacisFacet.sol | 2 +- src/Facets/LiFiIntentEscrowFacet.sol | 2 +- src/Facets/LiFiIntentEscrowFacetV2.sol | 2 +- src/Facets/NEARIntentsFacet.sol | 2 +- src/Facets/PolymerCCTPFacet.sol | 2 +- src/Facets/StargateFacetV2.sol | 2 +- src/Periphery/ReceiverOIF.sol | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Facets/AcrossFacetPackedV4.sol b/src/Facets/AcrossFacetPackedV4.sol index c362a9184e..3fb84ff6ea 100644 --- a/src/Facets/AcrossFacetPackedV4.sol +++ b/src/Facets/AcrossFacetPackedV4.sol @@ -190,7 +190,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { // pull tokens from msg.sender LibAsset.transferFromERC20( - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address(uint160(uint256(sendingAssetId))), msg.sender, address(this), @@ -230,7 +230,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { ) external { // Deposit assets LibAsset.transferFromERC20( - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address(uint160(uint256(sendingAssetId))), msg.sender, address(this), @@ -359,7 +359,7 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { // Check if receiver is EVM address (20 bytes) or non-EVM (longer) // If the first 12 bytes are zero, it's likely an EVM address if (bytes12(data[44:56]) == bytes12(0)) { - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.receiver = address( uint160(uint256(bytes32(data[44:76]))) ); @@ -401,14 +401,14 @@ contract AcrossFacetPackedV4 is ILiFi, TransferrableOwnership, LiFiData { } bridgeData.transactionId = bytes32(data[4:12]); // we truncate intentionally to save gas (not dangerous) - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.sendingAssetId = address( uint160(uint256(bytes32(data[76:108]))) ); // sendingAssetId // Check if receiver is EVM address (20 bytes) or non-EVM (longer) // If the first 12 bytes are zero, it's likely an EVM address if (bytes12(data[44:56]) == bytes12(0)) { - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 bridgeData.receiver = address( uint160(uint256(bytes32(data[44:76]))) ); diff --git a/src/Facets/AcrossFacetV4.sol b/src/Facets/AcrossFacetV4.sol index 22fc8a1a53..c8ac14774c 100644 --- a/src/Facets/AcrossFacetV4.sol +++ b/src/Facets/AcrossFacetV4.sol @@ -265,7 +265,7 @@ contract AcrossFacetV4 is function _convertAddressToBytes32( address _address ) internal pure returns (bytes32) { - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 return bytes32(uint256(uint160(_address))); } } diff --git a/src/Facets/AcrossV4SwapFacet.sol b/src/Facets/AcrossV4SwapFacet.sol index 7273d3e9c6..eec62d5943 100644 --- a/src/Facets/AcrossV4SwapFacet.sol +++ b/src/Facets/AcrossV4SwapFacet.sol @@ -359,7 +359,7 @@ contract AcrossV4SwapFacet is // Validate asset matches for ERC20 flows bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId); - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address decodedInputToken = address( uint160(uint256(params.inputToken)) ); @@ -610,7 +610,7 @@ contract AcrossV4SwapFacet is _validateAmount(quote.amount, _bridgeData.minAmount); // Validate burnToken matches bridgeData asset (native is already excluded by msg.value check above) - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address burnToken = address(uint160(uint256(quote.burnToken))); if (burnToken != _bridgeData.sendingAssetId) { revert InformationMismatch(); @@ -828,7 +828,7 @@ contract AcrossV4SwapFacet is function _convertAddressToBytes32( address _address ) internal pure returns (bytes32) { - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 return bytes32(uint256(uint160(_address))); } } diff --git a/src/Facets/AllBridgeFacet.sol b/src/Facets/AllBridgeFacet.sol index 594e88f5a3..21d20e3c02 100644 --- a/src/Facets/AllBridgeFacet.sol +++ b/src/Facets/AllBridgeFacet.sol @@ -155,7 +155,7 @@ contract AllBridgeFacet is } else { // destination chain is EVM // make sure that bridgeData and allBridgeData receiver addresses match - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( _bridgeData.receiver != address(uint160(uint256(_allBridgeData.recipient))) @@ -173,7 +173,7 @@ contract AllBridgeFacet is if (_allBridgeData.payFeeWithSendingAsset) { // pay fee with sending asset ALLBRIDGE.swapAndBridge( - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.sendingAssetId))), _bridgeData.minAmount, _allBridgeData.recipient, @@ -186,7 +186,7 @@ contract AllBridgeFacet is } else { // pay fee with native asset ALLBRIDGE.swapAndBridge{ value: _allBridgeData.fees }( - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.sendingAssetId))), _bridgeData.minAmount, _allBridgeData.recipient, diff --git a/src/Facets/CalldataVerificationFacet.sol b/src/Facets/CalldataVerificationFacet.sol index 51b6786e97..e8f573f0bb 100644 --- a/src/Facets/CalldataVerificationFacet.sol +++ b/src/Facets/CalldataVerificationFacet.sol @@ -395,7 +395,7 @@ contract CalldataVerificationFacet { } // Convert callToBytes32 to address type and compare them - // TODO: migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddressUnchecked (intentional truncation) — see LibBytes v1.1.0 address callToAddressFromBytes32 = address( uint160(uint256(callToBytes32)) ); diff --git a/src/Facets/CelerCircleBridgeFacet.sol b/src/Facets/CelerCircleBridgeFacet.sol index 81a3426ea5..a7bbe98245 100644 --- a/src/Facets/CelerCircleBridgeFacet.sol +++ b/src/Facets/CelerCircleBridgeFacet.sol @@ -125,7 +125,7 @@ contract CelerCircleBridgeFacet is CIRCLE_BRIDGE_PROXY.depositForBurn( _bridgeData.minAmount, uint64(_bridgeData.destinationChainId), - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.receiver))), USDC, _celerCircleData.maxFee, diff --git a/src/Facets/GlacisFacet.sol b/src/Facets/GlacisFacet.sol index 6339ebd93c..7023a0fc06 100644 --- a/src/Facets/GlacisFacet.sol +++ b/src/Facets/GlacisFacet.sol @@ -131,7 +131,7 @@ contract GlacisFacet is } else { // destination chain is EVM // make sure that bridgeData and glacisData receiver addresses match - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( _bridgeData.receiver != address(uint160(uint256(_glacisData.receiverAddress))) diff --git a/src/Facets/LiFiIntentEscrowFacet.sol b/src/Facets/LiFiIntentEscrowFacet.sol index 0a56653bc6..2fb446b4b0 100644 --- a/src/Facets/LiFiIntentEscrowFacet.sol +++ b/src/Facets/LiFiIntentEscrowFacet.sol @@ -202,7 +202,7 @@ contract LiFiIntentEscrowFacet is } else { // Check if the receiver is the same according to bridgeData and LIFIIntentData // Note: We already know 0 <= _bridgeData.receiver < recipient != 0 thus _bridgeData.receiver != 0. - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 if (recipient != bytes32(uint256(uint160(_bridgeData.receiver)))) { revert InvalidReceiver(); } diff --git a/src/Facets/LiFiIntentEscrowFacetV2.sol b/src/Facets/LiFiIntentEscrowFacetV2.sol index 49be096eed..385e9f4c67 100644 --- a/src/Facets/LiFiIntentEscrowFacetV2.sol +++ b/src/Facets/LiFiIntentEscrowFacetV2.sol @@ -204,7 +204,7 @@ contract LiFiIntentEscrowFacetV2 is } else { // Check if the receiver is the same according to bridgeData and LIFIIntentData // Note: We already know 0 <= _bridgeData.receiver < recipient != 0 thus _bridgeData.receiver != 0. - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 if (recipient != bytes32(uint256(uint160(_bridgeData.receiver)))) { revert InvalidReceiver(); } diff --git a/src/Facets/NEARIntentsFacet.sol b/src/Facets/NEARIntentsFacet.sol index c9eaa4f4c4..542c7e4e28 100644 --- a/src/Facets/NEARIntentsFacet.sol +++ b/src/Facets/NEARIntentsFacet.sol @@ -275,7 +275,7 @@ contract NEARIntentsFacet is ILiFi.BridgeData memory _bridgeData, NEARIntentsData calldata _nearData ) internal view { - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32 receiverBytes32 = _bridgeData.receiver == NON_EVM_ADDRESS ? _nearData.nonEVMReceiver : bytes32(uint256(uint160(_bridgeData.receiver))); diff --git a/src/Facets/PolymerCCTPFacet.sol b/src/Facets/PolymerCCTPFacet.sol index 1ba70624e0..6ad3663c0f 100644 --- a/src/Facets/PolymerCCTPFacet.sol +++ b/src/Facets/PolymerCCTPFacet.sol @@ -286,7 +286,7 @@ contract PolymerCCTPFacet is TOKEN_MESSENGER.depositForBurn( bridgeAmount, _chainIdToDomainId(destinationChainId), - // TODO: migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toBytes32 — see LibBytes v1.1.0 bytes32(uint256(uint160(_bridgeData.receiver))), USDC, UNRESTRICTED_DESTINATION_CALLER, diff --git a/src/Facets/StargateFacetV2.sol b/src/Facets/StargateFacetV2.sol index e5340e90ab..1baed2f53b 100644 --- a/src/Facets/StargateFacetV2.sol +++ b/src/Facets/StargateFacetV2.sol @@ -111,7 +111,7 @@ contract StargateFacetV2 is ILiFi, ReentrancyGuard, SwapperV2, Validatable { ) revert InformationMismatch(); // ensure that receiver addresses match in case of no destination call - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 if ( !_bridgeData.hasDestinationCall && (_bridgeData.receiver != diff --git a/src/Periphery/ReceiverOIF.sol b/src/Periphery/ReceiverOIF.sol index f5fa63c2d6..6212247228 100644 --- a/src/Periphery/ReceiverOIF.sol +++ b/src/Periphery/ReceiverOIF.sol @@ -90,7 +90,7 @@ contract ReceiverOIF is ILiFi, WithdrawablePeriphery, IOutputCallback { _swapAndCompleteBridgeTokens( transactionId, swapData, - // TODO: migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 + // TODO(EXSC-626): migrate to LibBytes.toAddress (checked) — see LibBytes v1.1.0 address(uint160(uint256(token))), payable(receiver), amount