Skip to content

Commit f4b976e

Browse files
feat: add direct RFQT fill suport to ZeroExApiAdapter [SIM-230] (#241)
1 parent 361728a commit f4b976e

File tree

4 files changed

+384
-161
lines changed

4 files changed

+384
-161
lines changed

contracts/mocks/external/ZeroExMock.sol

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,24 @@ contract ZeroExMock {
2929
bytes data;
3030
}
3131

32-
struct BatchFillData {
33-
address inputToken;
34-
address outputToken;
35-
uint256 sellAmount;
36-
WrappedBatchCall[] calls;
37-
}
38-
39-
struct WrappedBatchCall {
40-
bytes4 selector;
41-
uint256 sellAmount;
42-
bytes data;
43-
}
44-
45-
struct MultiHopFillData {
46-
address[] tokens;
47-
uint256 sellAmount;
48-
WrappedMultiHopCall[] calls;
49-
}
50-
51-
struct WrappedMultiHopCall {
52-
bytes4 selector;
53-
bytes data;
32+
struct RfqOrder {
33+
address makerToken;
34+
address takerToken;
35+
uint128 makerAmount;
36+
uint128 takerAmount;
37+
address maker;
38+
address taker;
39+
address txOrigin;
40+
bytes32 pool;
41+
uint64 expiry;
42+
uint256 salt;
43+
}
44+
45+
struct Signature {
46+
uint8 signatureType;
47+
uint8 v;
48+
bytes32 r;
49+
bytes32 s;
5450
}
5551

5652
struct BatchSellSubcall {
@@ -145,24 +141,27 @@ contract ZeroExMock {
145141
_transferTokens();
146142
}
147143

148-
function batchFill(
149-
BatchFillData memory /* fillData */,
150-
uint256 /* minBuyAmount */
144+
function fillRfqOrder(
145+
RfqOrder memory /* order */,
146+
Signature memory /* signature */,
147+
uint128 /* takerTokenFillAmount */
151148
)
152149
external
153150
payable
154-
returns (uint256)
151+
returns (uint128, uint128)
155152
{
156153
_transferTokens();
157154
}
158155

159-
function multiHopFill(
160-
MultiHopFillData memory /* fillData */,
161-
uint256 /* minBuyAmount */
156+
function batchFillRfqOrders(
157+
RfqOrder[] memory /* order */,
158+
Signature[] memory /* signature */,
159+
uint128[] memory /* takerTokenFillAmount */,
160+
bool /* revertIfIncomplete */
162161
)
163162
external
164163
payable
165-
returns (uint256)
164+
returns (uint128[] memory, uint128[] memory)
166165
{
167166
_transferTokens();
168167
}

contracts/protocol/integration/exchange/ZeroExApiAdapter.sol

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,24 @@ pragma experimental "ABIEncoderV2";
2828

2929
contract ZeroExApiAdapter {
3030

31-
struct BatchFillData {
32-
address inputToken;
33-
address outputToken;
34-
uint256 sellAmount;
35-
WrappedBatchCall[] calls;
36-
}
37-
38-
struct WrappedBatchCall {
39-
bytes4 selector;
40-
uint256 sellAmount;
41-
bytes data;
31+
struct RfqOrder {
32+
address makerToken;
33+
address takerToken;
34+
uint128 makerAmount;
35+
uint128 takerAmount;
36+
address maker;
37+
address taker;
38+
address txOrigin;
39+
bytes32 pool;
40+
uint64 expiry;
41+
uint256 salt;
4242
}
4343

44-
struct MultiHopFillData {
45-
address[] tokens;
46-
uint256 sellAmount;
47-
WrappedMultiHopCall[] calls;
48-
}
49-
50-
struct WrappedMultiHopCall {
51-
bytes4 selector;
52-
bytes data;
44+
struct Signature {
45+
uint8 signatureType;
46+
uint8 v;
47+
bytes32 r;
48+
bytes32 s;
5349
}
5450

5551
/* ============ State Variables ============ */
@@ -149,23 +145,31 @@ contract ZeroExApiAdapter {
149145
require(path.length > 1, "Uniswap token path too short");
150146
inputToken = path[0];
151147
outputToken = path[path.length - 1];
152-
} else if (selector == 0xafc6728e) {
153-
// batchFill()
154-
BatchFillData memory fillData;
155-
(fillData, minOutputTokenAmount) =
156-
abi.decode(_data[4:], (BatchFillData, uint256));
157-
inputToken = fillData.inputToken;
158-
outputToken = fillData.outputToken;
159-
inputTokenAmount = fillData.sellAmount;
160-
} else if (selector == 0x21c184b6) {
161-
// multiHopFill()
162-
MultiHopFillData memory fillData;
163-
(fillData, minOutputTokenAmount) =
164-
abi.decode(_data[4:], (MultiHopFillData, uint256));
165-
require(fillData.tokens.length > 1, "Multihop token path too short");
166-
inputToken = fillData.tokens[0];
167-
outputToken = fillData.tokens[fillData.tokens.length - 1];
168-
inputTokenAmount = fillData.sellAmount;
148+
} else if (selector == 0xaa77476c) {
149+
// fillRfqOrder()
150+
RfqOrder memory order;
151+
uint128 takerTokenFillAmount;
152+
(order, , takerTokenFillAmount) =
153+
abi.decode(_data[4:], (RfqOrder, Signature, uint128));
154+
inputTokenAmount = uint256(takerTokenFillAmount);
155+
inputToken = order.takerToken;
156+
outputToken = order.makerToken;
157+
minOutputTokenAmount = getRfqOrderMakerFillAmount(order, inputTokenAmount);
158+
} else if (selector == 0x75103cb9) {
159+
// batchFillRfqOrders()
160+
RfqOrder[] memory orders;
161+
uint128[] memory takerTokenFillAmounts;
162+
bool revertIfIncomplete;
163+
(orders, , takerTokenFillAmounts, revertIfIncomplete) =
164+
abi.decode(_data[4:], (RfqOrder[], uint256, uint128[], bool));
165+
require(orders.length > 0, "Empty RFQ orders");
166+
require(revertIfIncomplete, "batchFillRfqOrder must be all or nothing");
167+
inputToken = orders[0].takerToken;
168+
outputToken = orders[0].makerToken;
169+
for (uint256 i = 0; i < orders.length; ++i) {
170+
inputTokenAmount += uint256(takerTokenFillAmounts[i]);
171+
minOutputTokenAmount += getRfqOrderMakerFillAmount(orders[i], takerTokenFillAmounts[i]);
172+
}
169173
} else if (selector == 0x6af479b2) {
170174
// sellTokenForTokenToUniswapV3()
171175
bytes memory encodedPath;
@@ -208,6 +212,17 @@ contract ZeroExApiAdapter {
208212
);
209213
}
210214

215+
function getRfqOrderMakerFillAmount(RfqOrder memory order, uint256 takerTokenFillAmount)
216+
private
217+
pure
218+
returns (uint256 makerTokenFillAmount)
219+
{
220+
if (order.takerAmount == 0 || order.makerAmount == 0 || takerTokenFillAmount == 0) {
221+
return 0;
222+
}
223+
return uint256(order.makerAmount * takerTokenFillAmount / order.takerAmount);
224+
}
225+
211226
// Decode input and output tokens from an arbitrary length encoded Uniswap V3 path
212227
function _decodeTokensFromUniswapV3EncodedPath(bytes memory encodedPath)
213228
private

hardhat.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,4 @@ function checkForkedProviderEnvironment() {
108108
}
109109
}
110110

111-
export default config;
111+
export default config;

0 commit comments

Comments
 (0)