OrderBookV3FlashBorrower

Git Source

Inherits: IERC3156FlashBorrower, ICloneableV2, ReentrancyGuard, Initializable, DeployerDiscoverableMetaV3, ERC165

Abstract contract that liq-source specifialized contracts can inherit to provide flash loan based arbitrage against external liquidity sources to fill orderbook orders. For example consider a simple order: input = DAI output = USDT IORatio = 1.01e18 Order amount = 100e18 Assume external liq is offering 102 DAI per USDT so it exceeds the IO ratio but the order itself has no way to interact with the external contract. The OrderBookFlashBorrower can:

  • Flash loan 100 USDT from Orderbook
  • Sell the 100 USDT for 102 DAI on external liq
  • Take the order, giving 101 DAI and paying down 100 USDT loan
  • Keep 1 DAI profit As this contract is expected to be cloned using a minimal proxy there will be many copies of it in the wild. Each copy can be access gated by a Rain expression that is evaluated before anything else happens in arb. There are many reasons why this might be desirable:
  • Regulatory reasons that restrict how an arb bot operator can interact with orders and/or external liq.
  • The arb operator wants to attempt to prevent front running by other bots.
  • The arb operator may prefer a dedicated instance of the contract to make it easier to track profits, etc.

State Variables

sOrderBook

OrderBook contract to lend and arb against.

IOrderBookV3 public sOrderBook;

sI9rDispatch

The encoded dispatch that will run for access control to arb.

EncodedDispatch public sI9rDispatch;

sI9r

The interpreter that will eval access control to arb.

IInterpreterV2 public sI9r;

sI9rStore

The associated store for the interpreter.

IInterpreterStoreV1 public sI9rStore;

Functions

constructor

constructor(bytes32 metaHash, DeployerDiscoverableMetaV3ConstructionConfig memory config)
    DeployerDiscoverableMetaV3(metaHash, config);

supportsInterface

function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool);

_beforeInitialize

Hook called before initialize happens. Inheriting contracts can perform internal state maintenance before any external contract calls are made.

function _beforeInitialize(bytes memory data) internal virtual;

Parameters

NameTypeDescription
databytesArbitrary bytes the child may use to initialize.

initialize

Type hints for the input encoding for the initialize function. Reverts ALWAYS with InitializeSignatureFn as per ICloneableV2.

function initialize(OrderBookV3FlashBorrowerConfigV2 calldata) external pure returns (bytes32);

initialize

function initialize(bytes memory data) external initializer nonReentrant returns (bytes32);

onlyNotInitializing

Ensure the contract is not initializing.

modifier onlyNotInitializing();

_exchange

Hook that inheriting contracts MUST implement in order to achieve anything other than raising the ambient temperature of the room. _exchange is responsible for converting the flash loaned assets into the assets required to fill the orders. Generally this can only be achieved by interacting with an external liquidity source that is offering a better price than the orders require.

function _exchange(TakeOrdersConfigV2 memory takeOrders, bytes memory exchangeData) internal virtual;

Parameters

NameTypeDescription
takeOrdersTakeOrdersConfigV2As per arb.
exchangeDatabytesAs per arb.

onFlashLoan

Receive a flash loan.

function onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data)
    external
    onlyNotInitializing
    returns (bytes32);

Parameters

NameTypeDescription
initiatoraddressThe initiator of the loan.
<none>address
<none>uint256
<none>uint256
databytesArbitrary data structure, intended to contain user-defined parameters.

Returns

NameTypeDescription
<none>bytes32The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"

arb

Primary function to process arbitrage opportunities. Firstly the access gate is evaluated to ensure the sender is allowed to submit arbitrage. If there is no access control the sender should expect to be front run on the arb for any sufficiently profitable opportunity. This may be desirable in some cases, as the sender may simply want to be clearing the orderbook and they are expecting profit/utility from the orderbook strategies themselves somehow. Secondly the flash loan is taken and the _exchange hook is called to allow the inheriting contract to convert the flash loaned assets into the assets required to fill the orders. Finally the orders are taken and the remaining assets are sent to the sender.

function arb(TakeOrdersConfigV2 calldata takeOrders, uint256 minimumSenderOutput, bytes calldata exchangeData)
    external
    payable
    nonReentrant
    onlyNotInitializing;

Parameters

NameTypeDescription
takeOrdersTakeOrdersConfigV2As per IOrderBookV3.takeOrders.
minimumSenderOutputuint256The minimum output that must be sent to the sender by the end of the arb call. This, in combination with the orderbook's own asset handling, is expected to REPLACE the standard slippage protection that would be provided by a DEX. The sender is expected to calculate absolute values based on prevailing conditions such as gas price and the risk of holding the assets any arb profit is denominated in.
exchangeDatabytesArbitrary bytes that will be passed to _exchange after the flash loan is taken. The inheriting contract is responsible for decoding this data and defining how it controls interactions with the external liquidity. For example, GenericPoolOrderBookV3FlashBorrower uses this data as a literal encoded external call.

Events

Initialize

Emitted when the contract is initialized. Contains the OrderBookFlashBorrowerConfig struct to ensure the type appears in the ABI.

event Initialize(address sender, OrderBookV3FlashBorrowerConfigV2 config);