git.delta.rocks / unique-network / refs/commits / 89d693c101e5

difftreelog

NFTPAR-47 + contracts module

str-mv2020-07-02parent: #4ccb943.patch.diff
in: master

9 files changed

modifiedCargo.lockdiffbeforeafterboth
2762version = "2.0.0-rc4"2762version = "2.0.0-rc4"
2763dependencies = [2763dependencies = [
2764 "futures 0.3.5",2764 "futures 0.3.5",
2765 "jsonrpc-core",
2765 "log",2766 "log",
2766 "nft-runtime",2767 "nft-runtime",
2768 "pallet-contracts-rpc",
2767 "parking_lot 0.10.2",2769 "parking_lot 0.10.2",
2768 "sc-basic-authorship",2770 "sc-basic-authorship",
2769 "sc-cli",2771 "sc-cli",
2773 "sc-executor",2775 "sc-executor",
2774 "sc-finality-grandpa",2776 "sc-finality-grandpa",
2775 "sc-network",2777 "sc-network",
2778 "sc-rpc",
2776 "sc-service",2779 "sc-service",
2777 "sc-transaction-pool",2780 "sc-transaction-pool",
2778 "sp-consensus",2781 "sp-consensus",
2795 "frame-system",2798 "frame-system",
2796 "pallet-aura",2799 "pallet-aura",
2797 "pallet-balances",2800 "pallet-balances",
2801 "pallet-contracts",
2802 "pallet-contracts-primitives",
2803 "pallet-contracts-rpc-runtime-api",
2798 "pallet-grandpa",2804 "pallet-grandpa",
2799 "pallet-nft",2805 "pallet-nft",
2800 "pallet-randomness-collective-flip",2806 "pallet-randomness-collective-flip",
3012 "sp-std",3018 "sp-std",
3013]3019]
3020
3021[[package]]
3022name = "pallet-contracts"
3023version = "2.0.0-rc4"
3024source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
3025dependencies = [
3026 "frame-support",
3027 "frame-system",
3028 "pallet-contracts-primitives",
3029 "parity-scale-codec",
3030 "parity-wasm",
3031 "pwasm-utils",
3032 "serde",
3033 "sp-core",
3034 "sp-io",
3035 "sp-runtime",
3036 "sp-sandbox",
3037 "sp-std",
3038 "wasmi-validation",
3039]
3040
3041[[package]]
3042name = "pallet-contracts-primitives"
3043version = "2.0.0-rc4"
3044source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
3045dependencies = [
3046 "parity-scale-codec",
3047 "sp-runtime",
3048 "sp-std",
3049]
3050
3051[[package]]
3052name = "pallet-contracts-rpc"
3053version = "0.8.0-rc4"
3054source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
3055dependencies = [
3056 "jsonrpc-core",
3057 "jsonrpc-core-client",
3058 "jsonrpc-derive",
3059 "pallet-contracts-primitives",
3060 "pallet-contracts-rpc-runtime-api",
3061 "parity-scale-codec",
3062 "serde",
3063 "sp-api",
3064 "sp-blockchain",
3065 "sp-core",
3066 "sp-rpc",
3067 "sp-runtime",
3068]
3069
3070[[package]]
3071name = "pallet-contracts-rpc-runtime-api"
3072version = "0.8.0-rc4"
3073source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
3074dependencies = [
3075 "pallet-contracts-primitives",
3076 "parity-scale-codec",
3077 "sp-api",
3078 "sp-runtime",
3079 "sp-std",
3080]
30143081
3015[[package]]3082[[package]]
3016name = "pallet-finality-tracker"3083name = "pallet-finality-tracker"
3619source = "registry+https://github.com/rust-lang/crates.io-index"3686source = "registry+https://github.com/rust-lang/crates.io-index"
3620checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485"3687checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485"
3688
3689[[package]]
3690name = "pwasm-utils"
3691version = "0.12.0"
3692source = "registry+https://github.com/rust-lang/crates.io-index"
3693checksum = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192"
3694dependencies = [
3695 "byteorder",
3696 "log",
3697 "parity-wasm",
3698]
36213699
3622[[package]]3700[[package]]
3623name = "quick-error"3701name = "quick-error"
5575 "syn 1.0.31",5653 "syn 1.0.31",
5576]5654]
5655
5656[[package]]
5657name = "sp-sandbox"
5658version = "0.8.0-rc4"
5659source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
5660dependencies = [
5661 "parity-scale-codec",
5662 "sp-core",
5663 "sp-io",
5664 "sp-std",
5665 "sp-wasm-interface",
5666 "wasmi",
5667]
55775668
5578[[package]]5669[[package]]
5579name = "sp-serializer"5670name = "sp-serializer"
modifiednode/Cargo.tomldiffbeforeafterboth
20log = '0.4.8'20log = '0.4.8'
21parking_lot = '0.10.0'21parking_lot = '0.10.0'
22structopt = '0.3.8'22structopt = '0.3.8'
23jsonrpc-core = '14.0.5'
24
25[dependencies.pallet-contracts-rpc]
26git = 'https://github.com/paritytech/substrate.git'
27version = '0.8.0-rc4'
28tag = 'v2.0.0-rc4'
29
30[dependencies.sc-rpc]
31git = 'https://github.com/paritytech/substrate.git'
32tag = 'v2.0.0-rc4'
2333
24[dependencies.nft-runtime]34[dependencies.nft-runtime]
25path = '../runtime'35path = '../runtime'
modifiednode/src/chain_spec.rsdiffbeforeafterboth
8use sp_runtime::traits::{Verify, IdentifyAccount};8use sp_runtime::traits::{Verify, IdentifyAccount};
9use sc_service::ChainType;9use sc_service::ChainType;
10
11use nft_runtime::{ContractsConfig, ContractsSchedule};
1012
11// Note this is the URL for the telemetry server13// Note this is the URL for the telemetry server
12//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";14//const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
111 balances: Some(BalancesConfig {113 balances: Some(BalancesConfig {
112 balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),114 balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),
113 }),115 }),
116 contracts: Some(ContractsConfig {
117 current_schedule: ContractsSchedule {
118 // enable_println,
119 ..Default::default()
120 },
121 }),
114 aura: Some(AuraConfig {122 aura: Some(AuraConfig {
115 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),123 authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),
116 }),124 }),
modifiednode/src/service.rsdiffbeforeafterboth
27/// be able to perform chain operations.27/// be able to perform chain operations.
28macro_rules! new_full_start {28macro_rules! new_full_start {
29 ($config:expr) => {{29 ($config:expr) => {{
30 use jsonrpc_core::IoHandler;
30 use std::sync::Arc;31 use std::sync::Arc;
31 use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;32 use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
3233
8788
88 Ok(import_queue)89 Ok(import_queue)
89 })?;90 })?
91 .with_rpc_extensions(|builder| -> Result<IoHandler<sc_rpc::Metadata>, _> {
92 let handler = pallet_contracts_rpc::Contracts::new(builder.client().clone());
93 let delegate = pallet_contracts_rpc::ContractsApi::to_delegate(handler);
94
95 let mut io = IoHandler::default();
96 io.extend_with(delegate);
97 Ok(io)
98 })?;
9099
91 (builder, import_setup, inherent_data_providers)100 (builder, import_setup, inherent_data_providers)
92 }}101 }}
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
60 pub NextCollectionID get(fn next_collection_id): u64;60 pub NextCollectionID get(fn next_collection_id): u64;
61
62 pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;61 pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
63 //pub Collection get(collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
64
65 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;62 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
6663
69 pub ApprovedList get(fn approved): map hasher(blake2_128_concat) (u64, u64) => Vec<T::AccountId>;66 pub ApprovedList get(fn approved): map hasher(blake2_128_concat) (u64, u64) => Vec<T::AccountId>;
7067
71 pub ItemList get(fn item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;68 pub ItemList get(fn item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
72 // pub ItemList get(item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
73
74 pub ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;69 pub ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;
75 // pub ItemListIndex get(item_index): map hasher(blake2_128_concat) u64 => u64;70
71 pub AddressTokens get(fn address_tokens): map hasher(blake2_128_concat) (u64, T::AccountId) => Vec<u64>;
72
76 }73 }
77}74}
249247
250 let current_index = <ItemListIndex>::get(collection_id);248 let current_index = <ItemListIndex>::get(collection_id);
249
250 Self::add_token_index(collection_id, current_index, new_item.owner.clone())?;
251
251 <ItemListIndex>::insert(collection_id, current_index);252 <ItemListIndex>::insert(collection_id, current_index);
252 <ItemList<T>>::insert((collection_id, current_index), new_item);253 <ItemList<T>>::insert((collection_id, current_index), new_item);
279 }280 }
280 <ItemList<T>>::remove((collection_id, item_id));281 <ItemList<T>>::remove((collection_id, item_id));
282
283 Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
281284
282 // update balance285 // update balance
283 let new_balance = <Balance<T>>::get((collection_id, item.owner.clone())) - 1;286 let new_balance = <Balance<T>>::get((collection_id, item.owner.clone())) - 1;
319 <Balance<T>>::insert((collection_id, new_owner.clone()), balance_new_owner);322 <Balance<T>>::insert((collection_id, new_owner.clone()), balance_new_owner);
320323
321 // change owner324 // change owner
322 item.owner = new_owner;325 let old_owner = item.owner.clone();
326 item.owner = new_owner.clone();
323 <ItemList<T>>::insert((collection_id, item_id), item);327 <ItemList<T>>::insert((collection_id, item_id), item);
328
329 // update index collection
330 Self::move_token_index(collection_id, item_id, old_owner, new_owner.clone())?;
324331
325 // reset approved list332 // reset approved list
326 let itm: Vec<T::AccountId> = Vec::new();333 let itm: Vec<T::AccountId> = Vec::new();
403}410}
404411
412
413impl<T: Trait> Module<T> {
414 fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
415
416 let list_exists = <AddressTokens<T>>::contains_key((collection_id, owner.clone()));
417 if list_exists {
418
419 let mut list = <AddressTokens<T>>::get((collection_id, owner.clone()));
420 let item_contains = list.contains(&item_index.clone());
421
422 if !item_contains {
423 list.push(item_index.clone());
424 }
425
426 <AddressTokens<T>>::insert((collection_id, owner.clone()), list);
427
428 } else {
429
430 let mut itm = Vec::new();
431 itm.push(item_index.clone());
432 <AddressTokens<T>>::insert((collection_id, owner), itm);
433 }
434
435 Ok(())
436 }
437
438 fn remove_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
439
440 let list_exists = <AddressTokens<T>>::contains_key((collection_id, owner.clone()));
441 if list_exists {
442
443 let mut list = <AddressTokens<T>>::get((collection_id, owner.clone()));
444 let item_contains = list.contains(&item_index.clone());
445
446 if item_contains {
447 list.retain(|&item| item != item_index);
448 <AddressTokens<T>>::insert((collection_id, owner), list);
449 }
450 }
451
452 Ok(())
453 }
454
455 fn move_token_index(collection_id: u64, item_index: u64, old_owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
456
457 Self::remove_token_index(collection_id, item_index, old_owner)?;
458 Self::add_token_index(collection_id, item_index, new_owner)?;
459
460 Ok(())
461 }
462}
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
3use crate::{Module, Trait};3use crate::{Module, Trait};
4use frame_support::{impl_outer_origin, parameter_types, weights::Weight};4use frame_support::{
5 impl_outer_origin, parameter_types,
6 weights::{
7 Weight,
8 constants::{ BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND },
9 }};
5use frame_system as system;10use frame_system as system;
6use sp_core::H256;11use sp_core::H256;
7use sp_runtime::{12use sp_runtime::{
24 pub const MaximumBlockWeight: Weight = 1024;30 pub const MaximumBlockWeight: Weight = 1024;
25 pub const MaximumBlockLength: u32 = 2 * 1024;31 pub const MaximumBlockLength: u32 = 2 * 1024;
26 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);32 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
33 pub MaximumExtrinsicWeight: Weight = 10 * WEIGHT_PER_SECOND;
27}34}
35
28impl system::Trait for Test {36impl system::Trait for Test {
29 type Origin = Origin;37 type Origin = Origin;
30 type Call = ();38 type Call = ();
31 type Index = u64;39 type Index = u64;
32 type BlockNumber = u64;40 type BlockNumber = u64;
41 type BaseCallFilter = ();
42 type DbWeight = RocksDbWeight;
43 type BlockExecutionWeight = BlockExecutionWeight;
33 type Hash = H256;44 type Hash = H256;
34 type Hashing = BlakeTwo256;45 type Hashing = BlakeTwo256;
35 type AccountId = u64;46 type AccountId = u64;
36 type Lookup = IdentityLookup<Self::AccountId>;47 type Lookup = IdentityLookup<Self::AccountId>;
37 type Header = Header;48 type Header = Header;
38 type Event = ();49 type Event = ();
39 type BlockHashCount = BlockHashCount;50 type BlockHashCount = BlockHashCount;
51 type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
52 type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
40 type MaximumBlockWeight = MaximumBlockWeight;53 type MaximumBlockWeight = MaximumBlockWeight;
41 type MaximumBlockLength = MaximumBlockLength;54 type MaximumBlockLength = MaximumBlockLength;
42 type AvailableBlockRatio = AvailableBlockRatio;55 type AvailableBlockRatio = AvailableBlockRatio;
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
298 });298 });
299}299}
300300
301#[test]
302fn index_list() {
303 new_test_ext().execute_with(|| {
304 let size = 1024;
305 let origin1 = Origin::signed(1);
306 let origin2 = Origin::signed(2);
307 let origin3 = Origin::signed(3);
308
309 assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
310 assert_ok!(TemplateModule::create_collection(origin2.clone(), size));
311 assert_ok!(TemplateModule::create_collection(origin3.clone(), size));
312
313 assert_eq!(TemplateModule::collection(1).owner, 1);
314 assert_eq!(TemplateModule::collection(2).owner, 2);
315 assert_eq!(TemplateModule::collection(3).owner, 3);
316
317 // create items
318 assert_ok!(TemplateModule::create_item(
319 origin1.clone(),
320 1,
321 [1, 1, 1].to_vec()
322 ));
323
324 assert_ok!(TemplateModule::create_item(
325 origin1.clone(),
326 1,
327 [1, 1, 2].to_vec()
328 ));
329
330 assert_ok!(TemplateModule::create_item(
331 origin1.clone(),
332 1,
333 [1, 2, 3].to_vec()
334 ));
335
336 assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 3);
337
338 // burn one
339 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 2));
340 assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 2);
341
342 // burn another one
343 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 3));
344 assert_eq!(TemplateModule::address_tokens((1, 1))[0], 1);
345 });
346}
modifiedruntime/Cargo.tomldiffbeforeafterboth
4 'aura/std',4 'aura/std',
5 'balances/std',5 'balances/std',
6 'codec/std',6 'codec/std',
7 'contracts/std',
8 'contracts-primitives/std',
9 'contracts-rpc-runtime-api/std',
7 'frame-executive/std',10 'frame-executive/std',
8 'frame-support/std',11 'frame-support/std',
9 'grandpa/std',12 'grandpa/std',
47package = 'parity-scale-codec'50package = 'parity-scale-codec'
48version = '1.3.1'51version = '1.3.1'
52
53[dependencies.contracts]
54git = 'https://github.com/paritytech/substrate.git'
55default-features = false
56package = 'pallet-contracts'
57tag = 'v2.0.0-rc4'
58version = '2.0.0-rc4'
59
60[dependencies.contracts-primitives]
61git = 'https://github.com/paritytech/substrate.git'
62default-features = false
63package = 'pallet-contracts-primitives'
64tag = 'v2.0.0-rc4'
65version = '2.0.0-rc4'
66
67[dependencies.contracts-rpc-runtime-api]
68git = 'https://github.com/paritytech/substrate.git'
69default-features = false
70package = 'pallet-contracts-rpc-runtime-api'
71version = '0.8.0-rc4'
72tag = 'v2.0.0-rc4'
4973
50[dependencies.frame-executive]74[dependencies.frame-executive]
51default-features = false75default-features = false
modifiedruntime/src/lib.rsdiffbeforeafterboth
24use sp_version::RuntimeVersion;24use sp_version::RuntimeVersion;
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26use sp_version::NativeVersion;26use sp_version::NativeVersion;
27use contracts_rpc_runtime_api::ContractExecResult;
2728
28// A few exports that help ease life for downstream crates.29// A few exports that help ease life for downstream crates.
29#[cfg(any(feature = "std", test))]30#[cfg(any(feature = "std", test))]
30pub use sp_runtime::BuildStorage;31pub use sp_runtime::BuildStorage;
31pub use timestamp::Call as TimestampCall;32pub use timestamp::Call as TimestampCall;
32pub use balances::Call as BalancesCall;33pub use balances::Call as BalancesCall;
33pub use sp_runtime::{Permill, Perbill};34pub use sp_runtime::{Permill, Perbill};
35pub use contracts::Schedule as ContractsSchedule;
34pub use frame_support::{36pub use frame_support::{
35 construct_runtime, parameter_types, StorageValue,37 construct_runtime, parameter_types, StorageValue,
36 traits::{KeyOwnerProofSystem, Randomness},38 traits::{KeyOwnerProofSystem, Randomness},
69/// Digest item type.71/// Digest item type.
70pub type DigestItem = generic::DigestItem<Hash>;72pub type DigestItem = generic::DigestItem<Hash>;
73
74pub const MILLICENTS: Balance = 1_000_000_000;
75pub const CENTS: Balance = 1_000 * MILLICENTS;
76pub const DOLLARS: Balance = 100 * CENTS;
7177
72/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know78/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
73/// the specifics of the runtime. They can then be made to be agnostic over specific formats79/// the specifics of the runtime. They can then be made to be agnostic over specific formats
254 type Call = Call;260 type Call = Call;
255}261}
262
263parameter_types! {
264 pub const TombstoneDeposit: Balance = 16 * MILLICENTS;
265 pub const RentByteFee: Balance = 4 * MILLICENTS;
266 pub const RentDepositOffset: Balance = 1000 * MILLICENTS;
267 pub const SurchargeReward: Balance = 150 * MILLICENTS;
268}
269
270impl contracts::Trait for Runtime {
271 type Time = Timestamp;
272 type Randomness = RandomnessCollectiveFlip;
273 type Currency = Balances;
274 type Event = Event;
275 type DetermineContractAddress = contracts::SimpleAddressDeterminer<Runtime>;
276 type TrieIdGenerator = contracts::TrieIdFromParentCounter<Runtime>;
277 type RentPayment = ();
278 type SignedClaimHandicap = contracts::DefaultSignedClaimHandicap;
279 type TombstoneDeposit = TombstoneDeposit;
280 type StorageSizeOffset = contracts::DefaultStorageSizeOffset;
281 type RentByteFee = RentByteFee;
282 type RentDepositOffset = RentDepositOffset;
283 type SurchargeReward = SurchargeReward;
284 type MaxDepth = contracts::DefaultMaxDepth;
285 type MaxValueSize = contracts::DefaultMaxValueSize;
286 type WeightPrice = transaction_payment::Module<Self>;
287}
256288
257/// Used for the module template in `./template.rs`289/// Used for the module template in `./template.rs`
258impl nft::Trait for Runtime {290impl nft::Trait for Runtime {
267 {299 {
268 System: system::{Module, Call, Config, Storage, Event<T>},300 System: system::{Module, Call, Config, Storage, Event<T>},
269 RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},301 RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
302 Contracts: contracts::{Module, Call, Config, Storage, Event<T>},
270 Timestamp: timestamp::{Module, Call, Storage, Inherent},303 Timestamp: timestamp::{Module, Call, Storage, Inherent},
271 Aura: aura::{Module, Config<T>, Inherent(Timestamp)},304 Aura: aura::{Module, Config<T>, Inherent(Timestamp)},
272 Grandpa: grandpa::{Module, Call, Storage, Config, Event},305 Grandpa: grandpa::{Module, Call, Storage, Config, Event},
414 }447 }
415 }448 }
449
450 impl contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>
451 for Runtime
452 {
453 fn call(
454 origin: AccountId,
455 dest: AccountId,
456 value: Balance,
457 gas_limit: u64,
458 input_data: Vec<u8>,
459 ) -> ContractExecResult {
460 let exec_result =
461 Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
462 match exec_result {
463 Ok(v) => ContractExecResult::Success {
464 status: v.status,
465 data: v.data,
466 },
467 Err(_) => ContractExecResult::Error,
468 }
469 }
470
471 fn get_storage(
472 address: AccountId,
473 key: [u8; 32],
474 ) -> contracts_primitives::GetStorageResult {
475 Contracts::get_storage(address, key)
476 }
477
478 fn rent_projection(
479 address: AccountId,
480 ) -> contracts_primitives::RentProjectionResult<BlockNumber> {
481 Contracts::rent_projection(address)
482 }
483 }
484
416}485}
417486