From 36b007d01ca3d20b009550de9d2fbcb1393e662f Mon Sep 17 00:00:00 2001 From: "mia von steinkirch, phd" <1130416+miavonsteinkirch@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:27:14 -0800 Subject: [PATCH] Create dydx_flahsloan.sol --- flashloans/dydx_flahsloan.sol | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 flashloans/dydx_flahsloan.sol diff --git a/flashloans/dydx_flahsloan.sol b/flashloans/dydx_flahsloan.sol new file mode 100644 index 0000000..753bf90 --- /dev/null +++ b/flashloans/dydx_flahsloan.sol @@ -0,0 +1,61 @@ +function callFunction(address sender, Account.Info memory accountInfo, bytes memory data) external { + // Use chi tokens + uint256 gasStart = gasleft(); + + // Let the executor or the dYdX contract call this function + // probably fine to restrict to dYdX + require(msg.sender == executor || msg.sender == address(soloMargin)); + + // Decode the passed variables from the data object + ( + address[] memory sUSDAddresses, + uint256[] memory sUSDLoanIDs, + uint256 wethEstimate, + uint256 usdcEstimate, + uint256 ethToCoinbase + ) + = abi.decode(data, + ( + address[], + uint256[], + uint256, + uint256, + uint256 + )); + + // Swap WETH for USDC on uniswap v3 + uniswapRouter.exactOutputSingle( + ISwapRouter.ExactOutputSingleParams( + address(WETH), // address tokenIn; + usdcTokenAddress, // address tokenOut; + 3000, // uint24 fee; + address(this), // address recipient; + 10**18, // uint256 deadline; + usdcEstimate, // uint256 amountOut; + wethEstimate, // uint256 amountInMaximum; + 0 // uint160 sqrtPriceLimitX96; + ) + ); + + // Swap USDC for sUSD on Curve + curvePoolSUSD.exchange_underlying( + 1, // usdc + 3, // sUSD + usdcEstimate, // usdc input + 1); // min sUSD, generally not advisible to make a trade with a min amount out of 1, but its fine here I think because the overall risk of getting rekt is low + + // Liquidate the loans + for (uint256 i = 0; i < sUSDAddresses.length; i++) { + sUSDLoansAddress.liquidateUnclosedLoan(sUSDAddresses[i], sUSDLoanIDs[i]); + } + + // We got back ETH but must pay dYdX in WETH, so deposit our whole balance sans what is paid to miners + WETH.deposit{value: address(this).balance - ethToCoinbase}(); + + // Pay the miner + block.coinbase.transfer(ethToCoinbase); + + // Use for chi tokens + uint256 gasSpent = 21000 + gasStart - gasleft() + (16 * msg.data.length); + CHI.freeFromUpTo(owner, (gasSpent + 14154) / 41947); + }