Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFQ interactions #199

Merged
merged 7 commits into from
Feb 7, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add interaction to rfq
  • Loading branch information
SevenSwen committed Feb 1, 2023
commit 38b7e3ba4b4a1b2ec73a79508b3b7d4bcf05205c
31 changes: 27 additions & 4 deletions contracts/OrderRFQMixin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol";
import "@1inch/solidity-utils/contracts/OnlyWethReceiver.sol";

import "./helpers/AmountCalculator.sol";
import "./interfaces/IInteractionNotificationReceiver.sol";
import "./libraries/Errors.sol";
import "./OrderRFQLib.sol";

Expand All @@ -17,6 +18,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
using SafeERC20 for IERC20;
using OrderRFQLib for OrderRFQLib.OrderRFQ;
using CalldataLib for CalldataLib.Address;
using CalldataLib for bytes;

error RFQZeroTargetIsForbidden();
error RFQPrivateOrder();
Expand Down Expand Up @@ -83,6 +85,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
* @notice Fills order's quote, fully or partially (whichever is possible)
* @param order Order quote to fill
* @param signature Signature to confirm quote ownership
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param flagsAndAmount Fill configuration flags with amount packed in one slot
* @return filledMakingAmount Actual amount transferred from maker to taker
* @return filledTakingAmount Actual amount transferred from taker to maker
Expand All @@ -91,16 +94,18 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
function fillOrderRFQ(
OrderRFQLib.OrderRFQ calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 flagsAndAmount
) external payable returns(uint256 /* filledMakingAmount */, uint256 /* filledTakingAmount */, bytes32 /* orderHash */) {
return fillOrderRFQTo(order, signature, flagsAndAmount, msg.sender);
return fillOrderRFQTo(order, signature, interaction, flagsAndAmount, msg.sender);
}

/**
* @notice Fills order's quote, fully or partially, with compact signature
* @param order Order quote to fill
* @param r R component of signature
* @param vs VS component of signature
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param flagsAndAmount Fill configuration flags with amount packed in one slot
* - Bits 0-251 contain the amount to fill
* - Bit 252 is used to indicate whether weth should be unwrapped to eth
Expand All @@ -115,6 +120,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
OrderRFQLib.OrderRFQ calldata order,
bytes32 r,
bytes32 vs,
bytes calldata interaction,
uint256 flagsAndAmount
) external payable returns(uint256 filledMakingAmount, uint256 filledTakingAmount, bytes32 orderHash) {
orderHash = order.hash(_domainSeparatorV4());
Expand All @@ -128,7 +134,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
if(!ECDSA.recoverOrIsValidSignature(order.maker.get(), orderHash, r, vs)) revert RFQBadSignature();
}

(filledMakingAmount, filledTakingAmount) = _fillOrderRFQTo(order, flagsAndAmount, msg.sender);
(filledMakingAmount, filledTakingAmount) = _fillOrderRFQTo(order, interaction, flagsAndAmount, msg.sender);
emit OrderFilledRFQ(orderHash, filledMakingAmount);
}

Expand All @@ -138,6 +144,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
* Also allows to specify funds destination instead of `msg.sender`
* @param order Order quote to fill
* @param signature Signature to confirm quote ownership
* @param interaction A call data for InteractiveNotificationReceiver. Taker may execute interaction after getting maker assets and before sending taker assets.
* @param flagsAndAmount Fill configuration flags with amount packed in one slot
* @param target Address that will receive swap funds
* @param permit Should contain abi-encoded calldata for `IERC20Permit.permit` call
Expand All @@ -149,12 +156,13 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
function fillOrderRFQToWithPermit(
OrderRFQLib.OrderRFQ calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 flagsAndAmount,
address target,
bytes calldata permit
) external returns(uint256 /* filledMakingAmount */, uint256 /* filledTakingAmount */, bytes32 /* orderHash */) {
IERC20(order.takerAsset.get()).safePermit(permit);
return fillOrderRFQTo(order, signature, flagsAndAmount, target);
return fillOrderRFQTo(order, signature, interaction, flagsAndAmount, target);
}

/**
Expand All @@ -170,6 +178,7 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
function fillOrderRFQTo(
OrderRFQLib.OrderRFQ calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 flagsAndAmount,
address target
) public payable returns(uint256 filledMakingAmount, uint256 filledTakingAmount, bytes32 orderHash) {
Expand All @@ -180,12 +189,13 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
} else {
if(!ECDSA.recoverOrIsValidSignature(order.maker.get(), orderHash, signature)) revert RFQBadSignature();
}
(filledMakingAmount, filledTakingAmount) = _fillOrderRFQTo(order, flagsAndAmount, target);
(filledMakingAmount, filledTakingAmount) = _fillOrderRFQTo(order, interaction, flagsAndAmount, target);
emit OrderFilledRFQ(orderHash, filledMakingAmount);
}

function _fillOrderRFQTo(
OrderRFQLib.OrderRFQ calldata order,
bytes calldata interaction,
uint256 flagsAndAmount,
address target
) private returns(uint256 makingAmount, uint256 takingAmount) {
Expand Down Expand Up @@ -239,6 +249,19 @@ abstract contract OrderRFQMixin is EIP712, OnlyWethReceiver {
IERC20(order.makerAsset.get()).safeTransferFrom(maker, target, makingAmount);
}

if (interaction.length >= 20) {
// proceed only if interaction length is enough to store address
(address interactionTarget, bytes calldata interactionData) = interaction.decodeTargetAndCalldata();
uint256 offeredTakingAmount = IInteractionNotificationReceiver(interactionTarget).fillOrderInteraction(
msg.sender, makingAmount, takingAmount, interactionData
);

if (offeredTakingAmount > takingAmount)
{
takingAmount = offeredTakingAmount;
}
}

// Taker => Maker
if (order.takerAsset.get() == address(_WETH) && msg.value > 0) {
if (msg.value != takingAmount) revert Errors.InvalidMsgValue();
Expand Down