Skip to content

Commit

Permalink
feat: add direct RFQT fill suport to ZeroExApiAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
merklejerk committed Apr 8, 2022
1 parent 32df32d commit 3b2b061
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 163 deletions.
59 changes: 29 additions & 30 deletions contracts/mocks/external/ZeroExMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,24 @@ contract ZeroExMock {
bytes data;
}

struct BatchFillData {
address inputToken;
address outputToken;
uint256 sellAmount;
WrappedBatchCall[] calls;
}

struct WrappedBatchCall {
bytes4 selector;
uint256 sellAmount;
bytes data;
}

struct MultiHopFillData {
address[] tokens;
uint256 sellAmount;
WrappedMultiHopCall[] calls;
}

struct WrappedMultiHopCall {
bytes4 selector;
bytes data;
struct RfqOrder {
address makerToken;
address takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
address taker;
address txOrigin;
bytes32 pool;
uint64 expiry;
uint256 salt;
}

struct Signature {
uint8 signatureType;
uint8 v;
bytes32 r;
bytes32 s;
}

struct BatchSellSubcall {
Expand Down Expand Up @@ -145,24 +141,27 @@ contract ZeroExMock {
_transferTokens();
}

function batchFill(
BatchFillData memory /* fillData */,
uint256 /* minBuyAmount */
function fillRfqOrder(
RfqOrder memory /* order */,
Signature memory /* signature */,
uint128 /* takerTokenFillAmount */
)
external
payable
returns (uint256)
returns (uint128, uint128)
{
_transferTokens();
}

function multiHopFill(
MultiHopFillData memory /* fillData */,
uint256 /* minBuyAmount */
function batchFillRfqOrders(
RfqOrder[] memory /* order */,
Signature[] memory /* signature */,
uint128[] memory /* takerTokenFillAmount */,
bool /* revertIfIncomplete */
)
external
payable
returns (uint256)
returns (uint128[] memory, uint128[] memory)
{
_transferTokens();
}
Expand Down
89 changes: 52 additions & 37 deletions contracts/protocol/integration/exchange/ZeroExApiAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,24 @@ pragma experimental "ABIEncoderV2";

contract ZeroExApiAdapter {

struct BatchFillData {
address inputToken;
address outputToken;
uint256 sellAmount;
WrappedBatchCall[] calls;
}

struct WrappedBatchCall {
bytes4 selector;
uint256 sellAmount;
bytes data;
struct RfqOrder {
address makerToken;
address takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
address taker;
address txOrigin;
bytes32 pool;
uint64 expiry;
uint256 salt;
}

struct MultiHopFillData {
address[] tokens;
uint256 sellAmount;
WrappedMultiHopCall[] calls;
}

struct WrappedMultiHopCall {
bytes4 selector;
bytes data;
struct Signature {
uint8 signatureType;
uint8 v;
bytes32 r;
bytes32 s;
}

/* ============ State Variables ============ */
Expand Down Expand Up @@ -149,23 +145,31 @@ contract ZeroExApiAdapter {
require(path.length > 1, "Uniswap token path too short");
inputToken = path[0];
outputToken = path[path.length - 1];
} else if (selector == 0xafc6728e) {
// batchFill()
BatchFillData memory fillData;
(fillData, minOutputTokenAmount) =
abi.decode(_data[4:], (BatchFillData, uint256));
inputToken = fillData.inputToken;
outputToken = fillData.outputToken;
inputTokenAmount = fillData.sellAmount;
} else if (selector == 0x21c184b6) {
// multiHopFill()
MultiHopFillData memory fillData;
(fillData, minOutputTokenAmount) =
abi.decode(_data[4:], (MultiHopFillData, uint256));
require(fillData.tokens.length > 1, "Multihop token path too short");
inputToken = fillData.tokens[0];
outputToken = fillData.tokens[fillData.tokens.length - 1];
inputTokenAmount = fillData.sellAmount;
} else if (selector == 0xaa77476c) {
// fillRfqOrder()
RfqOrder memory order;
uint128 takerTokenFillAmount;
(order, , takerTokenFillAmount) =
abi.decode(_data[4:], (RfqOrder, Signature, uint128));
inputTokenAmount = uint256(takerTokenFillAmount);
inputToken = order.takerToken;
outputToken = order.makerToken;
minOutputTokenAmount = getRfqOrderMakerFillAmount(order, inputTokenAmount);
} else if (selector == 0x75103cb9) {
// batchFillRfqOrders()
RfqOrder[] memory orders;
uint128[] memory takerTokenFillAmounts;
bool revertIfIncomplete;
(orders, , takerTokenFillAmounts, revertIfIncomplete) =
abi.decode(_data[4:], (RfqOrder[], uint256, uint128[], bool));
require(orders.length > 0, "Empty RFQ orders");
require(revertIfIncomplete, "batchFillRfqOrder must be all or nothing");
inputToken = orders[0].takerToken;
outputToken = orders[0].makerToken;
for (uint256 i = 0; i < orders.length; ++i) {
inputTokenAmount += uint256(takerTokenFillAmounts[i]);
minOutputTokenAmount += getRfqOrderMakerFillAmount(orders[i], takerTokenFillAmounts[i]);
}
} else if (selector == 0x6af479b2) {
// sellTokenForTokenToUniswapV3()
bytes memory encodedPath;
Expand Down Expand Up @@ -208,6 +212,17 @@ contract ZeroExApiAdapter {
);
}

function getRfqOrderMakerFillAmount(RfqOrder memory order, uint256 takerTokenFillAmount)
private
pure
returns (uint256 makerTokenFillAmount)
{
if (order.takerAmount == 0 || order.makerAmount == 0 || takerTokenFillAmount == 0) {
return 0;
}
return uint256(order.makerAmount * takerTokenFillAmount / order.takerAmount);
}

// Decode input and output tokens from an arbitrary length encoded Uniswap V3 path
function _decodeTokensFromUniswapV3EncodedPath(bytes memory encodedPath)
private
Expand Down
4 changes: 2 additions & 2 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const config: HardhatUserConfig = {
contractSizer: {
runOnCompile: false,
},

mocha: mochaConfig,

// These are external artifacts we don't compile but would like to improve
Expand Down Expand Up @@ -106,4 +106,4 @@ function checkForkedProviderEnvironment() {
}
}

export default config;
export default config;
Loading

0 comments on commit 3b2b061

Please sign in to comment.