@@ -10,6 +10,7 @@ library EndpointStructs {
10
10
11
11
error PayloadTooLong (uint256 size );
12
12
error IncorrectPrefix (bytes4 prefix );
13
+ error UnorderedInstructions ();
13
14
14
15
/// @dev Prefix for all NativeTokenTransfer payloads
15
16
/// This is 0x99'N''T''T'
@@ -307,50 +308,47 @@ library EndpointStructs {
307
308
if (instructions.length > type (uint8 ).max) {
308
309
revert PayloadTooLong (instructions.length );
309
310
}
310
- uint8 instructionsLength = uint8 ( instructions.length ) ;
311
+ uint256 instructionsLength = instructions.length ;
311
312
312
313
bytes memory encoded;
313
- for (uint8 i = 0 ; i < instructionsLength; i++ ) {
314
+ for (uint256 i = 0 ; i < instructionsLength; i++ ) {
314
315
bytes memory innerEncoded = encodeEndpointInstruction (instructions[i]);
315
316
encoded = bytes .concat (encoded, innerEncoded);
316
317
}
317
- return abi.encodePacked (instructionsLength, encoded);
318
+ return abi.encodePacked (uint8 ( instructionsLength) , encoded);
318
319
}
319
320
320
- function parseEndpointInstructions (bytes memory encoded )
321
- public
322
- pure
323
- returns (EndpointInstruction[] memory )
324
- {
321
+ function parseEndpointInstructions (
322
+ bytes memory encoded ,
323
+ uint256 numEnabledEndpoints
324
+ ) public pure returns (EndpointInstruction[] memory ) {
325
325
uint256 offset = 0 ;
326
- uint8 instructionsLength;
326
+ uint256 instructionsLength;
327
327
(instructionsLength, offset) = encoded.asUint8Unchecked (offset);
328
- EndpointInstruction[] memory instructions = new EndpointInstruction [](instructionsLength);
329
328
330
- for (uint8 i = 0 ; i < instructionsLength; i++ ) {
329
+ // We allocate an array with the length of the number of enabled endpoints
330
+ // This gives us the flexibility to not have to pass instructions for endpoints that
331
+ // don't need them
332
+ EndpointInstruction[] memory instructions = new EndpointInstruction [](numEnabledEndpoints);
333
+
334
+ uint256 lastIndex = 0 ;
335
+ for (uint256 i = 0 ; i < instructionsLength; i++ ) {
331
336
EndpointInstruction memory instruction;
332
337
(instruction, offset) = parseEndpointInstructionUnchecked (encoded, offset);
333
- instructions[i] = instruction;
338
+
339
+ uint8 instructionIndex = instruction.index;
340
+
341
+ // The instructions passed in have to be strictly increasing in terms of endpoint index
342
+ if (i != 0 && instructionIndex <= lastIndex) {
343
+ revert UnorderedInstructions ();
344
+ }
345
+ lastIndex = instructionIndex;
346
+
347
+ instructions[instructionIndex] = instruction;
334
348
}
335
349
336
350
encoded.checkLength (offset);
337
351
338
352
return instructions;
339
353
}
340
-
341
- /*
342
- * @dev This function takes a list of EndpointInstructions and expands them to a 256-length list,
343
- * inserting each instruction into the expanded list based on `instruction.index`.
344
- */
345
- function sortEndpointInstructions (EndpointInstruction[] memory instructions )
346
- public
347
- pure
348
- returns (EndpointInstruction[] memory )
349
- {
350
- EndpointInstruction[] memory sortedInstructions = new EndpointInstruction [](type (uint8 ).max);
351
- for (uint8 i = 0 ; i < instructions.length ; i++ ) {
352
- sortedInstructions[instructions[i].index] = instructions[i];
353
- }
354
- return sortedInstructions;
355
- }
356
354
}
0 commit comments