2222use bitflags:: bitflags;
2323use codec:: { Decode , Encode } ;
2424use sp_core:: Bytes ;
25- use sp_runtime:: { DispatchError , RuntimeDebug } ;
25+ use sp_runtime:: { traits :: Zero , DispatchError , RuntimeDebug , traits :: Saturating } ;
2626use sp_std:: prelude:: * ;
2727
2828#[ cfg( feature = "std" ) ]
@@ -34,7 +34,7 @@ use serde::{Deserialize, Serialize};
3434#[ derive( Eq , PartialEq , Encode , Decode , RuntimeDebug ) ]
3535#[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
3636#[ cfg_attr( feature = "std" , serde( rename_all = "camelCase" ) ) ]
37- pub struct ContractResult < T > {
37+ pub struct ContractResult < R , Balance > {
3838 /// How much gas was consumed during execution.
3939 pub gas_consumed : u64 ,
4040 /// How much gas is required as gas limit in order to execute this call.
@@ -45,7 +45,14 @@ pub struct ContractResult<T> {
4545 ///
4646 /// This can only different from [`Self::gas_consumed`] when weight pre charging
4747 /// is used. Currently, only `seal_call_runtime` makes use of pre charging.
48+ /// Additionally, any `seal_call` or `seal_instantiate` makes use of pre-charging
49+ /// when a non-zero `gas_limit` argument is supplied.
4850 pub gas_required : u64 ,
51+ /// How much balance was deposited and reserved during execution in order to pay for storage.
52+ ///
53+ /// The storage deposit is never actually charged from the caller in case of [`Self::result`]
54+ /// is `Err`. This is because on error all storage changes are rolled back.
55+ pub storage_deposit : StorageDeposit < Balance > ,
4956 /// An optional debug message. This message is only filled when explicitly requested
5057 /// by the code that calls into the contract. Otherwise it is empty.
5158 ///
@@ -63,15 +70,20 @@ pub struct ContractResult<T> {
6370 #[ cfg_attr( feature = "std" , serde( with = "as_string" ) ) ]
6471 pub debug_message : Vec < u8 > ,
6572 /// The execution result of the wasm code.
66- pub result : T ,
73+ pub result : R ,
6774}
6875
6976/// Result type of a `bare_call` call.
70- pub type ContractExecResult = ContractResult < Result < ExecReturnValue , DispatchError > > ;
77+ pub type ContractExecResult < Balance > =
78+ ContractResult < Result < ExecReturnValue , DispatchError > , Balance > ;
7179
7280/// Result type of a `bare_instantiate` call.
73- pub type ContractInstantiateResult < AccountId > =
74- ContractResult < Result < InstantiateReturnValue < AccountId > , DispatchError > > ;
81+ pub type ContractInstantiateResult < AccountId , Balance > =
82+ ContractResult < Result < InstantiateReturnValue < AccountId > , DispatchError > , Balance > ;
83+
84+ /// Result type of a `bare_code_upload` call.
85+ pub type CodeUploadResult < CodeHash , Balance > =
86+ Result < CodeUploadReturnValue < CodeHash , Balance > , DispatchError > ;
7587
7688/// Result type of a `get_storage` call.
7789pub type GetStorageResult = Result < Option < Vec < u8 > > , ContractAccessError > ;
@@ -123,6 +135,17 @@ pub struct InstantiateReturnValue<AccountId> {
123135 pub account_id : AccountId ,
124136}
125137
138+ /// The result of succesfully uploading a contract.
139+ #[ derive( PartialEq , Eq , Encode , Decode , RuntimeDebug ) ]
140+ #[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
141+ #[ cfg_attr( feature = "std" , serde( rename_all = "camelCase" ) ) ]
142+ pub struct CodeUploadReturnValue < CodeHash , Balance > {
143+ /// The key under which the new code is stored.
144+ pub code_hash : CodeHash ,
145+ /// The deposit that was reserved at the caller. Is zero when the code already existed.
146+ pub deposit : Balance ,
147+ }
148+
126149/// Reference to an existing code hash or a new wasm module.
127150#[ derive( Eq , PartialEq , Encode , Decode , RuntimeDebug ) ]
128151#[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
@@ -134,6 +157,96 @@ pub enum Code<Hash> {
134157 Existing ( Hash ) ,
135158}
136159
160+ /// The amount of balance that was either charged or refunded in order to pay for storage.
161+ #[ derive( Eq , PartialEq , Encode , Decode , RuntimeDebug , Clone ) ]
162+ #[ cfg_attr( feature = "std" , derive( Serialize , Deserialize ) ) ]
163+ #[ cfg_attr( feature = "std" , serde( rename_all = "camelCase" ) ) ]
164+ pub enum StorageDeposit < Balance > {
165+ /// The transaction increased overall storage usage.
166+ ///
167+ /// This means that the specified amount of balance was transferred from the call origin
168+ /// to the contracts involved.
169+ Charge ( Balance ) ,
170+ /// The transaction reduced storage consumption.
171+ ///
172+ /// This means that the specified amount of balance was transferred from the involved
173+ /// contracts to the call origin.
174+ Refund ( Balance ) ,
175+ }
176+
177+ impl < Balance : Zero > Default for StorageDeposit < Balance > {
178+ fn default ( ) -> Self {
179+ Self :: Charge ( Zero :: zero ( ) )
180+ }
181+ }
182+
183+ impl < Balance : Zero > StorageDeposit < Balance > {
184+ /// Returns how much balance is charged or `0` in case of a refund.
185+ pub fn charge_or_zero ( self ) -> Balance {
186+ match self {
187+ Self :: Charge ( amount) => amount,
188+ Self :: Refund ( _) => Zero :: zero ( ) ,
189+ }
190+ }
191+ }
192+
193+ impl < Balance > StorageDeposit < Balance >
194+ where
195+ Balance : Saturating + Ord + Copy
196+ {
197+ /// This is essentially a saturating signed add.
198+ pub fn saturating_add ( & self , rhs : & Self ) -> Self {
199+ use StorageDeposit :: * ;
200+ match ( self , rhs) {
201+ ( Charge ( lhs) , Charge ( rhs) ) => Charge ( lhs. saturating_add ( * rhs) ) ,
202+ ( Refund ( lhs) , Refund ( rhs) ) => Refund ( lhs. saturating_add ( * rhs) ) ,
203+ ( Charge ( lhs) , Refund ( rhs) ) => if lhs >= rhs {
204+ Charge ( lhs. saturating_sub ( * rhs) )
205+ } else {
206+ Refund ( rhs. saturating_sub ( * lhs) )
207+ } ,
208+ ( Refund ( lhs) , Charge ( rhs) ) => if lhs > rhs {
209+ Refund ( lhs. saturating_sub ( * rhs) )
210+ } else {
211+ Charge ( rhs. saturating_sub ( * lhs) )
212+ } ,
213+ }
214+ }
215+
216+ /// This is essentially a saturating signed sub.
217+ pub fn saturating_sub ( & self , rhs : & Self ) -> Self {
218+ use StorageDeposit :: * ;
219+ match ( self , rhs) {
220+ ( Charge ( lhs) , Refund ( rhs) ) => Charge ( lhs. saturating_add ( * rhs) ) ,
221+ ( Refund ( lhs) , Charge ( rhs) ) => Refund ( lhs. saturating_add ( * rhs) ) ,
222+ ( Charge ( lhs) , Charge ( rhs) ) => if lhs >= rhs {
223+ Charge ( lhs. saturating_sub ( * rhs) )
224+ } else {
225+ Refund ( rhs. saturating_sub ( * lhs) )
226+ } ,
227+ ( Refund ( lhs) , Refund ( rhs) ) => if lhs > rhs {
228+ Refund ( lhs. saturating_sub ( * rhs) )
229+ } else {
230+ Charge ( rhs. saturating_sub ( * lhs) )
231+ } ,
232+ }
233+ }
234+
235+ /// If the amount of deposit (this type) is constrained by a `limit` this calcuates how
236+ /// much balance (if any) is still available from this limit.
237+ ///
238+ /// # Note
239+ ///
240+ /// In case of a refund the return value can be larger than `limit`.
241+ pub fn available ( & self , limit : & Balance ) -> Balance {
242+ use StorageDeposit :: * ;
243+ match self {
244+ Charge ( amount) => limit. saturating_sub ( * amount) ,
245+ Refund ( amount) => limit. saturating_add ( * amount) ,
246+ }
247+ }
248+ }
249+
137250#[ cfg( feature = "std" ) ]
138251mod as_string {
139252 use super :: * ;
0 commit comments