From c71974257bb9df949eb7b9ad9a8a756950d018dc Mon Sep 17 00:00:00 2001 From: "pwnh4 (@loicttn)" Date: Tue, 10 Dec 2024 14:21:07 +0100 Subject: [PATCH] fix(ocv2): add missing parsers --- src/contracts.c | 6 + src/handle_init_contract.c | 6 + src/kiln_plugin.h | 73 +++++ .../handle_provide_parameter.c | 6 +- src/provide_parameter/ocv2.c | 249 ++++++++++++++++++ src/provide_parameter/provide_parameter.h | 4 + tests/src/multiClaim.v2.test.js | 5 +- 7 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 src/provide_parameter/ocv2.c diff --git a/src/contracts.c b/src/contracts.c index 296ffee..34c063f 100644 --- a/src/contracts.c +++ b/src/contracts.c @@ -25,6 +25,12 @@ static const uint32_t KILN_V2_MULTICLAIM_SELECTOR = 0xb7ba18c7; // --- cast sig "claim(uint256[],uint32[],uint16)" static const uint32_t KILN_V2_CLAIM_SELECTOR = 0xadcf1163; +// Array of all supported OCV2 exit queues. +const char ocv2_exit_queues[OCV2_MAX_EXIT_QUEUES][ADDRESS_STR_LEN] = { + "0x8d6Fd650500f82c7D978a440348e5a9b886943bF", // Kiln + "0x86358F7B33b599c484e0335B8Ee4f7f7f92d8b60" // Coinbase +}; + // Array of all supported selectors. const uint32_t KILN_SELECTORS[NUM_SELECTORS] = { // V2 diff --git a/src/handle_init_contract.c b/src/handle_init_contract.c index 1f92860..f23466f 100644 --- a/src/handle_init_contract.c +++ b/src/handle_init_contract.c @@ -51,9 +51,15 @@ void handle_init_contract(ethPluginInitContract_t *msg) { switch (context->selectorIndex) { case KILN_V2_STAKE: + break; case KILN_V2_REQUEST_EXIT: + context->next_param = V2_REQUEST_EXIT_AMOUNT; + break; case KILN_V2_MULTICLAIM: + context->next_param = V2_MULTICLAIM_EXIT_QUEUES_OFFSET; + break; case KILN_V2_CLAIM: + context->next_param = V2_CLAIM_TICKET_IDS_OFFSET; break; default: diff --git a/src/kiln_plugin.h b/src/kiln_plugin.h index 07385c3..710b062 100644 --- a/src/kiln_plugin.h +++ b/src/kiln_plugin.h @@ -46,6 +46,73 @@ typedef enum { KILN_V2_CLAIM, } selector_t; +// **************************************************************************** +// * GLOBALS +// **************************************************************************** + +#define ADDRESS_STR_LEN 42 +#define OCV2_MAX_EXIT_QUEUES 2 +extern const char ocv2_exit_queues[OCV2_MAX_EXIT_QUEUES][ADDRESS_STR_LEN]; + +// **************************************************************************** +// * PARSERS STATE MACHINES +// **************************************************************************** + +typedef enum { + V2_REQUEST_EXIT_UNEXPECTED_PARAMETER = 0, + V2_REQUEST_EXIT_AMOUNT, +} v2_request_exit_parameters; + +typedef enum { + V2_CLAIM_UNEXPECTED_PARAMETER = 0, + V2_CLAIM_TICKET_IDS_OFFSET, + V2_CLAIM_CASK_IDS_OFFSET, + V2_CLAIM_MAX_CLAIM_DEPTH, + V2_CLAIM_TICKET_IDS_LENGTH, + V2_CLAIM_TICKET_IDS__ITEMS, + V2_CLAIM_CASK_IDS_LENGTH, + V2_CLAIM_CASK_IDS__ITEMS, +} v2_claim; + +typedef enum { + V2_MULTICLAIM_UNEXPECTED_PARAMETER = 0, + V2_MULTICLAIM_EXIT_QUEUES_OFFSET, + V2_MULTICLAIM_TICKET_IDS_OFFSET, + V2_MULTICLAIM_CASK_IDS_OFFSET, + + V2_MULTICLAIM_EXIT_QUEUES_LENGTH, + V2_MULTICLAIM_EXIT_QUEUES__ITEMS, + + V2_MULTICLAIM_TICKETIDS_LENGTH, + V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS, + V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH, + V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS, + + V2_MULTICLAIM_CASKIDS_LENGTH, + V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS, + V2_MULTICLAIM_CASKIDS__ITEM_LENGTH, + V2_MULTICLAIM_CASKIDS__ITEM__ITEMS, +} v2_multiclaim_parameters; + +// **************************************************************************** +// * PARSERS DATA STRUCTURES +// **************************************************************************** + +typedef struct { + uint8_t amount[INT256_LENGTH]; +} v2_request_exit_t; + +typedef struct { + // -- utils + uint16_t current_item_count; +} v2_claim_t; + +typedef struct { + // -- utils + uint16_t parent_item_count; + uint16_t current_item_count; +} v2_multiclaim_t; + // **************************************************************************** // * SHARED PLUGIN CONTEXT MEMORY // **************************************************************************** @@ -53,6 +120,12 @@ typedef enum { typedef struct context_t { uint8_t next_param; + union { + v2_request_exit_t v2_request_exit; + v2_claim_t v2_claim; + v2_multiclaim_t v2_multiclaim; + } param_data; + selector_t selectorIndex; } context_t; diff --git a/src/provide_parameter/handle_provide_parameter.c b/src/provide_parameter/handle_provide_parameter.c index 82c553a..3324f69 100644 --- a/src/provide_parameter/handle_provide_parameter.c +++ b/src/provide_parameter/handle_provide_parameter.c @@ -28,9 +28,13 @@ void handle_provide_parameter(ethPluginProvideParameter_t *msg) { msg->result = ETH_PLUGIN_RESULT_ERROR; break; case KILN_V2_REQUEST_EXIT: + handle_v2_request_exit(msg, context); + break; case KILN_V2_MULTICLAIM: + handle_v2_multiclaim(msg, context); + break; case KILN_V2_CLAIM: - msg->result = ETH_PLUGIN_RESULT_OK; + handle_v2_claim(msg, context); break; default: diff --git a/src/provide_parameter/ocv2.c b/src/provide_parameter/ocv2.c new file mode 100644 index 0000000..6976603 --- /dev/null +++ b/src/provide_parameter/ocv2.c @@ -0,0 +1,249 @@ +/******************************************************************************* + * + * ██╗ ██╗██╗██╗ ███╗ ██╗ + * ██║ ██╔╝██║██║ ████╗ ██║ + * █████╔╝ ██║██║ ██╔██╗ ██║ + * ██╔═██╗ ██║██║ ██║╚██╗██║ + * ██║ ██╗██║███████╗██║ ╚████║ + * ╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═══╝ + * + * Kiln Ethereum Ledger App + * (c) 2022-2024 Kiln + * + * contact@kiln.fi + ********************************************************************************/ + +#include "provide_parameter.h" + +void handle_v2_request_exit(ethPluginProvideParameter_t *msg, context_t *context) { + // ************************************************************************** + // FUNCTION TO PARSE + // ************************************************************************** + // + // function requestExit( + // uint256 amount + // ) external + // + // ************************************************************************** + // example + // [ 0] selector + // [ 4] amount + + v2_request_exit_t *params = &context->param_data.v2_request_exit; + + switch (context->next_param) { + case V2_REQUEST_EXIT_AMOUNT: + copy_parameter(params->amount, msg->parameter, sizeof(params->amount)); + context->next_param = V2_REQUEST_EXIT_UNEXPECTED_PARAMETER; + break; + default: + PRINTF("Param not supported: %d\n", context->next_param); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + msg->result = ETH_PLUGIN_RESULT_OK; +} + +void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context) { + // ************************************************************************** + // FUNCTION TO PARSE + // ************************************************************************** + // + // function claim( + // uint256[] ticketIds, + // uint32[] caskIds, + // uint16 maxClaimDepth + // ) + // + // ************************************************************************** + // example for 2 tickets and 3 cask ids + // [ 0] selector + // [ 4] ticketIds_offset + // [ 36] caskIds_offset + // [ 68] maxClaimDepth + // [100] ticketIds_length + // [132] ticketIds_0 + // [164] ticketIds_1 + // [196] caskIds_length + // [228] caskIds_0 + // [260] caskIds_1 + // [292] caskIds_2 + + v2_claim_t *params = &context->param_data.v2_claim; + + switch (context->next_param) { + case V2_CLAIM_TICKET_IDS_OFFSET: + context->next_param = V2_CLAIM_CASK_IDS_OFFSET; + break; + case V2_CLAIM_CASK_IDS_OFFSET: + context->next_param = V2_CLAIM_MAX_CLAIM_DEPTH; + break; + case V2_CLAIM_MAX_CLAIM_DEPTH: + context->next_param = V2_CLAIM_TICKET_IDS_LENGTH; + break; + case V2_CLAIM_TICKET_IDS_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); + context->next_param = V2_CLAIM_TICKET_IDS__ITEMS; + break; + case V2_CLAIM_TICKET_IDS__ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + context->next_param = V2_CLAIM_CASK_IDS_LENGTH; + } + break; + case V2_CLAIM_CASK_IDS_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); + context->next_param = V2_CLAIM_CASK_IDS__ITEMS; + break; + case V2_CLAIM_CASK_IDS__ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + context->next_param = V2_CLAIM_UNEXPECTED_PARAMETER; + } + break; + default: + PRINTF("Param not supported: %d\n", context->next_param); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } +} + +void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context) { + // ************************************************************************** + // FUNCTION TO PARSE + // ************************************************************************** + // + // function multiClaim( + // address[] exitQueues, + // uint256[][] ticketIds, + // uint32[][] casksIds + // ) + // + // ************************************************************************** + // example for 2 exit queues, 4 tickets and 4 cask ids + // [ 0] selector + // [ 4] exitQueues_offset + // [ 36] ticketIds_offset + // [ 68] caskIds_offset + // [100] exitQueues_length + // [132] exitQueues_0 + // [164] exitQueues_1 + // [196] ticketIds_length + // [228] ticketIds_0_offset + // [260] ticketIds_1_offset + // [292] ticketIds_0_length + // [324] ticketIds_0_0 + // [356] ticketIds_0_1 + // [388] ticketIds_1_length + // [420] ticketIds_1_0 + // [452] ticketIds_1_1 + // [484] caskIds_length + // [516] caskIds_0_offset + // [548] caskIds_1_offset + // [580] caskIds_0_length + // [612] caskIds_0_0 + // [644] caskIds_0_1 + // [676] caskIds_1_length + // [708] caskIds_1_0 + // [740] caskIds_1_1 + + v2_multiclaim_t *params = &context->param_data.v2_multiclaim; + + switch (context->next_param) { + case V2_MULTICLAIM_EXIT_QUEUES_OFFSET: + context->next_param = V2_MULTICLAIM_TICKET_IDS_OFFSET; + break; + case V2_MULTICLAIM_TICKET_IDS_OFFSET: + context->next_param = V2_MULTICLAIM_CASK_IDS_OFFSET; + break; + case V2_MULTICLAIM_CASK_IDS_OFFSET: + context->next_param = V2_MULTICLAIM_EXIT_QUEUES_LENGTH; + break; + case V2_MULTICLAIM_EXIT_QUEUES_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); + context->next_param = V2_MULTICLAIM_EXIT_QUEUES__ITEMS; + break; + case V2_MULTICLAIM_EXIT_QUEUES__ITEMS: { + uint8_t buffer[ADDRESS_LENGTH]; + copy_address(buffer, msg->parameter, sizeof(buffer)); + char address_buffer[ADDRESS_STR_LEN]; + getEthDisplayableAddress(buffer, address_buffer, sizeof(address_buffer), 0); + // we add a check to make sure we know the exit queue addresses + // that will be called in the multiclaim tx + bool is_valid = false; + for (int i = 0; i < OCV2_MAX_EXIT_QUEUES; i += 1) { + if (memcmp(ocv2_exit_queues[i], address_buffer, ADDRESS_STR_LEN) == 0) { + is_valid = true; + break; + } + } + if (!is_valid) { + PRINTF("Unexpected exit queue address: %s\n", address_buffer); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + + params->current_item_count -= 1; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_TICKETIDS_LENGTH; + } + break; + } + case V2_MULTICLAIM_TICKETIDS_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); + params->current_item_count = params->parent_item_count; + context->next_param = V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS; + break; + case V2_MULTICLAIM_TICKETIDS__OFFSET_ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; + } + break; + case V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); + context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS; + break; + case V2_MULTICLAIM_TICKETIDS__ITEM__ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + params->parent_item_count -= 1; + if (params->parent_item_count == 0) { + context->next_param = V2_MULTICLAIM_CASKIDS_LENGTH; + } else { + context->next_param = V2_MULTICLAIM_TICKETIDS__ITEM_LENGTH; + } + } + break; + case V2_MULTICLAIM_CASKIDS_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->parent_item_count); + params->current_item_count = params->parent_item_count; + context->next_param = V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS; + break; + case V2_MULTICLAIM_CASKIDS__OFFSET_ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; + } + break; + case V2_MULTICLAIM_CASKIDS__ITEM_LENGTH: + U2BE_from_parameter(msg->parameter, ¶ms->current_item_count); + context->next_param = V2_MULTICLAIM_CASKIDS__ITEM__ITEMS; + break; + case V2_MULTICLAIM_CASKIDS__ITEM__ITEMS: + params->current_item_count -= 1; + if (params->current_item_count == 0) { + if (params->parent_item_count == 0) { + context->next_param = V2_MULTICLAIM_UNEXPECTED_PARAMETER; + } else { + context->next_param = V2_MULTICLAIM_CASKIDS__ITEM_LENGTH; + } + } + break; + default: + PRINTF("Param not supported: %d\n", context->next_param); + msg->result = ETH_PLUGIN_RESULT_ERROR; + return; + } + msg->result = ETH_PLUGIN_RESULT_OK; +} \ No newline at end of file diff --git a/src/provide_parameter/provide_parameter.h b/src/provide_parameter/provide_parameter.h index 936f372..bf3557c 100644 --- a/src/provide_parameter/provide_parameter.h +++ b/src/provide_parameter/provide_parameter.h @@ -19,3 +19,7 @@ #include #include "kiln_plugin.h" + +void handle_v2_request_exit(ethPluginProvideParameter_t *msg, context_t *context); +void handle_v2_claim(ethPluginProvideParameter_t *msg, context_t *context); +void handle_v2_multiclaim(ethPluginProvideParameter_t *msg, context_t *context); diff --git a/tests/src/multiClaim.v2.test.js b/tests/src/multiClaim.v2.test.js index f77438a..2243b2b 100644 --- a/tests/src/multiClaim.v2.test.js +++ b/tests/src/multiClaim.v2.test.js @@ -18,7 +18,10 @@ nano_models.forEach(function (model) { const contract = new ethers.Contract(contractAddr, abi); const { data } = await contract.populateTransaction.multiClaim( - ['0x2e3956e1ee8b44ab826556770f69e3b9ca04a2a7'], + [ + '0x86358F7B33b599c484e0335B8Ee4f7f7f92d8b60', + '0x8d6Fd650500f82c7D978a440348e5a9b886943bF', + ], [ [42, 47], [150, 2],