Flash unwinder contracts and scripts, relay lane tuning, trustless bridge and token-aggregation updates.

Made-with: Cursor
This commit is contained in:
defiQUG
2026-04-12 06:33:54 -07:00
parent 662b35ad69
commit 6817f53591
40 changed files with 682 additions and 88 deletions

View File

@@ -5,6 +5,19 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
interface IAavePoolLike {
/// @notice Standard V3 flash loan (single-asset via length-1 arrays). Use this on Aave V3.2+ pools
/// where `flashLoanSimple` may revert with `NotActivated()`.
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata interestRateModes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/// @dev Retained for compatibility with older pool deployments; prefer `flashLoan` for new integrations.
function flashLoanSimple(
address receiverAddress,
address asset,
@@ -14,6 +27,17 @@ interface IAavePoolLike {
) external;
}
/// @dev Callback for `flashLoan` (multi-asset API).
interface IAaveFlashLoanReceiver {
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool);
}
interface IAaveFlashLoanSimpleReceiver {
function executeOperation(
address asset,
@@ -58,10 +82,10 @@ interface IAaveAtomicBridgeCoordinator {
/**
* @title AaveQuotePushFlashReceiver
* @notice Aave V3 flashLoanSimple receiver for the quote-push workflow:
* flash borrow quote -> buy PMM base -> unwind base externally -> repay lender, retaining any surplus.
* @notice Aave V3 flash-loan receiver for the quote-push workflow:
* flash borrow quote (`flashLoan` single-asset) -> buy PMM base -> unwind base externally -> repay lender, retaining any surplus.
*/
contract AaveQuotePushFlashReceiver is IAaveFlashLoanSimpleReceiver {
contract AaveQuotePushFlashReceiver is IAaveFlashLoanSimpleReceiver, IAaveFlashLoanReceiver {
using SafeERC20 for IERC20;
address public immutable pool;
@@ -119,7 +143,29 @@ contract AaveQuotePushFlashReceiver is IAaveFlashLoanSimpleReceiver {
}
function flashQuotePush(address asset, uint256 amount, QuotePushParams calldata params) external {
IAavePoolLike(pool).flashLoanSimple(address(this), asset, amount, abi.encode(address(this), params), 0);
address[] memory assets = new address[](1);
uint256[] memory amts = new uint256[](1);
uint256[] memory modes = new uint256[](1);
assets[0] = asset;
amts[0] = amount;
modes[0] = 0;
// `onBehalfOf` must not be zero on some Aave V3.2+ deployments (mapping lookups revert NotActivated).
IAavePoolLike(pool).flashLoan(
address(this), assets, amts, modes, address(this), abi.encode(address(this), params), 0
);
}
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool) {
if (msg.sender != pool) revert UntrustedPool();
if (assets.length != 1 || amounts.length != 1 || premiums.length != 1) revert BadParams();
_executeQuotePush(assets[0], amounts[0], premiums[0], initiator, params);
return true;
}
function executeOperation(
@@ -130,6 +176,17 @@ contract AaveQuotePushFlashReceiver is IAaveFlashLoanSimpleReceiver {
bytes calldata params
) external returns (bool) {
if (msg.sender != pool) revert UntrustedPool();
_executeQuotePush(asset, amount, premium, initiator, params);
return true;
}
function _executeQuotePush(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) internal {
(address expectedInitiator, QuotePushParams memory p) = abi.decode(params, (address, QuotePushParams));
if (initiator != expectedInitiator) revert UntrustedInitiator();
if (
@@ -148,7 +205,6 @@ contract AaveQuotePushFlashReceiver is IAaveFlashLoanSimpleReceiver {
uint256 unwindOut = _unwindBaseIntoQuote(p.baseToken, asset, p.externalUnwinder, p.minOutUnwind, p.unwindData);
uint256 surplus = _approveRepayment(asset, amount + premium);
emit QuotePushExecuted(asset, p.baseToken, amount, premium, baseOut, unwindOut, surplus);
return true;
}
function _swapQuoteForBase(address asset, uint256 amount, address integration, address pmmPool, uint256 minOutPmm)