Flash unwinder contracts and scripts, relay lane tuning, trustless bridge and token-aggregation updates.
Made-with: Cursor
This commit is contained in:
139
script/flash/RunMainnetAaveCwusdcUsdcQuotePushOnce.s.sol
Normal file
139
script/flash/RunMainnetAaveCwusdcUsdcQuotePushOnce.s.sol
Normal file
@@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {AaveQuotePushFlashReceiver} from "../../contracts/flash/AaveQuotePushFlashReceiver.sol";
|
||||
|
||||
interface IDODOPMMPoolQuote {
|
||||
function querySellQuote(address trader, uint256 payQuoteAmount) external view returns (uint256 receiveBaseAmount, uint256 mtFee);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title RunMainnetAaveCwusdcUsdcQuotePushOnce
|
||||
* @notice Single Aave flash quote-push round: borrow USDC -> PMM quote-in -> external unwind -> repay.
|
||||
*
|
||||
* Prereqs: deploy AaveQuotePushFlashReceiver + an IAaveExternalUnwinder (e.g. UniswapV3ExternalUnwinder).
|
||||
*
|
||||
* Env (required unless noted):
|
||||
* PRIVATE_KEY
|
||||
* AAVE_QUOTE_PUSH_RECEIVER_MAINNET
|
||||
* DODO_PMM_INTEGRATION_MAINNET
|
||||
* QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET
|
||||
* FLASH_QUOTE_AMOUNT_RAW gross USDC borrowed / pushed (6 decimals raw)
|
||||
*
|
||||
* Optional:
|
||||
* POOL_CWUSDC_USDC_MAINNET default 0x69776fc607e9edA8042e320e7e43f54d06c68f0E
|
||||
* CWUSDC_MAINNET default canonical cWUSDC
|
||||
* USDC_MAINNET default official USDC
|
||||
* MIN_OUT_PMM if unset, derived from querySellQuote(receiver, amount) * MIN_OUT_PMM_NUM / MIN_OUT_PMM_DEN (defaults 985/1000)
|
||||
* MIN_OUT_PMM_NUM / MIN_OUT_PMM_DEN
|
||||
* MIN_OUT_UNWIND if unset, amount + ceil(amount * AAVE_FLASH_PREMIUM_BPS / 10000) + MIN_OUT_UNWIND_BUFFER_RAW
|
||||
* AAVE_FLASH_PREMIUM_BPS default 5 (Aave V3 simple flash typical)
|
||||
* MIN_OUT_UNWIND_BUFFER_RAW default 5000 raw (~0.005 USDC) headroom
|
||||
* UNWIND_MODE 0 = Uniswap V3 exactInputSingle (abi.encode uint24 fee); 1 = DODO pool (abi.encode address pool);
|
||||
* 2 = Uniswap V3 exactInput multi-hop: unwindData = abi.encode(path), path from UNWIND_V3_PATH_HEX
|
||||
* UNWIND_V3_FEE_U24 required when UNWIND_MODE=0 (e.g. 500, 3000, 10000)
|
||||
* UNWIND_DODO_POOL required when UNWIND_MODE=1
|
||||
* UNWIND_V3_PATH_HEX required when UNWIND_MODE=2 — packed exactInput path (see UniswapV3ExternalUnwinder); build via:
|
||||
* bash scripts/verify/build-uniswap-v3-exact-input-path-hex.sh ADDR0 FEE0 ... ADDRN
|
||||
* UNWIND_MODE=4 TwoHopDodoIntegrationUnwinder: set UNWIND_TWO_HOP_POOL_A, UNWIND_TWO_HOP_POOL_B,
|
||||
* UNWIND_TWO_HOP_MID_TOKEN, optional UNWIND_MIN_MID_OUT_RAW (default 1 wei)
|
||||
* UNWIND_MODE=5 DODOToUniswapV3MultiHopExternalUnwinder:
|
||||
* set UNWIND_DODO_POOL, UNWIND_INTERMEDIATE_TOKEN, UNWIND_MIN_INTERMEDIATE_OUT_RAW,
|
||||
* UNWIND_V3_PATH_HEX (path starts at intermediate token and ends at tokenOut)
|
||||
*/
|
||||
contract RunMainnetAaveCwusdcUsdcQuotePushOnce is Script {
|
||||
address internal constant DEFAULT_POOL = 0x69776fc607e9edA8042e320e7e43f54d06c68f0E;
|
||||
address internal constant DEFAULT_CWUSDC = 0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a;
|
||||
address internal constant DEFAULT_USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address receiver = vm.envAddress("AAVE_QUOTE_PUSH_RECEIVER_MAINNET");
|
||||
address pool = vm.envOr("POOL_CWUSDC_USDC_MAINNET", DEFAULT_POOL);
|
||||
address integration = vm.envAddress("DODO_PMM_INTEGRATION_MAINNET");
|
||||
address baseToken = vm.envOr("CWUSDC_MAINNET", DEFAULT_CWUSDC);
|
||||
address usdc = vm.envOr("USDC_MAINNET", DEFAULT_USDC);
|
||||
address unwinder = vm.envAddress("QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET");
|
||||
uint256 amount = vm.envUint("FLASH_QUOTE_AMOUNT_RAW");
|
||||
|
||||
uint256 minPmmNum = vm.envOr("MIN_OUT_PMM_NUM", uint256(985));
|
||||
uint256 minPmmDen = vm.envOr("MIN_OUT_PMM_DEN", uint256(1000));
|
||||
|
||||
uint256 minOutPmm = vm.envOr("MIN_OUT_PMM", uint256(0));
|
||||
if (minOutPmm == 0) {
|
||||
(uint256 baseOut,) = IDODOPMMPoolQuote(pool).querySellQuote(receiver, amount);
|
||||
minOutPmm = (baseOut * minPmmNum) / minPmmDen;
|
||||
}
|
||||
|
||||
uint256 premiumBps = vm.envOr("AAVE_FLASH_PREMIUM_BPS", uint256(5));
|
||||
uint256 buf = vm.envOr("MIN_OUT_UNWIND_BUFFER_RAW", uint256(5000));
|
||||
uint256 minOutUnwind = vm.envOr("MIN_OUT_UNWIND", uint256(0));
|
||||
if (minOutUnwind == 0) {
|
||||
uint256 premium = (amount * premiumBps) / 10000;
|
||||
minOutUnwind = amount + premium + buf;
|
||||
}
|
||||
|
||||
uint256 unwindMode = vm.envOr("UNWIND_MODE", uint256(0));
|
||||
bytes memory unwindData;
|
||||
if (unwindMode == 0) {
|
||||
uint24 fee = uint24(vm.envUint("UNWIND_V3_FEE_U24"));
|
||||
unwindData = abi.encode(fee);
|
||||
} else if (unwindMode == 1) {
|
||||
address dodoPool = vm.envAddress("UNWIND_DODO_POOL");
|
||||
unwindData = abi.encode(dodoPool);
|
||||
} else if (unwindMode == 2) {
|
||||
string memory pathHex = vm.envString("UNWIND_V3_PATH_HEX");
|
||||
bytes memory path = vm.parseBytes(pathHex);
|
||||
unwindData = abi.encode(path);
|
||||
} else if (unwindMode == 4) {
|
||||
address poolA = vm.envAddress("UNWIND_TWO_HOP_POOL_A");
|
||||
address poolB = vm.envAddress("UNWIND_TWO_HOP_POOL_B");
|
||||
address midToken = vm.envAddress("UNWIND_TWO_HOP_MID_TOKEN");
|
||||
uint256 minMidOut = vm.envOr("UNWIND_MIN_MID_OUT_RAW", uint256(1));
|
||||
unwindData = abi.encode(poolA, poolB, midToken, minMidOut);
|
||||
} else if (unwindMode == 5) {
|
||||
address dodoPool = vm.envAddress("UNWIND_DODO_POOL");
|
||||
address intermediateToken = vm.envAddress("UNWIND_INTERMEDIATE_TOKEN");
|
||||
uint256 minIntermediateOut = vm.envOr("UNWIND_MIN_INTERMEDIATE_OUT_RAW", uint256(1));
|
||||
string memory pathHex = vm.envString("UNWIND_V3_PATH_HEX");
|
||||
bytes memory path = vm.parseBytes(pathHex);
|
||||
unwindData = abi.encode(dodoPool, intermediateToken, minIntermediateOut, path);
|
||||
} else {
|
||||
revert("UNWIND_MODE must be 0, 1, 2, 4, or 5");
|
||||
}
|
||||
|
||||
AaveQuotePushFlashReceiver.QuotePushParams memory p = AaveQuotePushFlashReceiver.QuotePushParams({
|
||||
integration: integration,
|
||||
pmmPool: pool,
|
||||
baseToken: baseToken,
|
||||
externalUnwinder: unwinder,
|
||||
minOutPmm: minOutPmm,
|
||||
minOutUnwind: minOutUnwind,
|
||||
unwindData: unwindData,
|
||||
atomicBridge: AaveQuotePushFlashReceiver.AtomicBridgeParams({
|
||||
coordinator: address(0),
|
||||
sourceChain: 0,
|
||||
destinationChain: 0,
|
||||
destinationAsset: address(0),
|
||||
bridgeAmount: 0,
|
||||
minDestinationAmount: 0,
|
||||
destinationRecipient: address(0),
|
||||
destinationDeadline: 0,
|
||||
routeId: bytes32(0),
|
||||
settlementMode: bytes32(0),
|
||||
submitCommitment: false
|
||||
})
|
||||
});
|
||||
|
||||
console.log("receiver", receiver);
|
||||
console.log("pool", pool);
|
||||
console.log("amount", amount);
|
||||
console.log("minOutPmm", minOutPmm);
|
||||
console.log("minOutUnwind", minOutUnwind);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
AaveQuotePushFlashReceiver(receiver).flashQuotePush(usdc, amount, p);
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user