From 3d2552abcb0d5395ed1554db408b8082fdd3f8c9 Mon Sep 17 00:00:00 2001 From: itofarina Date: Tue, 31 Dec 2024 14:29:27 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20propose=20swap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit co-authored-by: danilo neves cruz --- contracts/src/ExaPlugin.sol | 43 ++++++++++++++++++++++++++++------- contracts/src/IExaAccount.sol | 3 +++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/contracts/src/ExaPlugin.sol b/contracts/src/ExaPlugin.sol index 257d6f59..5ba5e5fa 100644 --- a/contracts/src/ExaPlugin.sol +++ b/contracts/src/ExaPlugin.sol @@ -112,12 +112,28 @@ contract ExaPlugin is AccessControl, BasePlugin, IExaAccount { function propose(IMarket market, uint256 amount, address receiver) external { _checkMarket(market); - proposals[msg.sender] = Proposal({ amount: amount, market: market, timestamp: block.timestamp, receiver: receiver }); + proposals[msg.sender] = + Proposal({ amount: amount, market: market, timestamp: block.timestamp, receiver: receiver, swapData: "" }); emit Proposed(msg.sender, market, receiver, amount, block.timestamp + PROPOSAL_DELAY); } - function swap(IERC20 assetIn, IERC20 assetOut, uint256 maxAmountIn, uint256 minAmountOut, bytes memory route) + // TODO add to manifest, only self. or merge with propose + function proposeSwap(IMarket market, uint256 amount, IERC20 assetOut, uint256 minAmountOut, bytes memory route) external + { + _checkMarket(market); + proposals[msg.sender] = Proposal({ + amount: amount, + market: market, + timestamp: block.timestamp, + receiver: msg.sender, + swapData: abi.encode(SwapData({ assetOut: assetOut, minAmountOut: minAmountOut, route: route })) + }); + // TODO emit + } + + function swap(IERC20 assetIn, IERC20 assetOut, uint256 maxAmountIn, uint256 minAmountOut, bytes memory route) + public returns (uint256 amountIn, uint256 amountOut) { uint256 balanceIn = assetIn.balanceOf(msg.sender); @@ -202,14 +218,19 @@ contract ExaPlugin is AccessControl, BasePlugin, IExaAccount { address market = address(proposal.market); if (market == address(0)) revert NoProposal(); + uint256 amount = proposal.amount; if (market != address(EXA_WETH)) { - _executeFromSender(market, 0, abi.encodeCall(IERC4626.withdraw, (proposal.amount, proposal.receiver, msg.sender))); - return; + _executeFromSender(market, 0, abi.encodeCall(IERC4626.withdraw, (amount, proposal.receiver, msg.sender))); + } else { + _executeFromSender(market, 0, abi.encodeCall(IERC4626.withdraw, (amount, address(this), msg.sender))); + WETH.withdraw(amount); + proposal.receiver.safeTransferETH(amount); + } + + if (proposal.swapData.length != 0) { + SwapData memory data = abi.decode(proposal.swapData, (SwapData)); + swap(IERC20(proposal.market.asset()), data.assetOut, amount, data.minAmountOut, data.route); } - uint256 amount = proposal.amount; - _executeFromSender(market, 0, abi.encodeCall(IERC4626.withdraw, (amount, address(this), msg.sender))); - WETH.withdraw(amount); - proposal.receiver.safeTransferETH(amount); } function collectCollateral( @@ -750,3 +771,9 @@ struct RepayCallbackData { uint256 positionAssets; uint256 maxRepay; } + +struct SwapData { + IERC20 assetOut; + uint256 minAmountOut; + bytes route; +} diff --git a/contracts/src/IExaAccount.sol b/contracts/src/IExaAccount.sol index 62e315e4..28b7bfd4 100644 --- a/contracts/src/IExaAccount.sol +++ b/contracts/src/IExaAccount.sol @@ -6,6 +6,8 @@ import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.s interface IExaAccount { function propose(IMarket market, uint256 amount, address receiver) external; + function proposeSwap(IMarket market, uint256 amount, IERC20 assetOut, uint256 minAmountOut, bytes memory route) + external; function swap(IERC20 assetIn, IERC20 assetOut, uint256 maxAmountIn, uint256 minAmountOut, bytes memory route) external returns (uint256 amountIn, uint256 amountOut); @@ -87,6 +89,7 @@ struct Proposal { IMarket market; address receiver; uint256 timestamp; + bytes swapData; } error BorrowLimitExceeded();