Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CalldataVerificationFacet [CalldataVerificationFacet v1.3.0] #1003

Merged
merged 9 commits into from
Feb 26, 2025
10 changes: 9 additions & 1 deletion audit/auditLog.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@
"auditorGitHandle": "sujithsomraaj",
"auditReportPath": "./audit/reports/2025.01.17_LiFiDexAggregator(v1.4.0).pdf",
"auditCommitHash": "n/a (one deployed contract instance was audited)"
},
"audit20250220": {
"auditCompletedOn": "20.02.2025",
"auditedBy": "Sujith Somraaj (individual security researcher)",
"auditorGitHandle": "sujithsomraaj",
"auditReportPath": "./audit/reports/2025.02.20_CalldataVerificationFacet(v1.3.0).pdf",
"auditCommitHash": "48427d21160585f276d206f0e103ce6bd42c4c03"
}
},
"auditedContracts": {
Expand All @@ -172,7 +179,8 @@
"1.2.0": ["audit20241206"]
},
"CalldataVerificationFacet": {
"1.2.0": ["audit20240902"]
"1.2.0": ["audit20240902"],
"1.3.0": ["audit20250220"]
},
"DeBridgeDlnFacet": {
"1.0.0": ["audit20241205"]
Expand Down
Binary file not shown.
138 changes: 13 additions & 125 deletions src/Facets/CalldataVerificationFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@

import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { AmarokFacet } from "./AmarokFacet.sol";
import { AcrossFacetV3 } from "./AcrossFacetV3.sol";
import { StargateFacetV2 } from "./StargateFacetV2.sol";
import { StargateFacet } from "./StargateFacet.sol";
import { AcrossFacetV3 } from "./AcrossFacetV3.sol";
import { CelerIMFacetBase, CelerIM } from "lifi/Helpers/CelerIMFacetBase.sol";
import { StandardizedCallFacet } from "lifi/Facets/StandardizedCallFacet.sol";
import { LibBytes } from "../Libraries/LibBytes.sol";
import { GenericSwapFacetV3 } from "lifi/Facets/GenericSwapFacetV3.sol";
import { InvalidCallData } from "../Errors/GenericErrors.sol";

/// @title CalldataVerificationFacet
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for verifying calldata
/// @custom:version 1.2.0
/// @custom:version 1.3.0
contract CalldataVerificationFacet {
using LibBytes for bytes;

Expand Down Expand Up @@ -111,16 +107,7 @@
function extractNonEVMAddress(
bytes calldata data
) external pure returns (bytes32 nonEVMAddress) {
bytes memory callData;

if (
bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector
) {
// standardizedCall
callData = abi.decode(data[4:], (bytes));
} else {
callData = data;
}
bytes memory callData = data;

// Non-EVM address is always the first parameter of bridge specific data
if (_extractBridgeData(data).hasSourceSwaps) {
Expand Down Expand Up @@ -169,22 +156,8 @@
}

LibSwap.SwapData[] memory swapData;
bytes memory callData;
bytes4 functionSelector = bytes4(data[:4]);

// check if this is a call via StandardizedCallFacet
if (
functionSelector == StandardizedCallFacet.standardizedCall.selector
) {
// extract nested function selector and calldata
// will always start at position 68
functionSelector = bytes4(data[68:72]);
callData = data[68:];
// callData = abi.decode(data[4:], (bytes)); // this one is also valid, even though the calldata differs slightly (add. padding)
} else {
callData = data;
}

if (
functionSelector ==
GenericSwapFacetV3.swapTokensSingleV3ERC20ToERC20.selector ||
Expand All @@ -198,13 +171,13 @@

// extract parameters from calldata
(, , , receiver, receivingAmount, swapData[0]) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(bytes32, string, string, address, uint256, LibSwap.SwapData)
);
} else {
// multi swap or GenericSwap V1 call
(, , , receiver, receivingAmount, swapData) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(bytes32, string, string, address, uint256, LibSwap.SwapData[])
);
}
Expand Down Expand Up @@ -273,68 +246,7 @@
bytes calldata callTo,
bytes calldata dstCalldata
) external pure returns (bool isValid) {
bytes memory callData = data;

// Handle standardizedCall
if (
bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector
) {
callData = abi.decode(data[4:], (bytes));
}

bytes4 selector = abi.decode(callData, (bytes4));

// ---------------------------------------
// Case: Amarok
if (selector == AmarokFacet.startBridgeTokensViaAmarok.selector) {
(, AmarokFacet.AmarokData memory amarokData) = abi.decode(
callData.slice(4, callData.length - 4),
(ILiFi.BridgeData, AmarokFacet.AmarokData)
);

return
keccak256(dstCalldata) == keccak256(amarokData.callData) &&
abi.decode(callTo, (address)) == amarokData.callTo;
}
if (
selector == AmarokFacet.swapAndStartBridgeTokensViaAmarok.selector
) {
(, , AmarokFacet.AmarokData memory amarokData) = abi.decode(
callData.slice(4, callData.length - 4),
(ILiFi.BridgeData, LibSwap.SwapData[], AmarokFacet.AmarokData)
);
return
keccak256(dstCalldata) == keccak256(amarokData.callData) &&
abi.decode(callTo, (address)) == amarokData.callTo;
}

// ---------------------------------------
// Case: Stargate
if (selector == StargateFacet.startBridgeTokensViaStargate.selector) {
(, StargateFacet.StargateData memory stargateData) = abi.decode(
callData.slice(4, callData.length - 4),
(ILiFi.BridgeData, StargateFacet.StargateData)
);
return
keccak256(dstCalldata) == keccak256(stargateData.callData) &&
keccak256(callTo) == keccak256(stargateData.callTo);
}
if (
selector ==
StargateFacet.swapAndStartBridgeTokensViaStargate.selector
) {
(, , StargateFacet.StargateData memory stargateData) = abi.decode(
callData.slice(4, callData.length - 4),
(
ILiFi.BridgeData,
LibSwap.SwapData[],
StargateFacet.StargateData
)
);
return
keccak256(dstCalldata) == keccak256(stargateData.callData) &&
keccak256(callTo) == keccak256(stargateData.callTo);
}
bytes4 selector = bytes4(data[:4]);

// ---------------------------------------
// Case: StargateV2
Expand All @@ -344,7 +256,7 @@
) {
(, StargateFacetV2.StargateData memory stargateDataV2) = abi
.decode(
callData.slice(4, callData.length - 4),
data[4:],
(ILiFi.BridgeData, StargateFacetV2.StargateData)
);

Expand All @@ -362,7 +274,7 @@
) {
(, , StargateFacetV2.StargateData memory stargateDataV2) = abi
.decode(
callData.slice(4, callData.length - 4),
data[4:],
(
ILiFi.BridgeData,
LibSwap.SwapData[],
Expand All @@ -385,7 +297,7 @@
selector == CelerIMFacetBase.startBridgeTokensViaCelerIM.selector
) {
(, CelerIM.CelerIMData memory celerIMData) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(ILiFi.BridgeData, CelerIM.CelerIMData)
);
return
Expand All @@ -397,7 +309,7 @@
CelerIMFacetBase.swapAndStartBridgeTokensViaCelerIM.selector
) {
(, , CelerIM.CelerIMData memory celerIMData) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(ILiFi.BridgeData, LibSwap.SwapData[], CelerIM.CelerIMData)
);
return
Expand All @@ -407,7 +319,7 @@
// Case: AcrossV3
if (selector == AcrossFacetV3.startBridgeTokensViaAcrossV3.selector) {
(, AcrossFacetV3.AcrossV3Data memory acrossV3Data) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(ILiFi.BridgeData, AcrossFacetV3.AcrossV3Data)
);

Expand All @@ -421,7 +333,7 @@
AcrossFacetV3.swapAndStartBridgeTokensViaAcrossV3.selector
) {
(, , AcrossFacetV3.AcrossV3Data memory acrossV3Data) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(
ILiFi.BridgeData,
LibSwap.SwapData[],
Expand All @@ -438,7 +350,7 @@
// Case: AcrossV3
if (selector == AcrossFacetV3.startBridgeTokensViaAcrossV3.selector) {
(, AcrossFacetV3.AcrossV3Data memory acrossV3Data) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(ILiFi.BridgeData, AcrossFacetV3.AcrossV3Data)
);

Expand All @@ -452,7 +364,7 @@
AcrossFacetV3.swapAndStartBridgeTokensViaAcrossV3.selector
) {
(, , AcrossFacetV3.AcrossV3Data memory acrossV3Data) = abi.decode(
callData.slice(4, callData.length - 4),
data[4:],
(
ILiFi.BridgeData,
LibSwap.SwapData[],
Expand All @@ -477,18 +389,6 @@
function _extractBridgeData(
bytes calldata data
) internal pure returns (ILiFi.BridgeData memory bridgeData) {
if (
bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector
) {
// StandardizedCall
bytes memory unwrappedData = abi.decode(data[4:], (bytes));
bridgeData = abi.decode(
unwrappedData.slice(4, unwrappedData.length - 4),
(ILiFi.BridgeData)
);
return bridgeData;
}
// normal call
bridgeData = abi.decode(data[4:], (ILiFi.BridgeData));
}

Expand All @@ -498,18 +398,6 @@
function _extractSwapData(
bytes calldata data
) internal pure returns (LibSwap.SwapData[] memory swapData) {
if (
bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector
) {
// standardizedCall
bytes memory unwrappedData = abi.decode(data[4:], (bytes));
(, swapData) = abi.decode(
unwrappedData.slice(4, unwrappedData.length - 4),
(ILiFi.BridgeData, LibSwap.SwapData[])
);
return swapData;
}
// normal call
(, swapData) = abi.decode(
data[4:],
(ILiFi.BridgeData, LibSwap.SwapData[])
Expand Down
Loading
Loading