11use crate :: Codegen ;
22use crate :: irgen:: constants:: { constant_gen, evaluate_constant_value} ;
33use alloy_primitives:: { B256 , hex, keccak256} ;
4+ use huff_neo_utils:: builtin_eval:: { PadDirection , eval_builtin_bytes, eval_event_hash, eval_function_signature} ;
45use huff_neo_utils:: bytecode:: { BytecodeRes , Bytes , CircularCodeSizeIndices , Jump , Jumps } ;
56use huff_neo_utils:: bytes_util:: { bytes32_to_hex_string, format_even_bytes, pad_n_bytes} ;
67use huff_neo_utils:: error:: { CodegenError , CodegenErrorKind } ;
@@ -10,7 +11,6 @@ use huff_neo_utils::prelude::{
1011 Argument , AstSpan , BuiltinFunctionArg , BuiltinFunctionCall , BuiltinFunctionKind , Contract , MacroDefinition , MacroInvocation , PushValue ,
1112 TableDefinition ,
1213} ;
13- use std:: fmt:: Display ;
1414
1515/// Creates a CodegenError for invalid arguments
1616fn invalid_arguments_error ( msg : impl Into < String > , span : & AstSpan ) -> CodegenError {
@@ -139,13 +139,13 @@ pub fn builtin_function_gen<'a>(
139139 }
140140 }
141141 BuiltinFunctionKind :: FunctionSignature => {
142- let push_value = function_signature ( contract, bf) ?;
142+ let push_value = eval_function_signature ( contract, bf) ?;
143143 let push_bytes = push_value. to_hex_with_opcode ( evm_version) ;
144144 * offset += push_bytes. len ( ) / 2 ;
145145 bytes. push ( ( starting_offset, Bytes ( push_bytes) ) ) ;
146146 }
147147 BuiltinFunctionKind :: EventHash => {
148- let push_value = event_hash ( contract, bf) ?;
148+ let push_value = eval_event_hash ( contract, bf) ?;
149149 let push_bytes = push_value. to_hex_with_opcode ( evm_version) ;
150150 * offset += push_bytes. len ( ) / 2 ;
151151 bytes. push ( ( starting_offset, Bytes ( push_bytes) ) ) ;
@@ -231,7 +231,7 @@ pub fn builtin_function_gen<'a>(
231231 bytes. push ( ( starting_offset, Bytes ( push_bytes) ) ) ;
232232 }
233233 BuiltinFunctionKind :: Bytes => {
234- let push_value = builtin_bytes ( bf) ?;
234+ let push_value = eval_builtin_bytes ( bf) ?;
235235 let push_bytes = push_value. to_hex_with_opcode ( evm_version) ;
236236 * offset += push_bytes. len ( ) / 2 ;
237237 bytes. push ( ( starting_offset, Bytes ( push_bytes) ) ) ;
@@ -440,86 +440,15 @@ pub fn tablesize(contract: &Contract, bf: &BuiltinFunctionCall) -> Result<(Table
440440 Ok ( ( ir_table, push_bytes) )
441441}
442442
443- /// Generates a PushValue for the __EVENT_HASH builtin function
444- ///
445- /// Returns a PushValue containing the full keccak256 hash (32 bytes) of the event signature.
446- /// Looks up event definitions in the contract or computes the hash via keccak256.
447- pub fn event_hash ( contract : & Contract , bf : & BuiltinFunctionCall ) -> Result < PushValue , CodegenError > {
448- validate_arg_count ( bf, 1 , "__EVENT_HASH" ) ?;
449- let first_arg = extract_single_argument ( bf, "__EVENT_HASH" ) ?;
450- let hash = if let Some ( event) = contract. events . iter ( ) . find ( |e| first_arg. name . as_ref ( ) . unwrap ( ) . eq ( & e. name ) ) {
451- event. hash
452- } else if let Some ( s) = & first_arg. name {
453- keccak256 ( s) . 0
454- } else {
455- tracing:: error!(
456- target: "codegen" ,
457- "MISSING EVENT INTERFACE PASSED TO __EVENT_HASH: \" {}\" " ,
458- first_arg. name. as_ref( ) . unwrap( )
459- ) ;
460- return Err ( CodegenError {
461- kind : CodegenErrorKind :: MissingEventInterface ( first_arg. name . as_ref ( ) . unwrap ( ) . to_string ( ) ) ,
462- span : bf. span . clone_box ( ) ,
463- token : None ,
464- } ) ;
465- } ;
466- Ok ( PushValue :: from ( hash) )
467- }
468-
469- /// Generates a PushValue for the __FUNC_SIG builtin function
470- ///
471- /// Returns a PushValue containing the 4-byte function selector (first 4 bytes of keccak256 hash).
472- /// Looks up function/error definitions in the contract or computes the selector via keccak256.
473- pub fn function_signature ( contract : & Contract , bf : & BuiltinFunctionCall ) -> Result < PushValue , CodegenError > {
474- validate_arg_count ( bf, 1 , "__FUNC_SIG" ) ?;
475- let first_arg = extract_single_argument ( bf, "__FUNC_SIG" ) ?;
476- let selector = if let Some ( func) = contract. functions . iter ( ) . find ( |f| first_arg. name . as_ref ( ) . unwrap ( ) . eq ( & f. name ) ) {
477- func. signature
478- } else if let Some ( error) = contract. errors . iter ( ) . find ( |e| first_arg. name . as_ref ( ) . unwrap ( ) . eq ( & e. name ) ) {
479- error. selector
480- } else if let Some ( s) = & first_arg. name {
481- keccak256 ( s) [ ..4 ] . try_into ( ) . unwrap ( )
482- } else {
483- tracing:: error!(
484- target: "codegen" ,
485- "MISSING FUNCTION INTERFACE PASSED TO __SIG: \" {}\" " ,
486- first_arg. name. as_ref( ) . unwrap( )
487- ) ;
488- return Err ( CodegenError {
489- kind : CodegenErrorKind :: MissingFunctionInterface ( first_arg. name . as_ref ( ) . unwrap ( ) . to_string ( ) ) ,
490- span : bf. span . clone_box ( ) ,
491- token : None ,
492- } ) ;
493- } ;
494-
495- // Left-pad the 4-byte selector to 32 bytes for B256
496- let mut bytes = [ 0u8 ; 32 ] ;
497- bytes[ 28 ..32 ] . copy_from_slice ( & selector) ;
498- Ok ( PushValue :: from ( bytes) )
499- }
500-
501- #[ derive( Debug , Clone , PartialEq ) ]
502- pub enum PadDirection {
503- Left ,
504- Right ,
505- }
506- impl Display for PadDirection {
507- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
508- match self {
509- PadDirection :: Left => write ! ( f, "__LEFTPAD" ) ,
510- PadDirection :: Right => write ! ( f, "__RIGHTPAD" ) ,
511- }
512- }
513- }
514-
515443/// Generates a PushValue for left or right padding a byte string to 32 bytes
516444pub fn builtin_pad ( contract : & Contract , bf : & BuiltinFunctionCall , direction : PadDirection ) -> Result < PushValue , CodegenError > {
517445 validate_arg_count ( bf, 1 , & direction. to_string ( ) ) ?;
518446 let first_arg = match & bf. args [ 0 ] {
519447 BuiltinFunctionArg :: Argument ( arg) => arg. name . clone ( ) . unwrap_or_default ( ) ,
520448 BuiltinFunctionArg :: BuiltinFunctionCall ( inner_call) => match inner_call. kind {
521- BuiltinFunctionKind :: FunctionSignature => function_signature ( contract, inner_call) ?. to_hex_trimmed ( ) ,
522- BuiltinFunctionKind :: Bytes => builtin_bytes ( inner_call) ?. to_hex_trimmed ( ) ,
449+ BuiltinFunctionKind :: FunctionSignature => eval_function_signature ( contract, inner_call) ?. to_hex_trimmed ( ) ,
450+ BuiltinFunctionKind :: Bytes => eval_builtin_bytes ( inner_call) ?. to_hex_trimmed ( ) ,
451+ BuiltinFunctionKind :: EventHash => eval_event_hash ( contract, inner_call) ?. to_hex_trimmed ( ) ,
523452 _ => {
524453 tracing:: error!( target: "codegen" , "Invalid function call argument type passed to {direction}" ) ;
525454 return Err ( invalid_arguments_error ( format ! ( "Invalid argument type passed to {direction}" ) , & bf. span ) ) ;
@@ -554,34 +483,3 @@ pub fn builtin_pad(contract: &Contract, bf: &BuiltinFunctionCall, direction: Pad
554483
555484 Ok ( PushValue :: new ( B256 :: from ( bytes_array) ) )
556485}
557-
558- /// Validates and converts a string argument to a right-padded 32-byte array
559- fn validate_and_pad_string ( bf : & BuiltinFunctionCall ) -> Result < [ u8 ; 32 ] , CodegenError > {
560- validate_arg_count ( bf, 1 , "__BYTES" ) ?;
561- let first_arg = match bf. args [ 0 ] {
562- BuiltinFunctionArg :: Argument ( ref arg) => arg. name . clone ( ) . unwrap_or_default ( ) ,
563- _ => {
564- tracing:: error!( target: "codegen" , "Invalid argument type passed to __BYTES" ) ;
565- return Err ( invalid_arguments_error ( "Invalid argument type passed to __BYTES" , & bf. span ) ) ;
566- }
567- } ;
568-
569- if first_arg. is_empty ( ) {
570- return Err ( invalid_arguments_error ( "Empty string passed to __BYTES" , & bf. span ) ) ;
571- }
572-
573- let bytes = first_arg. as_bytes ( ) ;
574- if bytes. len ( ) > 32 {
575- return Err ( invalid_arguments_error ( "Encoded bytes length exceeds 32 bytes" , & bf. span ) ) ;
576- }
577-
578- let mut bytes_array = [ 0u8 ; 32 ] ;
579- bytes_array[ 32 - bytes. len ( ) ..] . copy_from_slice ( bytes) ;
580- Ok ( bytes_array)
581- }
582-
583- /// Generates a PushValue for the __BYTES builtin function
584- pub fn builtin_bytes ( bf : & BuiltinFunctionCall ) -> Result < PushValue , CodegenError > {
585- let bytes_array = validate_and_pad_string ( bf) ?;
586- Ok ( PushValue :: new ( B256 :: from ( bytes_array) ) )
587- }
0 commit comments