Skip to content

Commit

Permalink
Move new lib into different file
Browse files Browse the repository at this point in the history
  • Loading branch information
hensha256 committed Feb 2, 2024
1 parent 2d2760c commit cf4e70b
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 103 deletions.
96 changes: 96 additions & 0 deletions src/lib/CosignerDataLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

struct CosignerData {
// The time at which the DutchOutputs start decaying
uint256 decayStartTime;
// The time at which price becomes static
uint256 decayEndTime;
// Encoded exclusiveFiller, inputOverride, and outputOverrides, where needed
// First byte: fff0 0000 where f is a flag signalling inclusion of the 3 variables
// exclusiveFiller: The address who has exclusive rights to the order until decayStartTime
// inputOverride: The number of tokens that the swapper will provide when settling the order
// outputOverrides: The tokens that must be received to satisfy the order
bytes extraData;
}

library CosignerExtraDataLib {
bytes32 constant EXCL_FILLER_FLAG_MASK = 0x8000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant INPUT_OVERRIDE_FLAG_MASK = 0x4000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant OUTPUT_OVERRIDE_FLAG_MASK = 0x2000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant OUTPUTS_LENGTH_FLAG_MASK = 0x1F00000000000000000000000000000000000000000000000000000000000000;

// "True" first bit of byte 1 signals that there is an exclusive filler
function hasExclusiveFiller(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), EXCL_FILLER_FLAG_MASK)
}
}

// "True" second bit of byte 1 signals that there is an input override
function hasInputOverride(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), INPUT_OVERRIDE_FLAG_MASK)
}
}

// "True" third bit of byte 1 signals that there is an output override
function hasOutputOverrides(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), OUTPUT_OVERRIDE_FLAG_MASK)
}
}

function decodeExtraParameters(bytes memory extraData)
internal
pure
returns (address filler, uint256 inputOverride, uint256[] memory outputOverrides)
{
if (extraData.length == 0) return (filler, inputOverride, outputOverrides);
// The first 32 bytes are length
// The first byte (index 0) only contains flags of whether each field is included in the bytes
// So we can start from index 1 (after 32) to start decoding each field
uint256 bytesOffset = 33;

if (hasExclusiveFiller(extraData)) {
// + 20 bytes for address, - 32 bytes for the length offset
require(extraData.length >= bytesOffset - 12);
assembly {
// it loads a full 32 bytes, shift right 96 bits so only the address remains
filler := shr(96, mload(add(extraData, bytesOffset)))
}
bytesOffset += 20;
}

if (hasInputOverride(extraData)) {
// + 32 bytes for uint256, - 32 bytes for the length offset
require(extraData.length >= bytesOffset);
assembly {
inputOverride := mload(add(extraData, bytesOffset))
}
bytesOffset += 32;
}

if (hasOutputOverrides(extraData)) {
uint256 length;
assembly {
length := shr(248, and(mload(add(extraData, 32)), OUTPUTS_LENGTH_FLAG_MASK))
}

// each element of the array is 32 bytes, - 32 bytes for the length offset
require(extraData.length == bytesOffset + (length - 1) * 32);
outputOverrides = new uint256[](length);

uint256 outputOverride;
for (uint256 i = 0; i < length; i++) {
assembly {
outputOverride := mload(add(extraData, add(bytesOffset, mul(i, 32))))
}
outputOverrides[i] = outputOverride;
}
}
}
}
95 changes: 1 addition & 94 deletions src/lib/V2DutchOrderLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,7 @@ pragma solidity ^0.8.0;
import {OrderInfo} from "../base/ReactorStructs.sol";
import {DutchOutput, DutchInput, DutchOrderLib} from "./DutchOrderLib.sol";
import {OrderInfoLib} from "./OrderInfoLib.sol";

struct CosignerData {
// The time at which the DutchOutputs start decaying
uint256 decayStartTime;
// The time at which price becomes static
uint256 decayEndTime;
// Encoded exclusiveFiller, inputOverride, and outputOverrides, where needed
// First byte: fff0 0000 where f is a flag signalling inclusion of the 3 variables
// exclusiveFiller: The address who has exclusive rights to the order until decayStartTime
// inputOverride: The number of tokens that the swapper will provide when settling the order
// outputOverrides: The tokens that must be received to satisfy the order
bytes extraData;
}
import {CosignerData} from "./CosignerDataLib.sol";

struct V2DutchOrder {
// generic order information
Expand Down Expand Up @@ -80,84 +68,3 @@ library V2DutchOrderLib {
);
}
}

