1818use crate :: {
1919 gas:: GasMeter ,
2020 storage:: { self , DepositAccount , WriteOutcome } ,
21+ wasm:: { decrement_refcount, increment_refcount} ,
2122 BalanceOf , CodeHash , Config , ContractInfo , ContractInfoOf , DebugBufferVec , Determinism , Error ,
22- Event , Nonce , Origin , Pallet as Contracts , Schedule , System , LOG_TARGET ,
23+ Event , Nonce , Origin , OwnerInfoOf , Pallet as Contracts , Schedule , System , LOG_TARGET ,
2324} ;
2425use frame_support:: {
2526 crypto:: ecdsa:: ECDSAExt ,
@@ -35,14 +36,17 @@ use frame_support::{
3536 Blake2_128Concat , BoundedVec , StorageHasher ,
3637} ;
3738use frame_system:: RawOrigin ;
38- use pallet_contracts_primitives:: ExecReturnValue ;
39+ use pallet_contracts_primitives:: { ExecReturnValue , StorageDeposit } ;
3940use smallvec:: { Array , SmallVec } ;
4041use sp_core:: {
4142 ecdsa:: Public as ECDSAPublic ,
4243 sr25519:: { Public as SR25519Public , Signature as SR25519Signature } ,
4344} ;
4445use sp_io:: { crypto:: secp256k1_ecdsa_recover_compressed, hashing:: blake2_256} ;
45- use sp_runtime:: traits:: { Convert , Hash , Zero } ;
46+ use sp_runtime:: {
47+ traits:: { Convert , Hash , Zero } ,
48+ Perbill ,
49+ } ;
4650use sp_std:: { marker:: PhantomData , mem, prelude:: * , vec:: Vec } ;
4751
4852pub type AccountIdOf < T > = <T as frame_system:: Config >:: AccountId ;
@@ -306,6 +310,22 @@ pub trait Ext: sealing::Sealed {
306310
307311 /// Returns a nonce that is incremented for every instantiated contract.
308312 fn nonce ( & mut self ) -> u64 ;
313+
314+ /// Add a contract dependency, This is useful for contract delegation, to make sure that the
315+ /// delegated contract is not removed while it is still in use.
316+ /// This will increase the reference count of the code hash, and charge a deposit of 30% of the
317+ /// code deposit.
318+ ///
319+ /// Returns an error if we have reached the maximum number of dependencies, or the dependency
320+ /// already exists.
321+ fn add_dependency ( & mut self , _code : CodeHash < Self :: T > ) -> Result < ( ) , DispatchError > ;
322+
323+ /// Remove a contract dependency.
324+ /// This is the counterpart of `add_dependency`. This method will decrease the reference count
325+ /// And refund the deposit that was charged by `add_dependency`.
326+ ///
327+ /// Returns an error if the dependency does not exist.
328+ fn remove_dependency ( & mut self , _code : CodeHash < Self :: T > ) -> Result < ( ) , DispatchError > ;
309329}
310330
311331/// Describes the different functions that can be exported by an [`Executable`].
@@ -1461,6 +1481,30 @@ where
14611481 current
14621482 }
14631483 }
1484+ fn add_dependency ( & mut self , code_hash : CodeHash < Self :: T > ) -> Result < ( ) , DispatchError > {
1485+ let frame = self . top_frame_mut ( ) ;
1486+ let info = frame. contract_info . get ( & frame. account_id ) ;
1487+
1488+ increment_refcount :: < T > ( code_hash) ?;
1489+ let owner_info = OwnerInfoOf :: < T > :: get ( code_hash) . ok_or ( Error :: < T > :: ContractNotFound ) ?;
1490+ let deposit = Perbill :: from_percent ( 30 ) . mul_ceil ( owner_info. deposit ( ) ) ;
1491+
1492+ frame
1493+ . nested_storage
1494+ . charge_dependency ( info. deposit_account ( ) , & StorageDeposit :: Charge ( deposit) ) ;
1495+ info. add_dependency ( code_hash, deposit)
1496+ }
1497+
1498+ fn remove_dependency ( & mut self , code_hash : CodeHash < Self :: T > ) -> Result < ( ) , DispatchError > {
1499+ let frame = self . top_frame_mut ( ) ;
1500+ let info = frame. contract_info . get ( & frame. account_id ) ;
1501+ let deposit = info. remove_dependency ( code_hash) ?;
1502+ decrement_refcount :: < T > ( code_hash) ;
1503+ frame
1504+ . nested_storage
1505+ . charge_dependency ( info. deposit_account ( ) , & StorageDeposit :: Refund ( deposit) ) ;
1506+ Ok ( ( ) )
1507+ }
14641508}
14651509
14661510mod sealing {
0 commit comments