pallet_contracts/address.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Functions that deal with address derivation.
19
20use crate::{CodeHash, Config};
21use codec::{Decode, Encode};
22use sp_runtime::traits::{Hash, TrailingZeroInput};
23
24/// Provides the contract address generation method.
25///
26/// See [`DefaultAddressGenerator`] for the default implementation.
27///
28/// # Note for implementors
29///
30/// 1. Make sure that there are no collisions, different inputs never lead to the same output.
31/// 2. Make sure that the same inputs lead to the same output.
32pub trait AddressGenerator<T: Config> {
33 /// The address of a contract based on the given instantiate parameters.
34 ///
35 /// Changing the formular for an already deployed chain is fine as long as no collisions
36 /// with the old formular. Changes only affect existing contracts.
37 fn contract_address(
38 deploying_address: &T::AccountId,
39 code_hash: &CodeHash<T>,
40 input_data: &[u8],
41 salt: &[u8],
42 ) -> T::AccountId;
43}
44
45/// Default address generator.
46///
47/// This is the default address generator used by contract instantiation. Its result
48/// is only dependent on its inputs. It can therefore be used to reliably predict the
49/// address of a contract. This is akin to the formula of eth's CREATE2 opcode. There
50/// is no CREATE equivalent because CREATE2 is strictly more powerful.
51/// Formula:
52/// `hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)`
53pub struct DefaultAddressGenerator;
54
55impl<T: Config> AddressGenerator<T> for DefaultAddressGenerator {
56 /// Formula: `hash("contract_addr_v1" ++ deploying_address ++ code_hash ++ input_data ++ salt)`
57 fn contract_address(
58 deploying_address: &T::AccountId,
59 code_hash: &CodeHash<T>,
60 input_data: &[u8],
61 salt: &[u8],
62 ) -> T::AccountId {
63 let entropy = (b"contract_addr_v1", deploying_address, code_hash, input_data, salt)
64 .using_encoded(T::Hashing::hash);
65 Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref()))
66 .expect("infinite length input; no invalid inputs for type; qed")
67 }
68}