@@ -6,65 +6,51 @@ use std::collections::HashMap;
66use tiny_keccak:: { Hasher , Keccak } ;
77use yultsur:: * ;
88
9- /// Builds a switch statement from the contract ABI that handles contract calls .
10- pub fn switch (
9+ /// Builds a switch statement that dispatches calls to the contract.
10+ pub fn dispatcher (
1111 interface : & Vec < String > ,
1212 defs : & HashMap < String , ContractDef > ,
1313) -> Result < yul:: Statement , CompileError > {
14- let cases = interface
14+ let arms = interface
1515 . into_iter ( )
16- . map ( |name| case ( name. to_owned ( ) , defs) )
16+ . map ( |name| dispatch_arm ( name. to_owned ( ) , defs) )
1717 . collect :: < Result < Vec < yul:: Case > , CompileError > > ( ) ?;
1818
1919 Ok ( switch ! {
2020 switch ( cloadn( 0 , 4 ) )
21- [ cases ...]
21+ [ arms ...]
2222 } )
2323}
2424
25- fn case ( name : String , defs : & HashMap < String , ContractDef > ) -> Result < yul:: Case , CompileError > {
26- if let Some ( def) = defs. get ( & name) {
27- return match def {
28- ContractDef :: Function { params, returns } => {
29- function_call_case ( name, params, returns. to_owned ( ) )
30- }
31- _ => Err ( CompileError :: static_str (
32- "Cannot create case from definition" ,
33- ) ) ,
34- } ;
25+ fn dispatch_arm (
26+ name : String ,
27+ defs : & HashMap < String , ContractDef >
28+ ) -> Result < yul:: Case , CompileError > {
29+ if let Some ( ContractDef :: Function { params, returns } ) = defs. get ( & name) {
30+ let selector = selector ( name. clone ( ) , & params) ;
31+
32+ if let Some ( returns) = returns {
33+ let selection = selection ( name, & params) ?;
34+ let return_data = returns. encode ( selection) ?;
35+ let return_size = literal_expression ! { ( returns. padded_size( ) ) } ;
36+
37+ let selection_with_return = statement ! { return ( [ return_data] , [ return_size] ) } ;
38+
39+ return Ok ( case ! { case [ selector] { [ selection_with_return] } } )
40+ }
41+
42+ let selection = selection_as_statement ( name, & params) ?;
43+
44+ return Ok ( case ! { case [ selector] { [ selection] } } )
3545 }
3646
3747 Err ( CompileError :: static_str ( "No definition for name" ) )
3848}
3949
40- fn function_call_case (
50+ fn selector (
4151 name : String ,
42- params : & Vec < FixedSize > ,
43- returns : Option < FixedSize > ,
44- ) -> Result < yul:: Case , CompileError > {
45- let selector = selector_literal ( name. clone ( ) , & params) ;
46- let name = identifier ! { ( name) } ;
47- let params = parameter_expressions ( & params) ?;
48-
49- if let Some ( returns) = returns {
50- let return_size = literal_expression ! { ( returns. padded_size( ) ) } ;
51- let function_call = expression ! { [ name] ( [ params...] ) } ;
52-
53- Ok ( case ! {
54- case [ selector] {
55- ( return ( [ returns. encode( function_call) ?] , [ return_size] ) )
56- }
57- } )
58- } else {
59- let function_call = statement ! { [ name] ( [ params...] ) } ;
60-
61- Ok ( case ! {
62- case [ selector] { [ function_call] }
63- } )
64- }
65- }
66-
67- fn selector_literal ( name : String , params : & Vec < FixedSize > ) -> yul:: Literal {
52+ params : & Vec < FixedSize >
53+ ) -> yul:: Literal {
6854 let signature = format ! (
6955 "{}({})" ,
7056 name,
@@ -84,31 +70,43 @@ fn selector_literal(name: String, params: &Vec<FixedSize>) -> yul::Literal {
8470 literal ! { ( format!( "0x{}" , hex:: encode( selector) ) ) }
8571}
8672
87- fn parameter_expressions ( params : & Vec < FixedSize > ) -> Result < Vec < yul:: Expression > , CompileError > {
73+ fn selection (
74+ name : String ,
75+ params : & Vec < FixedSize >
76+ ) -> Result < yul:: Expression , CompileError > {
8877 let mut ptr = 4 ;
89- let mut expressions = vec ! [ ] ;
78+ let mut decoded_params = vec ! [ ] ;
9079
9180 for param in params. iter ( ) {
92- expressions . push ( param. decode ( literal_expression ! { ( ptr) } ) ?) ;
81+ decoded_params . push ( param. decode ( literal_expression ! { ( ptr) } ) ?) ;
9382 ptr += param. padded_size ( ) ;
9483 }
9584
96- Ok ( expressions)
85+ let name = identifier ! { ( name) } ;
86+
87+ Ok ( expression ! { [ name] ( [ decoded_params...] ) } )
88+ }
89+
90+
91+ fn selection_as_statement (
92+ name : String ,
93+ params : & Vec < FixedSize >
94+ ) -> Result < yul:: Statement , CompileError > {
95+ Ok ( yul:: Statement :: Expression ( selection ( name, params) ?) )
9796}
9897
9998#[ test]
100- fn selector_literal_basic ( ) {
99+ fn test_selector_literal_basic ( ) {
101100 assert_eq ! (
102- selector_literal ( "foo" . to_string( ) , & vec![ ] ) . to_string( ) ,
101+ selector ( "foo" . to_string( ) , & vec![ ] ) . to_string( ) ,
103102 String :: from( "0xc2985578" ) ,
104- "Incorrect selector"
105103 )
106104}
107105
108106#[ test]
109107fn test_selector_literal ( ) {
110108 assert_eq ! (
111- selector_literal ( "bar" . to_string( ) , & vec![ FixedSize :: Base ( Base :: U256 ) ] ) . to_string( ) ,
109+ selector ( "bar" . to_string( ) , & vec![ FixedSize :: Base ( Base :: U256 ) ] ) . to_string( ) ,
112110 String :: from( "0x0423a132" ) ,
113111 )
114112}
0 commit comments