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

flash swap attempt #14

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions src/abstract/OrderBookFlashLender.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/Safe

import "../interface/ierc3156/IERC3156FlashBorrower.sol";
import "../interface/ierc3156/IERC3156FlashLender.sol";
import "../interface/unstable/IOrderBookV3TokenWithdrawer.sol";

/// Thrown when `flashLoan` token is zero address.
error ZeroToken();
Expand Down Expand Up @@ -97,11 +98,12 @@ abstract contract OrderBookFlashLender is IERC3156FlashLender {
/// @param token The token being sent or for the debt being paid.
/// @param receiver The receiver of the token or holder of the debt.
/// @param sendAmount The amount to send or repay.
function _decreaseFlashDebtThenSendToken(address token, address receiver, uint256 sendAmount) internal {
function _decreaseFlashDebtThenSendToken(address token, address receiver, uint256 sendAmount, bytes memory data) internal {
// If this token transfer matches the active debt then prioritise
// reducing debt over sending tokens.
uint256 debtReduction = 0;
if (token == _sToken && receiver == address(_sReceiver)) {
uint256 debtReduction = sendAmount.min(_sAmountUnpaid);
debtReduction = sendAmount.min(_sAmountUnpaid);
sendAmount -= debtReduction;

// Even if this completely zeros the amount the debt is considered
Expand All @@ -112,6 +114,9 @@ abstract contract OrderBookFlashLender is IERC3156FlashLender {
if (sendAmount > 0) {
IERC20(token).safeTransfer(receiver, sendAmount);
}
if (data.length > 0) {
IOrderBookV3TokenWithdrawer(receiver).onWithdrawal(token, sendAmount, debtReduction, data);
}
}

/// @inheritdoc IERC3156FlashLender
Expand Down
19 changes: 15 additions & 4 deletions src/concrete/OrderBook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ contract OrderBook is IOrderBookV3, ReentrancyGuard, Multicall, OrderBookFlashLe
}

/// @inheritdoc IOrderBookV3
function withdraw(address token, uint256 vaultId, uint256 targetAmount) external nonReentrant {
function withdraw(address token, uint256 vaultId, uint256 targetAmount, bytes memory data) external nonReentrant {
if (targetAmount == 0) {
revert ZeroWithdrawTargetAmount(msg.sender, token, vaultId);
}
Expand All @@ -254,6 +254,16 @@ contract OrderBook is IOrderBookV3, ReentrancyGuard, Multicall, OrderBookFlashLe
}
}

function _tokenWithdrawal(address token, address receiver, uint256 amount) internal {
if (amount > 0) {
// The overflow check here is redundant with .min above, so
// technically this is overly conservative but we REALLY don't want
// withdrawals to exceed vault balances.
emit Withdraw(address(this), token, 0, amount, amount);
_decreaseFlashDebtThenSendToken(token, receiver, amount);
}
}

/// @inheritdoc IOrderBookV3
function addOrder(OrderConfigV2 calldata config) external nonReentrant returns (bool stateChanged) {
uint256 sourceCount = LibBytecode.sourceCount(config.evaluableConfig.bytecode);
Expand Down Expand Up @@ -381,13 +391,14 @@ contract OrderBook is IOrderBookV3, ReentrancyGuard, Multicall, OrderBookFlashLe
revert MinimumInput(config.minimumInput, totalInput);
}

// Prioritise paying down any active flash loans before sending any
// tokens to `msg.sender`.
_tokenWithdrawal(config.input, msg.sender, totalInput);

// We already updated vault balances before we took tokens from
// `msg.sender` which is usually NOT the correct order of operations for
// depositing to a vault. We rely on reentrancy guards to make this safe.
IERC20(config.output).safeTransferFrom(msg.sender, address(this), totalOutput);
// Prioritise paying down any active flash loans before sending any
// tokens to `msg.sender`.
_decreaseFlashDebtThenSendToken(config.input, msg.sender, totalInput);
}

/// @inheritdoc IOrderBookV3
Expand Down
7 changes: 6 additions & 1 deletion src/interface/unstable/IOrderBookV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ interface IOrderBookV3 is IERC3156FlashLender, IInterpreterCallerV2 {
/// target amount if the vault does not have the funds available to cover
/// the target amount. For example an active order might move tokens before
/// the withdraw completes.

event Withdraw(address sender, address token, uint256 vaultId, uint256 targetAmount, uint256 amount);

/// An order has been added to the orderbook. The order is permanently and
Expand Down Expand Up @@ -455,7 +456,11 @@ interface IOrderBookV3 is IERC3156FlashLender, IInterpreterCallerV2 {
/// result in fewer tokens withdrawn if the vault balance is lower than the
/// target amount. MAY NOT be zero, the order book MUST revert with
/// `ZeroWithdrawTargetAmount` if the amount is zero.
function withdraw(address token, uint256 vaultId, uint256 targetAmount) external;
/// @param data Optional arbitrary data that will cause
/// `IOrderBookV3TokenWithdrawer.onWithdrawal` to be called on `msg.sender`
/// if the data has non-zero length. The data is forwarded to the
/// `onWithdrawal` call as-is.
function withdraw(address token, uint256 vaultId, uint256 targetAmount, bytes memory data) external;

/// Given an order config, deploys the expression and builds the full `Order`
/// for the config, then records it as an active order. Delegated adding an
Expand Down
11 changes: 11 additions & 0 deletions src/interface/unstable/IOrderBookV3TokenWithdrawer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-Licdnse-Identifier: CAL
pragma solidity ^0.8.18;

interface IOrderBookV3TokenWithdrawer {
function onWithdrawal(
address token,
uint256 sendAmount,
uint256 debtReduction,
bytes calldata data
) external;
}
Loading