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

POC: Seaport bulk signatures support in Account.isValidSignature #618

Closed
wants to merge 15 commits into from

Conversation

nkrishang
Copy link
Contributor

No description provided.

Copy link

codecov bot commented Feb 21, 2024

Codecov Report

Attention: Patch coverage is 58.10811% with 31 lines in your changes are missing coverage. Please review.

Project coverage is 64.53%. Comparing base (effd208) to head (fc55bb4).

Files Patch % Lines
contracts/extension/SeaportOrderEIP1271.sol 54.54% 15 Missing ⚠️
contracts/extension/SeaportOrderParser.sol 64.51% 11 Missing ⚠️
...racts/prebuilts/account/utils/AccountExtension.sol 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #618      +/-   ##
==========================================
- Coverage   64.55%   64.53%   -0.03%     
==========================================
  Files         216      218       +2     
  Lines        6701     6767      +66     
==========================================
+ Hits         4326     4367      +41     
- Misses       2375     2400      +25     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@nkrishang nkrishang changed the title POC: Seaport bulk signatures not supported by Account.isValidSignature POC: Seaport bulk signatures support in Account.isValidSignature Feb 22, 2024
contracts/extension/SeaportOrderParser.sol Dismissed Show dismissed Hide dismissed
contracts/extension/SeaportOrderParser.sol Dismissed Show dismissed Hide dismissed
contracts/extension/SeaportOrderParser.sol Dismissed Show dismissed Hide dismissed
contracts/extension/SeaportOrderParser.sol Dismissed Show dismissed Hide dismissed
contracts/extension/SeaportOrderParser.sol Dismissed Show dismissed Hide dismissed
Comment on lines +357 to +524
BulkOrder_Typehash_Height_Ten
)

// Exit the function once typehash has been located.
leave
}

// Handle height eleven and twelve via branchless logic.
typeHash := ternary(
eq(treeHeight, 11),
BulkOrder_Typehash_Height_Eleven,
BulkOrder_Typehash_Height_Twelve
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height thirteen and fourteen.
if lt(treeHeight, 15) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 13),
BulkOrder_Typehash_Height_Thirteen,
BulkOrder_Typehash_Height_Fourteen
)

// Exit the function once typehash has been located.
leave
}
// Handle height fifteen and sixteen via branchless logic.
typeHash := ternary(
eq(treeHeight, 15),
BulkOrder_Typehash_Height_Fifteen,
BulkOrder_Typehash_Height_Sixteen
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height seventeen through twenty.
if lt(treeHeight, 21) {
// Handle tree height seventeen and eighteen.
if lt(treeHeight, 19) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 17),
BulkOrder_Typehash_Height_Seventeen,
BulkOrder_Typehash_Height_Eighteen
)

// Exit the function once typehash has been located.
leave
}

// Handle height nineteen and twenty via branchless logic.
typeHash := ternary(
eq(treeHeight, 19),
BulkOrder_Typehash_Height_Nineteen,
BulkOrder_Typehash_Height_Twenty
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height twenty-one and twenty-two.
if lt(treeHeight, 23) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 21),
BulkOrder_Typehash_Height_TwentyOne,
BulkOrder_Typehash_Height_TwentyTwo
)

// Exit the function once typehash has been located.
leave
}

// Handle height twenty-three & twenty-four w/ branchless logic.
typeHash := ternary(
eq(treeHeight, 23),
BulkOrder_Typehash_Height_TwentyThree,
BulkOrder_Typehash_Height_TwentyFour
)

// Exit the function once typehash has been located.
leave
}

// Implement ternary conditional using branchless logic.
function ternary(cond, ifTrue, ifFalse) -> c {
c := xor(ifFalse, mul(cond, xor(ifFalse, ifTrue)))
}

// Look up the typehash using the supplied tree height.
_typeHash := lookupTypeHash(_treeHeight)
}
}

Check warning

Code scanning / Slither

Assembly usage Warning

Comment on lines +38 to +204

// Read consideration item typehash from runtime code & place on stack.
typeHash = _CONSIDERATION_ITEM_TYPEHASH;

// Utilize assembly so that memory regions can be reused across hashes.
assembly {
// Retrieve the free memory pointer and place on the stack.
let hashArrPtr := mload(FreeMemoryPointerSlot)

// Get the pointer to the consideration array.
let considerationArrPtr := add(
mload(add(orderParameters, OrderParameters_consideration_head_offset)),
OneWord
)

// Iterate over the consideration items (not including tips).
for {
let i := 0
} lt(i, originalConsiderationLength) {
i := add(i, 1)
} {
// Read the pointer to the consideration data and subtract one
// word to get typeHash pointer.
let ptr := sub(mload(considerationArrPtr), OneWord)

// Read the current value before the consideration data.
let value := mload(ptr)

// Write the type hash to the previous word.
mstore(ptr, typeHash)

// Take the EIP712 hash and store it in the hash array.
mstore(hashArrPtr, keccak256(ptr, EIP712_ConsiderationItem_size))

// Restore the previous word.
mstore(ptr, value)

// Increment the array pointers by one word.
considerationArrPtr := add(considerationArrPtr, OneWord)
hashArrPtr := add(hashArrPtr, OneWord)
}

// Derive the consideration hash using the hashes of each item.
considerationHash := keccak256(mload(FreeMemoryPointerSlot), shl(OneWordShift, originalConsiderationLength))
}

