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

(fix): adds calldata extraction handling for GenericSwapV3 single swap calls (CallDataVerificationFacet v1.2.0) [CalldataVerificationFacet v1.2.0,IAcrossSpokePool v1.0.0] #767

Merged
merged 24 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
511f3d1
adds extraction handling for GenericSwapV3 single calldata
0xDEnYO Aug 16, 2024
9912f64
push test coverage to 100%
0xDEnYO Aug 16, 2024
96fa80d
remove lcov-filtered.info
0xDEnYO Aug 16, 2024
3ee3d93
minor update
0xDEnYO Aug 16, 2024
121dd30
Merge branch 'main' into fixCallDataVerificationFacet
0xDEnYO Aug 16, 2024
7af5e5b
remove console import
0xDEnYO Aug 16, 2024
7838b0b
Merge branch 'fixCallDataVerificationFacet' of github.com:lifinance/c…
0xDEnYO Aug 16, 2024
1c7cc45
Merge branch 'main' into fixCallDataVerificationFacet
ezynda3 Aug 19, 2024
374d066
Merge branch 'main' into fixCallDataVerificationFacet
0xDEnYO Aug 21, 2024
51b585a
gas optimization (audit issue #7)
0xDEnYO Aug 29, 2024
afa7dab
adds handling for StargateV2 destination calls (audit issue #8)
0xDEnYO Aug 29, 2024
65aeb11
gas optimization in extractGenericSwapParameters (audit issue #6)
0xDEnYO Aug 29, 2024
a4c2574
update min callData length check (audit issue #4)
0xDEnYO Aug 29, 2024
2475ff1
gas optimization in extractNonEVMAddress (audit issue #3)
0xDEnYO Aug 29, 2024
ecb03c8
update comments, fix typo (audit issue#2)
0xDEnYO Aug 29, 2024
6a7b6b1
adds handling for AcrossV3 destination calls (audit issue #9)
0xDEnYO Aug 29, 2024
dcadf14
Merge branch 'main' of github.com:lifinance/contracts into fixCallDat…
0xDEnYO Aug 30, 2024
f9c6beb
Merge branch 'fixCallDataVerificationFacet' of github.com:lifinance/c…
0xDEnYO Aug 30, 2024
71ae339
typo fixed in comment
0xDEnYO Sep 2, 2024
028bcc2
gas optimization
0xDEnYO Sep 2, 2024
9a93c45
updates audit log and adds audit report
0xDEnYO Sep 3, 2024
c81517f
Merge branch 'main' of github.com:lifinance/contracts into fixCallDat…
0xDEnYO Oct 17, 2024
b7f25a3
Merge branch 'main' into fixCallDataVerificationFacet
ezynda3 Jan 11, 2025
de8c0e1
update log
ezynda3 Jan 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions src/Facets/AcrossFacetV3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { IAcrossSpokePool } from "../Interfaces/IAcrossSpokePool.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { ReentrancyGuard } from "../Helpers/ReentrancyGuard.sol";
import { SwapperV2 } from "../Helpers/SwapperV2.sol";
import { Validatable } from "../Helpers/Validatable.sol";
import { InformationMismatch } from "../Errors/GenericErrors.sol";

/// @title AcrossFacetV3
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for bridging through Across Protocol
/// @custom:version 1.0.0
contract AcrossFacetV3 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
/// Storage ///

/// @notice The contract address of the spoke pool on the source chain.
IAcrossSpokePool public immutable spokePool;

/// @notice The WETH address on the current chain.
address public immutable wrappedNative;

/// Types ///

/// @param receiverAddress The address that will receive the token on dst chain (our Receiver contract or the user-defined receiver address)
/// @param refundAddress The address that will be used for potential bridge refunds
/// @param receivingAssetId The address of the token to be received at destination chain
/// @param outputAmount The amount to be received at destination chain (after fees)
/// @param quoteTimestamp The timestamp of the Across quote that was used for this transaction
/// @param fillDeadline The destination chain timestamp until which the order can be filled
/// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens
struct AcrossV3Data {
address receiverAddress;
address refundAddress;
address receivingAssetId;
uint256 outputAmount;
uint32 quoteTimestamp;
uint32 fillDeadline;
bytes message;
}

/// Constructor ///

/// @notice Initialize the contract.
/// @param _spokePool The contract address of the spoke pool on the source chain.
/// @param _wrappedNative The address of the wrapped native token on the source chain.
constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {
spokePool = _spokePool;
wrappedNative = _wrappedNative;
}

/// External Methods ///

/// @notice Bridges tokens via Across
/// @param _bridgeData the core information needed for bridging
/// @param _acrossData data specific to Across
function startBridgeTokensViaAcrossV3(
ILiFi.BridgeData memory _bridgeData,
AcrossV3Data calldata _acrossData
)
external
payable
nonReentrant
refundExcessNative(payable(msg.sender))
validateBridgeData(_bridgeData)
doesNotContainSourceSwaps(_bridgeData)
{
LibAsset.depositAsset(
_bridgeData.sendingAssetId,
_bridgeData.minAmount
);
_startBridge(_bridgeData, _acrossData);
}

/// @notice Performs a swap before bridging via Across
/// @param _bridgeData the core information needed for bridging
/// @param _swapData an array of swap related data for performing swaps before bridging
/// @param _acrossData data specific to Across
function swapAndStartBridgeTokensViaAcrossV3(
ILiFi.BridgeData memory _bridgeData,
LibSwap.SwapData[] calldata _swapData,
AcrossV3Data calldata _acrossData
)
external
payable
nonReentrant
refundExcessNative(payable(msg.sender))
containsSourceSwaps(_bridgeData)
validateBridgeData(_bridgeData)
{
_bridgeData.minAmount = _depositAndSwap(
_bridgeData.transactionId,
_bridgeData.minAmount,
_swapData,
payable(msg.sender)
);
_startBridge(_bridgeData, _acrossData);
}

/// Internal Methods ///

/// @dev Contains the business logic for the bridge via Across
/// @param _bridgeData the core information needed for bridging
/// @param _acrossData data specific to Across
function _startBridge(
ILiFi.BridgeData memory _bridgeData,
AcrossV3Data calldata _acrossData
) internal {
// validate destination call flag
if (_acrossData.message.length > 0 != _bridgeData.hasDestinationCall)
revert InformationMismatch();

// ensure that receiver addresses match in case of no destination call
if (
!_bridgeData.hasDestinationCall &&
(_bridgeData.receiver != _acrossData.receiverAddress)
) revert InformationMismatch();

// check if sendingAsset is native or ERC20
if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {
// NATIVE
spokePool.depositV3{ value: _bridgeData.minAmount }(
_acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)
_acrossData.receiverAddress, // recipient (on dst)
wrappedNative, // inputToken
_acrossData.receivingAssetId, // outputToken
_bridgeData.minAmount, // inputAmount
_acrossData.outputAmount, // outputAmount
_bridgeData.destinationChainId,
address(0), // exclusiveRelayer (not used by us)
_acrossData.quoteTimestamp,
_acrossData.fillDeadline,
0, // exclusivityDeadline (not used by us)
_acrossData.message
);
} else {
// ERC20
LibAsset.maxApproveERC20(
IERC20(_bridgeData.sendingAssetId),
address(spokePool),
_bridgeData.minAmount
);
spokePool.depositV3(
_acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)
_acrossData.receiverAddress, // recipient (on dst)
_bridgeData.sendingAssetId, // inputToken
_acrossData.receivingAssetId, // outputToken
_bridgeData.minAmount, // inputAmount
_acrossData.outputAmount, // outputAmount
_bridgeData.destinationChainId,
address(0), // exclusiveRelayer (not used by us)
_acrossData.quoteTimestamp,
_acrossData.fillDeadline,
0, // exclusivityDeadline (not used by us)
_acrossData.message
);
}

emit LiFiTransferStarted(_bridgeData);
}
}
Loading
Loading