library CosignerExtraDataLib {
bytes32 constant EXCL_FILLER_FLAG_MASK = 0x8000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant INPUT_OVERRIDE_FLAG_MASK = 0x4000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant OUTPUT_OVERRIDE_FLAG_MASK = 0x2000000000000000000000000000000000000000000000000000000000000000;
bytes32 constant OUTPUTS_LENGTH_FLAG_MASK = 0x1F00000000000000000000000000000000000000000000000000000000000000;

// "True" first bit of byte 1 signals that there is an exclusive filler
function hasExclusiveFiller(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), EXCL_FILLER_FLAG_MASK)
}
}

// "True" second bit of byte 1 signals that there is an input override
function hasInputOverride(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), INPUT_OVERRIDE_FLAG_MASK)
}
}

// "True" third bit of byte 1 signals that there is an output override
function hasOutputOverrides(bytes memory extraData) internal pure returns (bool flag) {
if (extraData.length == 0) return false;
assembly {
flag := and(mload(add(extraData, 32)), OUTPUT_OVERRIDE_FLAG_MASK)
}
}

function decodeExtraParameters(bytes memory extraData)
internal
pure
returns (address filler, uint256 inputOverride, uint256[] memory outputOverrides)
{
if (extraData.length == 0) return (filler, inputOverride, outputOverrides);
// The first 32 bytes are length
// The first byte (index 0) only contains flags of whether each field is included in the bytes
// So we can start from index 1 (after 32) to start decoding each field
uint256 bytesOffset = 33;

if (hasExclusiveFiller(extraData)) {
// + 20 bytes for address, - 32 bytes for the length offset
require(extraData.length >= bytesOffset - 12);
assembly {
// it loads a full 32 bytes, shift right 96 bits so only the address remains
filler := shr(96, mload(add(extraData, bytesOffset)))
}
bytesOffset += 20;
}

if (hasInputOverride(extraData)) {
// + 32 bytes for uint256, - 32 bytes for the length offset
require(extraData.length >= bytesOffset);
assembly {
inputOverride := mload(add(extraData, bytesOffset))
}
bytesOffset += 32;
}

if (hasOutputOverrides(extraData)) {
uint256 length;
assembly {
length := shr(248, and(mload(add(extraData, 32)), OUTPUTS_LENGTH_FLAG_MASK))
}

// each element of the array is 32 bytes, - 32 bytes for the length offset
require(extraData.length == bytesOffset + (length - 1) * 32);
outputOverrides = new uint256[](length);

uint256 outputOverride;
for (uint256 i = 0; i < length; i++) {
assembly {
outputOverride := mload(add(extraData, add(bytesOffset, mul(i, 32))))
}
outputOverrides[i] = outputOverride;
}
}
}
}
10 changes: 2 additions & 8 deletions src/reactors/V2DutchOrderReactor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,8 @@ import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {Permit2Lib} from "../lib/Permit2Lib.sol";
import {ExclusivityLib} from "../lib/ExclusivityLib.sol";
import {DutchDecayLib} from "../lib/DutchDecayLib.sol";
import {
CosignerExtraDataLib,
V2DutchOrderLib,
V2DutchOrder,
CosignerData,
DutchOutput,
DutchInput
} from "../lib/V2DutchOrderLib.sol";
import {CosignerExtraDataLib} from "../lib/CosignerDataLib.sol";
import {V2DutchOrderLib, V2DutchOrder, CosignerData, DutchOutput, DutchInput} from "../lib/V2DutchOrderLib.sol";
import {SignedOrder, ResolvedOrder} from "../base/ReactorStructs.sol";

/// @notice Reactor for v2 dutch orders
Expand Down
2 changes: 1 addition & 1 deletion test/reactors/V2DutchOrderReactor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {DeployPermit2} from "../util/DeployPermit2.sol";
import {
V2DutchOrder,
V2DutchOrderLib,
CosignerExtraDataLib,
CosignerData,
V2DutchOrderReactor,
ResolvedOrder,
DutchOutput,
DutchInput,
BaseReactor
} from "../../src/reactors/V2DutchOrderReactor.sol";
import {CosignerExtraDataLib} from "../../src/lib/CosignerDataLib.sol";
import {OrderInfo, InputToken, SignedOrder, OutputToken} from "../../src/base/ReactorStructs.sol";
import {ExclusivityLib} from "../../src/lib/ExclusivityLib.sol";
import {DutchDecayLib} from "../../src/lib/DutchDecayLib.sol";
Expand Down

0 comments on commit cf4e70b

Please sign in to comment.