@@ -12,6 +12,14 @@ pub struct WalletConnect {
1212 address : Address ,
1313}
1414
15+ #[ derive( Debug , thiserror:: Error ) ]
16+ pub enum WalletError {
17+ #[ error( transparent) ]
18+ CallError ( #[ from] CallError ) ,
19+ #[ error( "failed to sign the tx" ) ]
20+ FailedToSignTx ,
21+ }
22+
1523impl WalletConnect {
1624 pub fn new ( ) -> Result < Self , Box < dyn Error > > {
1725 let client = Client :: new (
@@ -61,14 +69,15 @@ impl WalletConnect {
6169 pub async fn sign_message < S : Send + Sync + AsRef < [ u8 ] > > (
6270 & self ,
6371 msg : S ,
64- ) -> Result < Signature , CallError > {
72+ ) -> Result < Signature , WalletError > {
6573 let msg = unsafe { std:: str:: from_utf8_unchecked ( msg. as_ref ( ) ) } ;
6674 self . client
6775 . personal_sign ( & [ msg, & self . address_string ( ) ] )
6876 . await
77+ . map_err ( WalletError :: from)
6978 }
7079
71- pub async fn sign_transaction ( & self , msg : & TypedTransaction ) -> Result < Signature , CallError > {
80+ pub async fn sign_transaction ( & self , msg : & TypedTransaction ) -> Result < Signature , WalletError > {
7281 let to = if let Some ( NameOrAddress :: Address ( address) ) = msg. to ( ) {
7382 Some ( * address)
7483 } else {
@@ -77,28 +86,125 @@ impl WalletConnect {
7786 let tx = Transaction {
7887 from : * msg. from ( ) . unwrap ( ) ,
7988 to,
80- gas_limit : None ,
89+ gas_limit : msg . gas ( ) . cloned ( ) ,
8190 gas_price : msg. gas_price ( ) ,
8291 value : * msg. value ( ) . unwrap_or ( & U256 :: from ( 0 ) ) ,
8392 data : msg. data ( ) . unwrap ( ) . to_vec ( ) ,
84- nonce : msg . nonce ( ) . copied ( ) ,
93+ nonce : None ,
8594 } ;
8695
8796 let raw = self . client . sign_transaction ( tx) . await ?. to_vec ( ) ;
88- assert_eq ! ( raw[ raw. len( ) - 66 ] , 160 ) ;
89- assert_eq ! ( raw[ raw. len( ) - 33 ] , 160 ) ;
90-
91- // Transform `v` according to:
92- // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#specification
93- let mut v = raw[ raw. len ( ) - 67 ] as u64 ;
94- if v == 27 || v == 28 {
95- v += 2 * self . chain_id ( ) + 8 ;
97+ let mut v_r_s = None ;
98+ for offset in 0 ..7 {
99+ let mut head = raw. len ( ) - 67 + offset;
100+ v_r_s = extract_v_r_s ( & raw [ head..] ) ;
101+ if v_r_s. is_some ( ) {
102+ break ;
103+ }
104+
105+ if offset == 0 {
106+ continue ;
107+ }
108+ head = raw. len ( ) - 67 - offset;
109+ v_r_s = extract_v_r_s ( & raw [ head..] ) ;
110+ if v_r_s. is_some ( ) {
111+ break ;
112+ }
96113 }
97114
115+ let ( v, r, s) = v_r_s. ok_or ( WalletError :: FailedToSignTx ) ?;
98116 Ok ( Signature {
99117 v,
100- r : U256 :: from ( & raw [ raw . len ( ) - 65 ..raw . len ( ) - 33 ] ) ,
101- s : U256 :: from ( & raw [ raw . len ( ) - 32 .. ] ) ,
118+ r : U256 :: from ( r ) ,
119+ s : U256 :: from ( s ) ,
102120 } )
103121 }
104122}
123+
124+ fn extract_v_r_s ( tx : & [ u8 ] ) -> Option < ( u64 , & [ u8 ] , & [ u8 ] ) > {
125+ let mut head = 0_usize ;
126+ let v: u64 = tx[ head] . into ( ) ;
127+
128+ head += 1 ;
129+ if tx[ head] <= 0x80 {
130+ return None ;
131+ }
132+ let len_r = ( tx[ head] - 0x80 ) as usize ;
133+ if head + len_r >= tx. len ( ) {
134+ return None ;
135+ }
136+ let r = & tx[ head + 1 ..head + 1 + len_r] ;
137+
138+ head += 1 + len_r;
139+ if tx[ head] <= 0x80 {
140+ return None ;
141+ }
142+ let len_s = ( tx[ head] - 0x80 ) as usize ;
143+ if head + len_s >= tx. len ( ) {
144+ return None ;
145+ }
146+ let s = & tx[ head + 1 ..head + 1 + len_s] ;
147+
148+ if 1 + r. len ( ) + s. len ( ) + 2 != tx. len ( ) {
149+ return None ;
150+ }
151+
152+ Some ( ( v, r, s) )
153+ }
154+
155+ #[ cfg( test) ]
156+ mod test {
157+ use super :: * ;
158+
159+ #[ test]
160+ fn test_regular_sig ( ) {
161+ let tx = [
162+ 0x1c , 0xa0 , 0x88 , 0xff , 0x6c , 0xf0 , 0xfe , 0xfd , 0x94 , 0xdb , 0x46 , 0x11 , 0x11 , 0x49 ,
163+ 0xae , 0x4b , 0xfc , 0x17 , 0x9e , 0x9b , 0x94 , 0x72 , 0x1f , 0xff , 0xd8 , 0x21 , 0xd3 , 0x8d ,
164+ 0x16 , 0x46 , 0x4b , 0x3f , 0x71 , 0xd0 , 0xa0 , 0x45 , 0xe0 , 0xaf , 0xf8 , 0x00 , 0x96 , 0x1c ,
165+ 0xfc , 0xe8 , 0x05 , 0xda , 0xef , 0x70 , 0x16 , 0xb9 , 0xb6 , 0x75 , 0xc1 , 0x37 , 0xa6 , 0xa4 ,
166+ 0x1a , 0x54 , 0x8f , 0x7b , 0x60 , 0xa3 , 0x48 , 0x4c , 0x06 , 0xa3 , 0x3a ,
167+ ] ;
168+
169+ let v_r_s = extract_v_r_s ( & tx) ;
170+ assert ! ( v_r_s. is_some( ) ) ;
171+ let ( v, r, s) = v_r_s. unwrap ( ) ;
172+
173+ assert_eq ! ( v, 0x1c ) ;
174+ assert_eq ! ( r, & tx[ tx. len( ) - 65 ..tx. len( ) - 33 ] ) ;
175+ assert_eq ! ( s, & tx[ tx. len( ) - 32 ..] ) ;
176+ }
177+
178+ #[ test]
179+ fn test_variable_sig ( ) {
180+ let tx = [
181+ 0x2c , 0xa0 , 0x09 , 0x0c , 0x0a , 0x25 , 0xaf , 0x16 , 0x3b , 0x51 , 0x86 , 0xd5 , 0x6f , 0x61 ,
182+ 0xd2 , 0xd1 , 0xe7 , 0xcf , 0xf1 , 0x05 , 0xb8 , 0x9e , 0x24 , 0xed , 0x48 , 0x26 , 0x7c , 0x43 ,
183+ 0xa0 , 0x22 , 0x27 , 0xd9 , 0xf7 , 0x14 , 0x9f , 0x9b , 0xcc , 0xf7 , 0x3a , 0xef , 0xa7 , 0x7d ,
184+ 0x2c , 0xcb , 0x0b , 0x81 , 0x59 , 0x15 , 0x04 , 0xde , 0xcc , 0x07 , 0xc1 , 0x26 , 0x92 , 0xf9 ,
185+ 0x0f , 0xfe , 0x47 , 0xd0 , 0xf0 , 0xbd , 0xea , 0x99 , 0xa6 , 0x8d ,
186+ ] ;
187+
188+ let v_r_s = extract_v_r_s ( & tx) ;
189+ assert ! ( v_r_s. is_some( ) ) ;
190+ let ( v, r, s) = v_r_s. unwrap ( ) ;
191+
192+ assert_eq ! ( v, 0x2c ) ;
193+ assert_eq ! ( r, & tx[ tx. len( ) - 64 ..tx. len( ) - 32 ] ) ;
194+ assert_eq ! ( s, & tx[ tx. len( ) - 31 ..] ) ;
195+ }
196+
197+ #[ test]
198+ fn test_malformed_sig ( ) {
199+ let tx = [
200+ 0x2c , 0xa0 , 0x09 , 0x0c , 0x0a , 0x25 , 0xaf , 0x16 , 0x3b , 0x51 , 0x86 , 0xd5 , 0x6f , 0x61 ,
201+ 0xd2 , 0xd1 , 0xe7 , 0xcf , 0xf1 , 0x05 , 0xb8 , 0x9e , 0x24 , 0xed , 0x48 , 0x26 , 0x7c , 0x43 ,
202+ 0xa0 , 0x22 , 0x27 , 0xd9 , 0xf7 , 0x14 , 0x81 , 0x9b , 0xcc , 0xf7 , 0x3a , 0xef , 0xa7 , 0x7d ,
203+ 0x2c , 0xcb , 0x0b , 0x81 , 0x59 , 0x15 , 0x04 , 0xde , 0xcc , 0x07 , 0xc1 , 0x26 , 0x92 , 0xf9 ,
204+ 0x0f , 0xfe , 0x47 , 0xd0 , 0xf0 , 0xbd , 0xea , 0x99 , 0xa6 , 0x8d ,
205+ ] ;
206+
207+ let v_r_s = extract_v_r_s ( & tx) ;
208+ assert ! ( v_r_s. is_none( ) ) ;
209+ }
210+ }
0 commit comments