// Read order item EIP-712 typehash from runtime code & place on stack.
typeHash = _ORDER_TYPEHASH;

// Utilize assembly to access derived hashes & other arguments directly.
assembly {
// Retrieve pointer to the region located just behind parameters.
let typeHashPtr := sub(orderParameters, OneWord)

// Store the value at that pointer location to restore later.
let previousValue := mload(typeHashPtr)

// Store the order item EIP-712 typehash at the typehash location.
mstore(typeHashPtr, typeHash)

// Retrieve the pointer for the offer array head.
let offerHeadPtr := add(orderParameters, OrderParameters_offer_head_offset)

// Retrieve the data pointer referenced by the offer head.
let offerDataPtr := mload(offerHeadPtr)

// Store the offer hash at the retrieved memory location.
mstore(offerHeadPtr, offerHash)

// Retrieve the pointer for the consideration array head.
let considerationHeadPtr := add(orderParameters, OrderParameters_consideration_head_offset)

// Retrieve the data pointer referenced by the consideration head.
let considerationDataPtr := mload(considerationHeadPtr)

// Store the consideration hash at the retrieved memory location.
mstore(considerationHeadPtr, considerationHash)

// Retrieve the pointer for the counter.
let counterPtr := add(orderParameters, OrderParameters_counter_offset)

// Store the counter at the retrieved memory location.
mstore(counterPtr, counter)

// Derive the order hash using the full range of order parameters.
orderHash := keccak256(typeHashPtr, EIP712_Order_size)

// Restore the value previously held at typehash pointer location.
mstore(typeHashPtr, previousValue)

// Restore offer data pointer at the offer head pointer location.
mstore(offerHeadPtr, offerDataPtr)

// Restore consideration data pointer at the consideration head ptr.
mstore(considerationHeadPtr, considerationDataPtr)

// Restore consideration item length at the counter pointer.
mstore(counterPtr, originalConsiderationLength)
}
}

Check warning

Code scanning / Slither

Assembly usage Warning

Comment on lines +292 to +355
function _computeBulkOrderProof(
bytes memory proofAndSignature,
bytes32 leaf
) internal pure returns (bytes32 bulkOrderHash) {
// Declare arguments for the root hash and the height of the proof.
bytes32 root;
uint256 height;

// Utilize assembly to efficiently derive the root hash using the proof.
assembly {
// Retrieve the length of the proof, key, and signature combined.
let fullLength := mload(proofAndSignature)

// If proofAndSignature has odd length, it is a compact signature
// with 64 bytes.
let signatureLength := sub(ECDSA_MaxLength, and(fullLength, 1))

// Derive height (or depth of tree) with signature and proof length.
height := shr(OneWordShift, sub(fullLength, signatureLength))

// Update the length in memory to only include the signature.
mstore(proofAndSignature, signatureLength)

// Derive the pointer for the key using the signature length.
let keyPtr := add(proofAndSignature, add(OneWord, signatureLength))

// Retrieve the three-byte key using the derived pointer.
let key := shr(BulkOrderProof_keyShift, mload(keyPtr))

/// Retrieve pointer to first proof element by applying a constant
// for the key size to the derived key pointer.
let proof := add(keyPtr, BulkOrderProof_keySize)

// Compute level 1.
let scratchPtr1 := shl(OneWordShift, and(key, 1))
mstore(scratchPtr1, leaf)
mstore(xor(scratchPtr1, OneWord), mload(proof))

// Compute remaining proofs.
for {
let i := 1
} lt(i, height) {
i := add(i, 1)
} {
proof := add(proof, OneWord)
let scratchPtr := shl(OneWordShift, and(shr(i, key), 1))
mstore(scratchPtr, keccak256(0, TwoWords))
mstore(xor(scratchPtr, OneWord), mload(proof))
}

// Compute root hash.
root := keccak256(0, TwoWords)
}

// Retrieve appropriate typehash constant based on height.
bytes32 rootTypeHash = _lookupBulkOrderTypehash(height);

// Use the typehash and the root hash to derive final bulk order hash.
assembly {
mstore(0, rootTypeHash)
mstore(OneWord, root)
bulkOrderHash := keccak256(0, TwoWords)
}
}

