Omniscia Native Audit

Order Code Style Findings

Order Code Style Findings

ORE-01C: Improper Specialized Encoding Mechanism

TypeSeverityLocation
Gas OptimizationOrder.sol:L12-L23, L25, L26, L27, L40-L46

Description:

The encoding mechanism employed by Order is inefficient. As it correctly states in the commented out code, the size of an address type is 20 whilst it is used as 32 in the encoding mechanism. This is due to the code not performing an actual tight encoding mechanism.

Example:

contracts/libraries/Order.sol
12struct Order {
13 uint256 id;
14 address signer;
15 address buyer;
16 address seller;
17 address buyerToken;
18 address sellerToken;
19 uint256 buyerTokenAmount;
20 uint256 sellerTokenAmount;
21 uint256 deadlineTimestamp;
22 address txOrigin;
23}
24
25uint256 private constant ADDR_SIZE = 32; //20;
26uint256 private constant UINT256_SIZE = 32; //32;

Recommendation:

Given that each byte is stored in sequence, a special decoding mechanism can be employed similarly to Uniswap V3 whereby the arguments are decoded one-by-one. This will significantly optimize the Native exchange when dealing with multiple orders as the memory needs of the contract will be greatly minimized.

Alleviation:

The code now properly decodes the Order struct manually byte-by-byte, significantly optimizing the data needs of an Order struct.

ORE-02C: Inexistent Error Messages

TypeSeverityLocation
Code StyleOrder.sol:L43, L53

Description:

The linked require checks have no error messages explicitly defined.

Example:

contracts/libraries/Order.sol
43require(orders.length != 0 && orders.length % HOP_SIZE == 0);

Recommendation:

We advise each to be set so to increase the legibility of the codebase and aid in validating the require checks' conditions.

Alleviation:

An error message has been properly introduced for all referenced require statements.

ORE-03C: Potential Enhancement of Functionality

TypeSeverityLocation
Gas OptimizationOrder.sol:L40-L46, L52-L55

Description:

The decodeFirstOrder, getFirstOrder, and skipOrder functions are separate but are used together in the Router implementation.

Example:

contracts/libraries/Order.sol
40function decodeFirstOrder(
41 bytes memory orders
42) internal pure returns (Order memory order, bytes memory signature) {
43 require(orders.length != 0 && orders.length % HOP_SIZE == 0);
44 order = abi.decode(orders.slice(0, ORDER_SIZE), (Order));
45 signature = orders.slice(ORDER_SIZE, SIG_SIZE);
46}
47
48function getFirstOrder(bytes memory orders) internal pure returns (bytes memory) {
49 return orders.slice(0, HOP_SIZE);
50}
51
52function skipOrder(bytes memory orders) internal pure returns (bytes memory) {
53 require(orders.length != 0 && orders.length % HOP_SIZE == 0);
54 return orders.slice(HOP_SIZE, orders.length - HOP_SIZE);
55}

Recommendation:

We advise their functionality to be merged into a single function that decodes the first order, returns it, and additionally returns the remaining orders sliced via skipOrder (i.e. decodeAndSkipFirstOrder).

Alleviation:

The Native team evaluated this exhibit but opted not to apply a remediation for it as they consider it inconsequential.