1
1
use alloy_primitives:: { FixedBytes , Uint , U256 } ;
2
2
use alloy_sol_types:: { sol, SolValue } ;
3
3
use axelar_soroban_std:: ensure;
4
- use soroban_sdk:: { contracterror , Bytes , BytesN , Env , String } ;
4
+ use soroban_sdk:: { Bytes , BytesN , Env , String } ;
5
5
6
+ // alloc needed for converting to alloy types
7
+ use crate :: abi:: alloc:: { string:: String as StdString , vec} ;
8
+ use crate :: error:: ContractError ;
6
9
use crate :: types:: { self , HubMessage , Message } ;
7
10
extern crate alloc;
8
- use crate :: abi:: alloc:: { string:: String as StdString , vec} ;
9
-
10
- #[ contracterror]
11
- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
12
- #[ repr( u32 ) ]
13
- pub enum MessageError {
14
- InsufficientMessageLength = 0 ,
15
- InvalidMessageType = 1 ,
16
- AbiDecodeFailed = 2 ,
17
- InvalidAmount = 3 ,
18
- InvalidUtf8 = 4 ,
19
- }
20
11
21
12
sol ! {
13
+ #[ derive( PartialEq , Eq ) ]
22
14
enum MessageType {
23
15
InterchainTransfer ,
24
16
DeployInterchainToken ,
59
51
}
60
52
61
53
impl Message {
62
- pub fn abi_encode ( self , env : & Env ) -> Result < Bytes , MessageError > {
54
+ pub fn abi_encode ( self , env : & Env ) -> Result < Bytes , ContractError > {
63
55
let msg = match self {
64
56
Self :: InterchainTransfer ( types:: InterchainTransfer {
65
57
token_id,
@@ -95,18 +87,15 @@ impl Message {
95
87
Ok ( Bytes :: from_slice ( env, & msg) )
96
88
}
97
89
98
- pub fn abi_decode ( env : & Env , payload : & Bytes ) -> Result < Self , MessageError > {
99
- ensure ! ( payload. len( ) >= 32 , MessageError :: InsufficientMessageLength ) ;
100
-
90
+ pub fn abi_decode ( env : & Env , payload : & Bytes ) -> Result < Self , ContractError > {
101
91
let payload = payload. to_alloc_vec ( ) ;
102
92
103
- let message_type = MessageType :: abi_decode ( & payload[ 0 ..32 ] , true )
104
- . map_err ( |_| MessageError :: InvalidMessageType ) ?;
93
+ let message_type = get_message_type ( & payload) ?;
105
94
106
95
match message_type {
107
96
MessageType :: InterchainTransfer => {
108
97
let decoded = InterchainTransfer :: abi_decode_params ( & payload, true )
109
- . map_err ( |_| MessageError :: AbiDecodeFailed ) ?;
98
+ . map_err ( |_| ContractError :: AbiDecodeFailed ) ?;
110
99
111
100
Ok ( Self :: InterchainTransfer ( types:: InterchainTransfer {
112
101
token_id : BytesN :: from_array ( env, & decoded. tokenId . into ( ) ) ,
@@ -121,7 +110,7 @@ impl Message {
121
110
}
122
111
MessageType :: DeployInterchainToken => {
123
112
let decoded = DeployInterchainToken :: abi_decode_params ( & payload, true )
124
- . map_err ( |_| MessageError :: AbiDecodeFailed ) ?;
113
+ . map_err ( |_| ContractError :: AbiDecodeFailed ) ?;
125
114
126
115
Ok ( Self :: DeployInterchainToken ( types:: DeployInterchainToken {
127
116
token_id : BytesN :: from_array ( env, & decoded. tokenId . into ( ) ) ,
@@ -131,14 +120,13 @@ impl Message {
131
120
minter : from_vec ( env, decoded. minter . as_ref ( ) ) ,
132
121
} ) )
133
122
}
134
- _ => Err ( MessageError :: InvalidMessageType ) ,
123
+ _ => Err ( ContractError :: InvalidMessageType ) ,
135
124
}
136
125
}
137
126
}
138
127
139
- #[ allow( dead_code) ]
140
128
impl HubMessage {
141
- pub fn abi_encode ( self , env : & Env ) -> Result < Bytes , MessageError > {
129
+ pub fn abi_encode ( self , env : & Env ) -> Result < Bytes , ContractError > {
142
130
let msg = match self {
143
131
Self :: SendToHub {
144
132
destination_chain,
@@ -162,18 +150,15 @@ impl HubMessage {
162
150
Ok ( Bytes :: from_slice ( env, & msg) )
163
151
}
164
152
165
- pub fn abi_decode ( env : & Env , payload : & Bytes ) -> Result < Self , MessageError > {
166
- ensure ! ( payload. len( ) >= 32 , MessageError :: InsufficientMessageLength ) ;
167
-
153
+ pub fn abi_decode ( env : & Env , payload : & Bytes ) -> Result < Self , ContractError > {
168
154
let payload = payload. to_alloc_vec ( ) ;
169
155
170
- let message_type = MessageType :: abi_decode ( & payload[ 0 ..32 ] , true )
171
- . map_err ( |_| MessageError :: InvalidMessageType ) ?;
156
+ let message_type = get_message_type ( & payload) ?;
172
157
173
158
match message_type {
174
159
MessageType :: SendToHub => {
175
160
let decoded = SendToHub :: abi_decode_params ( & payload, true )
176
- . map_err ( |_| MessageError :: AbiDecodeFailed ) ?;
161
+ . map_err ( |_| ContractError :: AbiDecodeFailed ) ?;
177
162
178
163
Ok ( Self :: SendToHub {
179
164
destination_chain : String :: from_str ( env, & decoded. destination_chain ) ,
@@ -185,7 +170,7 @@ impl HubMessage {
185
170
}
186
171
MessageType :: ReceiveFromHub => {
187
172
let decoded = ReceiveFromHub :: abi_decode_params ( & payload, true )
188
- . map_err ( |_| MessageError :: AbiDecodeFailed ) ?;
173
+ . map_err ( |_| ContractError :: AbiDecodeFailed ) ?;
189
174
190
175
Ok ( Self :: ReceiveFromHub {
191
176
source_chain : String :: from_str ( env, & decoded. source_chain ) ,
@@ -195,19 +180,31 @@ impl HubMessage {
195
180
) ?,
196
181
} )
197
182
}
198
- _ => Err ( MessageError :: InvalidMessageType ) ,
183
+ _ => Err ( ContractError :: InvalidMessageType ) ,
199
184
}
200
185
}
201
186
}
202
187
203
- fn to_std_string ( soroban_string : String ) -> Result < StdString , MessageError > {
188
+ pub fn get_message_type ( payload : & [ u8 ] ) -> Result < MessageType , ContractError > {
189
+ ensure ! (
190
+ payload. len( ) >= 32 ,
191
+ ContractError :: InsufficientMessageLength
192
+ ) ;
193
+
194
+ let message_type = MessageType :: abi_decode ( & payload[ 0 ..32 ] , true )
195
+ . map_err ( |_| ContractError :: InvalidMessageType ) ?;
196
+
197
+ Ok ( message_type)
198
+ }
199
+
200
+ fn to_std_string ( soroban_string : String ) -> Result < StdString , ContractError > {
204
201
let length = soroban_string. len ( ) as usize ;
205
202
let mut bytes = vec ! [ 0u8 ; length] ;
206
203
soroban_string. copy_into_slice ( & mut bytes) ;
207
- StdString :: from_utf8 ( bytes) . map_err ( |_| MessageError :: InvalidUtf8 )
204
+ StdString :: from_utf8 ( bytes) . map_err ( |_| ContractError :: InvalidUtf8 )
208
205
}
209
206
210
- fn to_i128 ( value : Uint < 256 , 4 > ) -> Result < i128 , MessageError > {
207
+ fn to_i128 ( value : Uint < 256 , 4 > ) -> Result < i128 , ContractError > {
211
208
let slice = value. as_le_slice ( ) ;
212
209
213
210
let mut bytes_to_remove = [ 0 ; 16 ] ;
@@ -217,12 +214,12 @@ fn to_i128(value: Uint<256, 4>) -> Result<i128, MessageError> {
217
214
218
215
ensure ! (
219
216
i128 :: from_le_bytes( bytes_to_remove) == 0 ,
220
- MessageError :: InvalidAmount
217
+ ContractError :: InvalidAmount
221
218
) ;
222
219
223
220
let i128_value = i128:: from_le_bytes ( bytes_to_convert) ;
224
221
225
- ensure ! ( i128_value >= 0 , MessageError :: InvalidAmount ) ;
222
+ ensure ! ( i128_value >= 0 , ContractError :: InvalidAmount ) ;
226
223
227
224
Ok ( i128_value)
228
225
}
@@ -253,7 +250,7 @@ mod tests {
253
250
use soroban_sdk:: { Bytes , BytesN , Env , String } ;
254
251
use std:: vec:: Vec ;
255
252
256
- fn bytes_from_hex ( env : & Env , hex_string : & str ) -> Bytes {
253
+ pub fn bytes_from_hex ( env : & Env , hex_string : & str ) -> Bytes {
257
254
let bytes_vec: Vec < u8 > = hex:: decode ( hex_string) . unwrap ( ) ;
258
255
Bytes :: from_slice ( env, & bytes_vec)
259
256
}
@@ -305,7 +302,7 @@ mod tests {
305
302
306
303
for sequence in invalid_sequences {
307
304
let result = to_std_string ( sequence) ;
308
- assert ! ( matches!( result, Err ( MessageError :: InvalidUtf8 ) ) ) ;
305
+ assert ! ( matches!( result, Err ( ContractError :: InvalidUtf8 ) ) ) ;
309
306
}
310
307
}
311
308
@@ -340,18 +337,18 @@ mod tests {
340
337
341
338
let result = to_i128 ( bad_uint) ;
342
339
343
- assert ! ( matches!( result, Err ( MessageError :: InvalidAmount ) ) ) ;
340
+ assert ! ( matches!( result, Err ( ContractError :: InvalidAmount ) ) ) ;
344
341
}
345
342
346
343
#[ test]
347
344
fn to_i128_fails_overflow ( ) {
348
345
let overflow: Uint < 256 , 4 > = Uint :: from ( i128:: MAX ) + Uint :: from ( 1 ) ;
349
346
let result = to_i128 ( overflow) ;
350
- assert ! ( matches!( result, Err ( MessageError :: InvalidAmount ) ) ) ;
347
+ assert ! ( matches!( result, Err ( ContractError :: InvalidAmount ) ) ) ;
351
348
352
349
let overflow: Uint < 256 , 4 > = Uint :: from ( u128:: MAX ) ;
353
350
let result = to_i128 ( overflow) ;
354
- assert ! ( matches!( result, Err ( MessageError :: InvalidAmount ) ) ) ;
351
+ assert ! ( matches!( result, Err ( ContractError :: InvalidAmount ) ) ) ;
355
352
}
356
353
357
354
#[ test]
@@ -529,7 +526,7 @@ mod tests {
529
526
let invalid_payload = Bytes :: from_slice ( & env, & bytes) ;
530
527
531
528
let result = HubMessage :: abi_decode ( & env, & invalid_payload) ;
532
- assert ! ( matches!( result, Err ( MessageError :: InvalidMessageType ) ) ) ;
529
+ assert ! ( matches!( result, Err ( ContractError :: InvalidMessageType ) ) ) ;
533
530
534
531
let invalid_hub_message_type = assert_ok ! ( types:: Message :: InterchainTransfer (
535
532
types:: InterchainTransfer {
@@ -543,6 +540,6 @@ mod tests {
543
540
. abi_encode( & env) ) ;
544
541
545
542
let result = HubMessage :: abi_decode ( & env, & invalid_hub_message_type) ;
546
- assert ! ( matches!( result, Err ( MessageError :: InvalidMessageType ) ) ) ;
543
+ assert ! ( matches!( result, Err ( ContractError :: InvalidMessageType ) ) ) ;
547
544
}
548
545
}
0 commit comments