Check warning

Code scanning / Slither

Assembly usage Warning

Comment on lines +362 to +514
// Handle tree height nine through sixteen.
if lt(treeHeight, 17) {
// Handle tree height nine through twelve.
if lt(treeHeight, 13) {
// Handle tree height nine and ten.
if lt(treeHeight, 11) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 9),
BulkOrder_Typehash_Height_Nine,
BulkOrder_Typehash_Height_Ten
)

// Exit the function once typehash has been located.
leave
}

// Handle height eleven and twelve via branchless logic.
typeHash := ternary(
eq(treeHeight, 11),
BulkOrder_Typehash_Height_Eleven,
BulkOrder_Typehash_Height_Twelve
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height thirteen and fourteen.
if lt(treeHeight, 15) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 13),
BulkOrder_Typehash_Height_Thirteen,
BulkOrder_Typehash_Height_Fourteen
)

// Exit the function once typehash has been located.
leave
}
// Handle height fifteen and sixteen via branchless logic.
typeHash := ternary(
eq(treeHeight, 15),
BulkOrder_Typehash_Height_Fifteen,
BulkOrder_Typehash_Height_Sixteen
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height seventeen through twenty.
if lt(treeHeight, 21) {
// Handle tree height seventeen and eighteen.
if lt(treeHeight, 19) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 17),
BulkOrder_Typehash_Height_Seventeen,
BulkOrder_Typehash_Height_Eighteen
)

// Exit the function once typehash has been located.
leave
}

// Handle height nineteen and twenty via branchless logic.
typeHash := ternary(
eq(treeHeight, 19),
BulkOrder_Typehash_Height_Nineteen,
BulkOrder_Typehash_Height_Twenty
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height twenty-one and twenty-two.
if lt(treeHeight, 23) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 21),
BulkOrder_Typehash_Height_TwentyOne,
BulkOrder_Typehash_Height_TwentyTwo
)

// Exit the function once typehash has been located.
leave
}

// Handle height twenty-three & twenty-four w/ branchless logic.
typeHash := ternary(
eq(treeHeight, 23),
BulkOrder_Typehash_Height_TwentyThree,
BulkOrder_Typehash_Height_TwentyFour
)

// Exit the function once typehash has been located.
leave
}

Check warning

Code scanning / Slither

Cyclomatic complexity Warning

Comment on lines +362 to +514
// Handle tree height nine through sixteen.
if lt(treeHeight, 17) {
// Handle tree height nine through twelve.
if lt(treeHeight, 13) {
// Handle tree height nine and ten.
if lt(treeHeight, 11) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 9),
BulkOrder_Typehash_Height_Nine,
BulkOrder_Typehash_Height_Ten
)

// Exit the function once typehash has been located.
leave
}

// Handle height eleven and twelve via branchless logic.
typeHash := ternary(
eq(treeHeight, 11),
BulkOrder_Typehash_Height_Eleven,
BulkOrder_Typehash_Height_Twelve
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height thirteen and fourteen.
if lt(treeHeight, 15) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 13),
BulkOrder_Typehash_Height_Thirteen,
BulkOrder_Typehash_Height_Fourteen
)

// Exit the function once typehash has been located.
leave
}
// Handle height fifteen and sixteen via branchless logic.
typeHash := ternary(
eq(treeHeight, 15),
BulkOrder_Typehash_Height_Fifteen,
BulkOrder_Typehash_Height_Sixteen
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height seventeen through twenty.
if lt(treeHeight, 21) {
// Handle tree height seventeen and eighteen.
if lt(treeHeight, 19) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 17),
BulkOrder_Typehash_Height_Seventeen,
BulkOrder_Typehash_Height_Eighteen
)

// Exit the function once typehash has been located.
leave
}

// Handle height nineteen and twenty via branchless logic.
typeHash := ternary(
eq(treeHeight, 19),
BulkOrder_Typehash_Height_Nineteen,
BulkOrder_Typehash_Height_Twenty
)

// Exit the function once typehash has been located.
leave
}

// Handle tree height twenty-one and twenty-two.
if lt(treeHeight, 23) {
// Utilize branchless logic to determine typehash.
typeHash := ternary(
eq(treeHeight, 21),
BulkOrder_Typehash_Height_TwentyOne,
BulkOrder_Typehash_Height_TwentyTwo
)

// Exit the function once typehash has been located.
leave
}

// Handle height twenty-three & twenty-four w/ branchless logic.
typeHash := ternary(
eq(treeHeight, 23),
BulkOrder_Typehash_Height_TwentyThree,
BulkOrder_Typehash_Height_TwentyFour
)

// Exit the function once typehash has been located.
leave
}

Check warning

Code scanning / Slither

Cyclomatic complexity Warning

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant