1use crate::transaction::MultiAddress;
2use alloc::vec::Vec;
3use scale::{Compact, Decode, Encode};
4
5pub(crate) fn build_contract_call<AccountId, AccountIndex, Balance, ARGS: Encode>(
6 contract_id: AccountId,
7 contract_method: [u8; 4],
8 contract_args: Option<&ARGS>,
9 value: Balance,
10 gas_limit: WeightV2,
11) -> ContractCall<AccountId, AccountIndex, Balance> {
12 let storage_deposit_limit = None;
13
14 let mut data = Vec::new();
15 contract_method.encode_to(&mut data);
16 if let Some(args) = contract_args {
17 let mut encoded_contract_args = args.encode();
18 data.append(&mut encoded_contract_args);
19 }
20
21 ContractCall {
22 dest: MultiAddress::Id(contract_id),
23 value,
24 gas_limit,
25 storage_deposit_limit,
26 data,
27 }
28}
29
30pub(crate) fn build_contract_query<AccountId, Balance, ARGS: Encode>(
31 origin: AccountId,
32 contract_id: AccountId,
33 contract_method: [u8; 4],
34 contract_args: Option<&ARGS>,
35 value: Balance,
36) -> ContractQuery<AccountId, Balance> {
37 let mut data = Vec::new();
38 contract_method.encode_to(&mut data);
39 if let Some(args) = contract_args {
40 let mut encoded_contract_args = args.encode();
41 data.append(&mut encoded_contract_args);
42 }
43
44 ContractQuery {
45 origin,
46 dest: contract_id,
47 value,
48 gas_limit: None,
49 storage_deposit_limit: None,
50 data,
51 }
52}
53
54#[derive(Encode, Decode, PartialEq, Eq, Clone, Debug)]
56#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
57pub(crate) struct ContractCall<AccountId, AccountIndex, Balance> {
58 dest: MultiAddress<AccountId, AccountIndex>,
60 #[codec(compact)]
62 value: Balance,
63 gas_limit: WeightV2,
65 storage_deposit_limit: Option<Compact<Balance>>,
68 data: Vec<u8>,
70}
71
72#[derive(Encode, Decode, PartialEq, Eq, Clone, Copy, Debug)]
74#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
75pub struct WeightV2 {
76 #[codec(compact)]
77 pub ref_time: u64,
78 #[codec(compact)]
79 pub proof_size: u64,
80}
81
82#[derive(Encode, Decode, PartialEq, Eq, Clone, Debug)]
84#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
85pub(crate) struct ContractQuery<AccountId, Balance> {
86 origin: AccountId,
87 dest: AccountId,
88 value: Balance,
89 gas_limit: Option<WeightV2>,
90 storage_deposit_limit: Option<Balance>,
91 data: Vec<u8>,
92}
93
94#[derive(Encode, Decode, Clone, Debug)]
96#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
97pub struct ContractQueryResult<Error, Balance> {
98 pub(crate) gas_consumed: WeightV2,
99 pub(crate) gas_required: WeightV2,
100 pub(crate) storage_deposit: StorageDeposit<Balance>,
101 pub(crate) debug_message: Vec<u8>,
102 pub(crate) result: ExecReturnValue<Error>,
103}
104
105#[derive(Encode, Decode, Clone, Debug)]
106#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
107pub(crate) struct ExecReturnValue<Error> {
108 pub(crate) flags: u32,
109 pub(crate) data: Result<Vec<u8>, Error>,
110}
111
112#[derive(Encode, Decode, PartialEq, Eq, Clone, Debug)]
113#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
114pub(crate) enum StorageDeposit<Balance> {
115 Refund(Balance),
116 Charge(Balance),
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_encode_contract_call() {
125 let contract_id: [u8; 32] =
126 hex_literal::hex!("f77bfd16d61d39dcd8c4413ac88642354f5726bb5915bf52bc4f502a671f1aa5");
127 let contract_method = hex_literal::hex!("1d32619f");
128 let contract_args = Some(&2i32);
129
130 let call: ContractCall<[u8; 32], u32, u128> = build_contract_call(
131 contract_id,
132 contract_method,
133 contract_args,
134 0u128,
135 WeightV2 {
136 ref_time: 3991666688u64,
137 proof_size: 131072u64,
138 },
139 );
140
141 let encoded_call = Encode::encode(&call);
142 let expected = hex_literal::hex!("00f77bfd16d61d39dcd8c4413ac88642354f5726bb5915bf52bc4f502a671f1aa500030000eced0200080000201d32619f02000000");
143 assert_eq!(&expected, encoded_call.as_slice());
144 }
145
146 #[test]
147 fn test_encode_contract_query() {
148 let origin: [u8; 32] =
149 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d");
150 let contract_id: [u8; 32] =
151 hex_literal::hex!("f77bfd16d61d39dcd8c4413ac88642354f5726bb5915bf52bc4f502a671f1aa5");
152 let contract_method = hex_literal::hex!("2f865bd9");
153 let contract_args: Option<&()> = None; let call = build_contract_query(origin, contract_id, contract_method, contract_args, 0u128);
156
157 let encoded_call = Encode::encode(&call);
158 let expected = hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27df77bfd16d61d39dcd8c4413ac88642354f5726bb5915bf52bc4f502a671f1aa5000000000000000000000000000000000000102f865bd9");
159 assert_eq!(&expected, encoded_call.as_slice());
160 }
161
162 #[derive(Decode, Debug)]
164 enum Error {
165 Error1,
166 Error2,
167 }
168
169 #[test]
170 fn test_decode_contract_query_result() {
171 let result = hex_literal::hex!("d6b2469e3a3d0100030000eced020008000100000000000000000000000000000000000000000000140003000000");
172
173 let contract_query_result =
174 <ContractQueryResult<Error, u128>>::decode(&mut result.as_slice()).unwrap();
175
176 assert_eq!(663858357u64, contract_query_result.gas_consumed.ref_time);
177 assert_eq!(20302u64, contract_query_result.gas_consumed.proof_size);
178 assert_eq!(3991666688u64, contract_query_result.gas_required.ref_time);
179 assert_eq!(131072u64, contract_query_result.gas_required.proof_size);
180 assert_eq!(
181 StorageDeposit::Charge(0),
182 contract_query_result.storage_deposit
183 );
184 assert_eq!(0u32, contract_query_result.result.flags);
185 assert!(contract_query_result.result.data.is_ok());
186 let result = contract_query_result.result.data.unwrap();
187 let data = <Result<i32, Error>>::decode(&mut result.as_slice()).unwrap();
188
189 assert!(data.is_ok());
190 assert_eq!(3i32, data.unwrap());
191 }
192}