-
Notifications
You must be signed in to change notification settings - Fork 518
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
Conversation
Codecov ReportAttention: Patch coverage is
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. |
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
|
||
// 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
- INLINE ASM
- INLINE ASM
- INLINE ASM
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
// 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
// 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
No description provided.