1
+
2
+ module wormhole_transceiver ::wormhole_transceiver_info {
3
+ use wormhole::external_address::{Self ,ExternalAddress };
4
+ use wormhole::bytes;
5
+ use wormhole::cursor::{Self , Cursor };
6
+ use ntt_common::bytes4::{Self };
7
+ use ntt::mode::{Self , Mode };
8
+
9
+ const INFO_PREFIX : vector <u8 > = x"9C23BD3B ";
10
+
11
+ #[error]
12
+ const EIncorrectPrefix : vector <u8 >
13
+ = b"incorrect prefix ";
14
+
15
+ // https://github.com/wormhole-foundation/native-token-transfers/blob/b6b681a77e8289869f35862b261b8048e3f5d398/evm/src/libraries/TransceiverStructs.sol#L409C12-L409C27
16
+ public struct WormholeTransceiverInfo has drop {
17
+ manager_address: ExternalAddress ,
18
+ manager_mode: Mode ,
19
+ token_address: ExternalAddress ,
20
+ token_decimals: u8
21
+ }
22
+
23
+ public (package ) fun new (manager_address: ExternalAddress , mode: Mode , token_address: ExternalAddress , decimals: u8 ): WormholeTransceiverInfo {
24
+ WormholeTransceiverInfo {
25
+ manager_address: manager_address,
26
+ manager_mode: mode,
27
+ token_address: token_address,
28
+ token_decimals: decimals
29
+ }
30
+ }
31
+
32
+ public fun to_bytes (self: &WormholeTransceiverInfo ): vector <u8> {
33
+ let mut buf = vector ::empty <u8 >();
34
+
35
+ buf.append (INFO_PREFIX );
36
+ buf.append (self.manager_address.to_bytes ()); // decimals and amount
37
+ buf.append (self.manager_mode.serialize ()); // 32 bytes
38
+ buf.append (self.token_address.to_bytes ()); // 32 bytes
39
+ bytes::push_u8 (&mut buf, self.token_decimals); // 2 bytes
40
+ buf
41
+ }
42
+
43
+ public fun take_bytes (cur: &mut Cursor <u8 >): WormholeTransceiverInfo {
44
+ let ntt_prefix = bytes4::take (cur);
45
+ assert !(ntt_prefix.to_bytes () == INFO_PREFIX , EIncorrectPrefix );
46
+ let manager_address = external_address::take_bytes (cur);
47
+ let mode = mode::parse (bytes::take_bytes (cur, 1 ));
48
+ let token_address = external_address::take_bytes (cur);
49
+ let token_decimals = bytes::take_u8 (cur);
50
+
51
+ WormholeTransceiverInfo {
52
+ manager_address: manager_address,
53
+ manager_mode: mode,
54
+ token_address: token_address,
55
+ token_decimals: token_decimals
56
+ }
57
+ }
58
+
59
+ public fun parse (buf: vector <u8 >): WormholeTransceiverInfo {
60
+ let mut cur = cursor::new (buf);
61
+ let info = take_bytes (&mut cur);
62
+ cur.destroy_empty ();
63
+ info
64
+ }
65
+
66
+ #[test]
67
+ public fun test_round_trip () {
68
+ let reg = new (external_address::from_address (@102 ), mode::burning (), external_address::from_address (@304 ), 9 );
69
+
70
+ let reg_bytes = reg.to_bytes ();
71
+
72
+ let reg_round_trip = parse (reg_bytes);
73
+
74
+ assert !(reg.manager_address == reg_round_trip.manager_address);
75
+ assert !(reg.manager_mode == reg_round_trip.manager_mode);
76
+ assert !(reg.token_address == reg_round_trip.token_address);
77
+ assert !(reg.token_decimals == reg_round_trip.token_decimals);
78
+ }
79
+
80
+ #[test]
81
+ public fun test_raw_to_bytes () {
82
+ let mut raw_bytes = vector ::empty <u8 >();
83
+
84
+ let prefix = vector <u8 >[0x9c , 0x23 , 0xbd , 0x3b ];
85
+ let manager_address = vector <u8 >[0x1 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 ];
86
+ let mode = vector <u8 >[0x1 ];
87
+
88
+ let token_address = vector <u8 >[0x4 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x5 ];
89
+ let token_decimals = vector <u8 >[0x3 ];
90
+
91
+ vector ::append (&mut raw_bytes, prefix);
92
+ vector ::append (&mut raw_bytes, manager_address);
93
+ vector ::append (&mut raw_bytes, mode);
94
+ vector ::append (&mut raw_bytes, token_address);
95
+ vector ::append (&mut raw_bytes, token_decimals);
96
+
97
+
98
+ let reg = parse (raw_bytes);
99
+
100
+ assert !(reg.manager_address.to_bytes () == manager_address);
101
+ assert !(reg.manager_mode == mode::burning ());
102
+ assert !(reg.token_address.to_bytes () == token_address);
103
+ assert !(reg.token_decimals == 3 );
104
+ }
105
+
106
+ #[test]
107
+ public fun test_reg_to_raw_bytes (){
108
+ let mut raw_bytes = vector ::empty <u8 >();
109
+
110
+
111
+ let prefix = vector <u8 >[0x9c , 0x23 , 0xbd , 0x3b ];
112
+ let manager_address = vector <u8 >[0x1 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 ];
113
+ let mode = vector <u8 >[0x0 ];
114
+
115
+ let token_address = vector <u8 >[0x4 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x5 ];
116
+ let token_decimals = vector <u8 >[0x9 ];
117
+
118
+ vector ::append (&mut raw_bytes, prefix);
119
+ vector ::append (&mut raw_bytes, manager_address);
120
+ vector ::append (&mut raw_bytes, mode);
121
+ vector ::append (&mut raw_bytes, token_address);
122
+ vector ::append (&mut raw_bytes, token_decimals);
123
+
124
+ // Create value
125
+ let reg = new (external_address::from_address (@0x0100000000000000000000000000000000000000000000000000000000000002 ), mode::locking (), external_address::from_address (@0x0400000000000000000000000000000000000000000000000000000000000005 ), 9 );
126
+
127
+ assert !(reg.manager_address.to_bytes () == manager_address);
128
+ assert !(reg.manager_mode == mode::locking ());
129
+ assert !(reg.token_address.to_bytes () == token_address);
130
+ assert !(reg.token_decimals == 9 );
131
+
132
+ let derived = to_bytes (®);
133
+ assert !(derived == raw_bytes);
134
+ }
135
+
136
+ }
0 commit comments