7575//! allowed to code owner.
7676//! * [`Pallet::set_code`] - Changes the code of an existing contract. Only allowed to `Root`
7777//! origin.
78- //! * [`Pallet::migrate`] - Runs migration steps of curent multi-block migration in priority, before
79- //! [`Hooks::on_idle`][frame_support::traits::Hooks::on_idle] activates.
78+ //! * [`Pallet::migrate`] - Runs migration steps of current multi-block migration in priority,
79+ //! before [`Hooks::on_idle`][frame_support::traits::Hooks::on_idle] activates.
8080//!
8181//! ## Usage
8282//!
@@ -105,7 +105,7 @@ use crate::{
105105 exec:: { AccountIdOf , ErrorOrigin , ExecError , Executable , Key , Stack as ExecStack } ,
106106 gas:: GasMeter ,
107107 storage:: { meter:: Meter as StorageMeter , ContractInfo , DeletionQueueManager } ,
108- wasm:: { CodeInfo , TryInstantiate , WasmBlob } ,
108+ wasm:: { CodeInfo , WasmBlob } ,
109109} ;
110110use codec:: { Codec , Decode , Encode , HasCompact } ;
111111use environmental:: * ;
@@ -695,24 +695,40 @@ pub mod pallet {
695695 salt : Vec < u8 > ,
696696 ) -> DispatchResultWithPostInfo {
697697 Migration :: < T > :: ensure_migrated ( ) ?;
698+ let origin = ensure_signed ( origin) ?;
698699 let code_len = code. len ( ) as u32 ;
700+
701+ let ( module, upload_deposit) = Self :: try_upload_code (
702+ origin. clone ( ) ,
703+ code,
704+ storage_deposit_limit. clone ( ) . map ( Into :: into) ,
705+ Determinism :: Enforced ,
706+ None ,
707+ ) ?;
708+
709+ // Reduces the storage deposit limit by the amount that was reserved for the upload.
710+ let storage_deposit_limit =
711+ storage_deposit_limit. map ( |limit| limit. into ( ) . saturating_sub ( upload_deposit) ) ;
712+
699713 let data_len = data. len ( ) as u32 ;
700714 let salt_len = salt. len ( ) as u32 ;
701715 let common = CommonInput {
702- origin : Origin :: from_runtime_origin ( origin) ? ,
716+ origin : Origin :: from_account_id ( origin) ,
703717 value,
704718 data,
705719 gas_limit,
706- storage_deposit_limit : storage_deposit_limit . map ( Into :: into ) ,
720+ storage_deposit_limit,
707721 debug_message : None ,
708722 } ;
723+
709724 let mut output =
710- InstantiateInput :: < T > { code : Code :: Upload ( code ) , salt } . run_guarded ( common) ;
725+ InstantiateInput :: < T > { code : WasmCode :: Wasm ( module ) , salt } . run_guarded ( common) ;
711726 if let Ok ( retval) = & output. result {
712727 if retval. 1 . did_revert ( ) {
713728 output. result = Err ( <Error < T > >:: ContractReverted . into ( ) ) ;
714729 }
715730 }
731+
716732 output. gas_meter . into_dispatch_result (
717733 output. result . map ( |( _address, result) | result) ,
718734 T :: WeightInfo :: instantiate_with_code ( code_len, data_len, salt_len) ,
@@ -748,8 +764,8 @@ pub mod pallet {
748764 storage_deposit_limit : storage_deposit_limit. map ( Into :: into) ,
749765 debug_message : None ,
750766 } ;
751- let mut output =
752- InstantiateInput :: < T > { code : Code :: Existing ( code_hash ) , salt } . run_guarded ( common) ;
767+ let mut output = InstantiateInput :: < T > { code : WasmCode :: CodeHash ( code_hash ) , salt }
768+ . run_guarded ( common) ;
753769 if let Ok ( retval) = & output. result {
754770 if retval. 1 . did_revert ( ) {
755771 output. result = Err ( <Error < T > >:: ContractReverted . into ( ) ) ;
@@ -1052,9 +1068,15 @@ struct CallInput<T: Config> {
10521068 determinism : Determinism ,
10531069}
10541070
1071+ /// Reference to an existing code hash or a new wasm module.
1072+ enum WasmCode < T : Config > {
1073+ Wasm ( WasmBlob < T > ) ,
1074+ CodeHash ( CodeHash < T > ) ,
1075+ }
1076+
10551077/// Input specific to a contract instantiation invocation.
10561078struct InstantiateInput < T : Config > {
1057- code : Code < CodeHash < T > > ,
1079+ code : WasmCode < T > ,
10581080 salt : Vec < u8 > ,
10591081}
10601082
@@ -1099,7 +1121,7 @@ struct InternalOutput<T: Config, O> {
10991121
11001122/// Helper trait to wrap contract execution entry points into a single function
11011123/// [`Invokable::run_guarded`].
1102- trait Invokable < T : Config > {
1124+ trait Invokable < T : Config > : Sized {
11031125 /// What is returned as a result of a successful invocation.
11041126 type Output ;
11051127
@@ -1111,7 +1133,7 @@ trait Invokable<T: Config> {
11111133 ///
11121134 /// We enforce a re-entrancy guard here by initializing and checking a boolean flag through a
11131135 /// global reference.
1114- fn run_guarded ( & self , common : CommonInput < T > ) -> InternalOutput < T , Self :: Output > {
1136+ fn run_guarded ( self , common : CommonInput < T > ) -> InternalOutput < T , Self :: Output > {
11151137 // Set up a global reference to the boolean flag used for the re-entrancy guard.
11161138 environmental ! ( executing_contract: bool ) ;
11171139
@@ -1159,11 +1181,8 @@ trait Invokable<T: Config> {
11591181 /// contract or a instantiation of a new one.
11601182 ///
11611183 /// Called by dispatchables and public functions through the [`Invokable::run_guarded`].
1162- fn run (
1163- & self ,
1164- common : CommonInput < T > ,
1165- gas_meter : GasMeter < T > ,
1166- ) -> InternalOutput < T , Self :: Output > ;
1184+ fn run ( self , common : CommonInput < T > , gas_meter : GasMeter < T > )
1185+ -> InternalOutput < T , Self :: Output > ;
11671186
11681187 /// This method ensures that the given `origin` is allowed to invoke the current `Invokable`.
11691188 ///
@@ -1175,7 +1194,7 @@ impl<T: Config> Invokable<T> for CallInput<T> {
11751194 type Output = ExecReturnValue ;
11761195
11771196 fn run (
1178- & self ,
1197+ self ,
11791198 common : CommonInput < T > ,
11801199 mut gas_meter : GasMeter < T > ,
11811200 ) -> InternalOutput < T , Self :: Output > {
@@ -1201,7 +1220,7 @@ impl<T: Config> Invokable<T> for CallInput<T> {
12011220 value,
12021221 data. clone ( ) ,
12031222 debug_message,
1204- * determinism,
1223+ determinism,
12051224 ) ;
12061225
12071226 match storage_meter. try_into_deposit ( & origin) {
@@ -1223,8 +1242,8 @@ impl<T: Config> Invokable<T> for InstantiateInput<T> {
12231242 type Output = ( AccountIdOf < T > , ExecReturnValue ) ;
12241243
12251244 fn run (
1226- & self ,
1227- mut common : CommonInput < T > ,
1245+ self ,
1246+ common : CommonInput < T > ,
12281247 mut gas_meter : GasMeter < T > ,
12291248 ) -> InternalOutput < T , Self :: Output > {
12301249 let mut storage_deposit = Default :: default ( ) ;
@@ -1233,37 +1252,15 @@ impl<T: Config> Invokable<T> for InstantiateInput<T> {
12331252 let InstantiateInput { salt, .. } = self ;
12341253 let CommonInput { origin : contract_origin, .. } = common;
12351254 let origin = contract_origin. account_id ( ) ?;
1236- let ( extra_deposit, executable) = match & self . code {
1237- Code :: Upload ( binary) => {
1238- let executable = WasmBlob :: from_code (
1239- binary. clone ( ) ,
1240- & schedule,
1241- origin. clone ( ) ,
1242- Determinism :: Enforced ,
1243- TryInstantiate :: Skip ,
1244- )
1245- . map_err ( |( err, msg) | {
1246- common
1247- . debug_message
1248- . as_mut ( )
1249- . map ( |buffer| buffer. try_extend ( & mut msg. bytes ( ) ) ) ;
1250- err
1251- } ) ?;
1252- // The open deposit will be charged during execution when the
1253- // uploaded module does not already exist. This deposit is not part of the
1254- // storage meter because it is not transferred to the contract but
1255- // reserved on the uploading account.
1256- ( executable. open_deposit ( & executable. code_info ( ) ) , executable)
1257- } ,
1258- Code :: Existing ( hash) =>
1259- ( Default :: default ( ) , WasmBlob :: from_storage ( * hash, & mut gas_meter) ?) ,
1255+
1256+ let executable = match self . code {
1257+ WasmCode :: Wasm ( module) => module,
1258+ WasmCode :: CodeHash ( code_hash) => WasmBlob :: from_storage ( code_hash, & mut gas_meter) ?,
12601259 } ;
1260+
12611261 let contract_origin = Origin :: from_account_id ( origin. clone ( ) ) ;
1262- let mut storage_meter = StorageMeter :: new (
1263- & contract_origin,
1264- common. storage_deposit_limit ,
1265- common. value . saturating_add ( extra_deposit) ,
1266- ) ?;
1262+ let mut storage_meter =
1263+ StorageMeter :: new ( & contract_origin, common. storage_deposit_limit , common. value ) ?;
12671264 let CommonInput { value, data, debug_message, .. } = common;
12681265 let result = ExecStack :: < T , WasmBlob < T > > :: run_instantiate (
12691266 origin. clone ( ) ,
@@ -1277,9 +1274,7 @@ impl<T: Config> Invokable<T> for InstantiateInput<T> {
12771274 debug_message,
12781275 ) ;
12791276
1280- storage_deposit = storage_meter
1281- . try_into_deposit ( & contract_origin) ?
1282- . saturating_add ( & StorageDeposit :: Charge ( extra_deposit) ) ;
1277+ storage_deposit = storage_meter. try_into_deposit ( & contract_origin) ?;
12831278 result
12841279 } ;
12851280 InternalOutput { result : try_exec ( ) , gas_meter, storage_deposit }
@@ -1383,7 +1378,7 @@ impl<T: Config> Pallet<T> {
13831378 origin : T :: AccountId ,
13841379 value : BalanceOf < T > ,
13851380 gas_limit : Weight ,
1386- storage_deposit_limit : Option < BalanceOf < T > > ,
1381+ mut storage_deposit_limit : Option < BalanceOf < T > > ,
13871382 code : Code < CodeHash < T > > ,
13881383 data : Vec < u8 > ,
13891384 salt : Vec < u8 > ,
@@ -1397,6 +1392,45 @@ impl<T: Config> Pallet<T> {
13971392 } else {
13981393 None
13991394 } ;
1395+ // collect events if CollectEvents is UnsafeCollect
1396+ let events = || {
1397+ if collect_events == CollectEvents :: UnsafeCollect {
1398+ Some ( System :: < T > :: read_events_no_consensus ( ) . map ( |e| * e) . collect ( ) )
1399+ } else {
1400+ None
1401+ }
1402+ } ;
1403+
1404+ let ( code, upload_deposit) : ( WasmCode < T > , BalanceOf < T > ) = match code {
1405+ Code :: Upload ( code) => {
1406+ let result = Self :: try_upload_code (
1407+ origin. clone ( ) ,
1408+ code,
1409+ storage_deposit_limit. map ( Into :: into) ,
1410+ Determinism :: Enforced ,
1411+ debug_message. as_mut ( ) ,
1412+ ) ;
1413+
1414+ let ( module, deposit) = match result {
1415+ Ok ( result) => result,
1416+ Err ( error) =>
1417+ return ContractResult {
1418+ gas_consumed : Zero :: zero ( ) ,
1419+ gas_required : Zero :: zero ( ) ,
1420+ storage_deposit : Default :: default ( ) ,
1421+ debug_message : debug_message. unwrap_or ( Default :: default ( ) ) . into ( ) ,
1422+ result : Err ( error) ,
1423+ events : events ( ) ,
1424+ } ,
1425+ } ;
1426+
1427+ storage_deposit_limit =
1428+ storage_deposit_limit. map ( |l| l. saturating_sub ( deposit. into ( ) ) ) ;
1429+ ( WasmCode :: Wasm ( module) , deposit)
1430+ } ,
1431+ Code :: Existing ( hash) => ( WasmCode :: CodeHash ( hash) , Default :: default ( ) ) ,
1432+ } ;
1433+
14001434 let common = CommonInput {
14011435 origin : Origin :: from_account_id ( origin) ,
14021436 value,
@@ -1405,23 +1439,20 @@ impl<T: Config> Pallet<T> {
14051439 storage_deposit_limit,
14061440 debug_message : debug_message. as_mut ( ) ,
14071441 } ;
1442+
14081443 let output = InstantiateInput :: < T > { code, salt } . run_guarded ( common) ;
1409- // collect events if CollectEvents is UnsafeCollect
1410- let events = if collect_events == CollectEvents :: UnsafeCollect {
1411- Some ( System :: < T > :: read_events_no_consensus ( ) . map ( |e| * e) . collect ( ) )
1412- } else {
1413- None
1414- } ;
14151444 ContractInstantiateResult {
14161445 result : output
14171446 . result
14181447 . map ( |( account_id, result) | InstantiateReturnValue { result, account_id } )
14191448 . map_err ( |e| e. error ) ,
14201449 gas_consumed : output. gas_meter . gas_consumed ( ) ,
14211450 gas_required : output. gas_meter . gas_required ( ) ,
1422- storage_deposit : output. storage_deposit ,
1451+ storage_deposit : output
1452+ . storage_deposit
1453+ . saturating_add ( & StorageDeposit :: Charge ( upload_deposit) ) ,
14231454 debug_message : debug_message. unwrap_or_default ( ) . to_vec ( ) ,
1424- events,
1455+ events : events ( ) ,
14251456 }
14261457 }
14271458
@@ -1436,17 +1467,31 @@ impl<T: Config> Pallet<T> {
14361467 determinism : Determinism ,
14371468 ) -> CodeUploadResult < CodeHash < T > , BalanceOf < T > > {
14381469 Migration :: < T > :: ensure_migrated ( ) ?;
1470+ let ( module, deposit) =
1471+ Self :: try_upload_code ( origin, code, storage_deposit_limit, determinism, None ) ?;
1472+ Ok ( CodeUploadReturnValue { code_hash : * module. code_hash ( ) , deposit } )
1473+ }
1474+
1475+ /// Uploads new code and returns the Wasm blob and deposit amount collected.
1476+ fn try_upload_code (
1477+ origin : T :: AccountId ,
1478+ code : Vec < u8 > ,
1479+ storage_deposit_limit : Option < BalanceOf < T > > ,
1480+ determinism : Determinism ,
1481+ mut debug_message : Option < & mut DebugBufferVec < T > > ,
1482+ ) -> Result < ( WasmBlob < T > , BalanceOf < T > ) , DispatchError > {
14391483 let schedule = T :: Schedule :: get ( ) ;
1440- let module =
1441- WasmBlob :: from_code ( code, & schedule, origin, determinism, TryInstantiate :: Instantiate )
1442- . map_err ( |( err, _) | err) ?;
1443- let deposit = module. open_deposit ( & module. code_info ( ) ) ;
1484+ let mut module =
1485+ WasmBlob :: from_code ( code, & schedule, origin, determinism) . map_err ( |( err, msg) | {
1486+ debug_message. as_mut ( ) . map ( |d| d. try_extend ( msg. bytes ( ) ) ) ;
1487+ err
1488+ } ) ?;
1489+ let deposit = module. store_code ( ) ?;
14441490 if let Some ( storage_deposit_limit) = storage_deposit_limit {
14451491 ensure ! ( storage_deposit_limit >= deposit, <Error <T >>:: StorageDepositLimitExhausted ) ;
14461492 }
1447- let result = CodeUploadReturnValue { code_hash : * module. code_hash ( ) , deposit } ;
1448- module. store ( ) ?;
1449- Ok ( result)
1493+
1494+ Ok ( ( module, deposit) )
14501495 }
14511496
14521497 /// Query storage of a specified contract under a specified key.
@@ -1490,7 +1535,7 @@ impl<T: Config> Pallet<T> {
14901535 owner : T :: AccountId ,
14911536 ) -> frame_support:: dispatch:: DispatchResult {
14921537 let schedule = T :: Schedule :: get ( ) ;
1493- WasmBlob :: store_code_unchecked ( code, & schedule, owner) ?;
1538+ WasmBlob :: < T > :: from_code_unchecked ( code, & schedule, owner) ? . store_code ( ) ?;
14941539 Ok ( ( ) )
14951540 }
14961541
0 commit comments