OrderBookV3FlashBorrower
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
| Name | Type | Description |
|---|---|---|
data | bytes | Arbitrary 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
| Name | Type | Description |
|---|---|---|
takeOrders | TakeOrdersConfigV2 | As per arb. |
exchangeData | bytes | As per arb. |
onFlashLoan
Receive a flash loan.
function onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data)
external
onlyNotInitializing
returns (bytes32);
Parameters
| Name | Type | Description |
|---|---|---|
initiator | address | The initiator of the loan. |
<none> | address | |
<none> | uint256 | |
<none> | uint256 | |
data | bytes | Arbitrary data structure, intended to contain user-defined parameters. |
Returns
| Name | Type | Description |
|---|---|---|
<none> | bytes32 | The 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
| Name | Type | Description |
|---|---|---|
takeOrders | TakeOrdersConfigV2 | As per IOrderBookV3.takeOrders. |
minimumSenderOutput | uint256 | The 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. |
exchangeData | bytes | Arbitrary 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);