-
Notifications
You must be signed in to change notification settings - Fork 83
/
OrderQuoter.sol
64 lines (57 loc) · 2.79 KB
/
OrderQuoter.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {IReactorCallback} from "../interfaces/IReactorCallback.sol";
import {IReactor} from "../interfaces/IReactor.sol";
import {BaseReactor} from "../reactors/BaseReactor.sol";
import {OrderInfo, ResolvedOrder, SignedOrder} from "../base/ReactorStructs.sol";
/// @notice Quoter contract for orders
/// @dev note this is meant to be used as an off-chain lens contract to pre-validate generic orders
contract OrderQuoter is IReactorCallback {
/// @notice thrown if reactorCallback receives more than one order
error OrdersLengthIncorrect();
uint256 constant ORDER_INFO_OFFSET = 64;
/// @notice Quote the given order, returning the ResolvedOrder object which defines
/// the current input and output token amounts required to satisfy it
/// Also bubbles up any reverts that would occur during the processing of the order
/// @param order abi-encoded order, including `reactor` as the first encoded struct member
/// @param sig The order signature
/// @return result The ResolvedOrder
function quote(bytes memory order, bytes memory sig) external returns (ResolvedOrder memory result) {
try IReactor(getReactor(order)).executeWithCallback(SignedOrder(order, sig), bytes("")) {}
catch (bytes memory reason) {
result = parseRevertReason(reason);
}
}
/// @notice Return the reactor of a given order (abi.encoded bytes).
/// @param order abi-encoded order, including `reactor` as the first encoded struct member
/// @return reactor
function getReactor(bytes memory order) public pure returns (IReactor reactor) {
assembly {
let orderInfoOffsetPointer := add(order, ORDER_INFO_OFFSET)
reactor := mload(add(orderInfoOffsetPointer, mload(orderInfoOffsetPointer)))
}
}
/// @notice Return the order info of a given order (abi-encoded bytes).
/// @param order abi-encoded order, including `reactor` as the first encoded struct member
function parseRevertReason(bytes memory reason) private pure returns (ResolvedOrder memory order) {
if (reason.length < 192) {
assembly {
revert(add(32, reason), mload(reason))
}
} else {
return abi.decode(reason, (ResolvedOrder));
}
}
/// @notice Reactor callback function
/// @dev reverts with the resolved order as reason
/// @param resolvedOrders The resolved orders
function reactorCallback(ResolvedOrder[] memory resolvedOrders, bytes memory) external pure {
if (resolvedOrders.length != 1) {
revert OrdersLengthIncorrect();
}
bytes memory order = abi.encode(resolvedOrders[0]);
assembly {
revert(add(32, order), mload(order))
}
}
}