@@ -76,16 +76,17 @@ impl Counter {
7676/// }
7777/// ```
7878pub struct TestEnvironment {
79- // The secrets to be used for light and contract account creation, as well as contract deployments. By keeping
80- // track of the last used secret we can issue new ones automatically without requiring the user to provide
79+ // The secrets and salt to be used for light and contract account creation, as well as contract deployments. By
80+ // keeping track of the last used secret we can issue new ones automatically without requiring the user to provide
8181 // different ones.
8282 //
83- // Additionally, having the secrets be deterministic for each set of accounts and all concurrent tests results in
84- // TXE being able to maximize cache usage and not have to recompute account addresses and contract artifacts, which
85- // are relatively expensive operations.
83+ // Additionally, having the secrets and salt be deterministic for each set of accounts and all concurrent tests
84+ // results in TXE being able to maximize cache usage and not have to recompute account addresses and contract
85+ // artifacts, which are relatively expensive operations.
8686 light_account_secret : Counter ,
8787 contract_account_secret : Counter ,
8888 contract_deployment_secret : Counter ,
89+ contract_deployment_salt : Counter ,
8990}
9091
9192/// Configuration values for [`TestEnvironment::private_context_opts`]. Meant to be used by calling `new` and then
@@ -138,6 +139,38 @@ struct EventDiscoveryOptions {
138139 contract_address : Option <AztecAddress >,
139140}
140141
142+ /// Configuration values for [`TestEnvironment::deploy_opts`]. Meant to be used by calling `new` and then chaining
143+ /// methods setting each value, e.g.:
144+ /// ```noir
145+ /// env.deploy_opts(DeployOptions::new().with_salt(42).with_secret(100), "MyContract").without_initializer();
146+ /// ```
147+ pub struct DeployOptions {
148+ salt : Option <Field >,
149+ secret : Option <Field >,
150+ }
151+
152+ impl DeployOptions {
153+ /// Creates a new `DeployOptions` with default values, i.e. the same as if using the `deploy` method instead of
154+ /// `deploy_opts`. Use the `with_salt` and `with_secret` methods to set the desired configuration values.
155+ pub fn new () -> Self {
156+ Self { salt : Option ::none (), secret : Option ::none () }
157+ }
158+
159+ /// Sets the deployment salt. The salt affects the resulting contract address: the same contract deployed with
160+ /// different salts will have different addresses.
161+ pub fn with_salt (&mut self , salt : Field ) -> Self {
162+ self .salt = Option ::some (salt );
163+ *self
164+ }
165+
166+ /// Sets the secret used for key derivation. The secret affects the contract's public keys and therefore its
167+ /// address: the same contract deployed with different secrets will have different addresses.
168+ pub fn with_secret (&mut self , secret : Field ) -> Self {
169+ self .secret = Option ::some (secret );
170+ *self
171+ }
172+ }
173+
141174impl TestEnvironment {
142175 /// Creates a new `TestEnvironment`. This function should only be called once per test.
143176 pub unconstrained fn new () -> Self {
@@ -150,6 +183,9 @@ impl TestEnvironment {
150183 light_account_secret : Counter ::new (),
151184 contract_account_secret : Counter ::new_with_offset (1 _000 ),
152185 contract_deployment_secret : Counter ::new_with_offset (2 _000 ),
186+ // The salt counter does not need an offset because keys (derived from secret) and salt are unrelated: a
187+ // collision between a salt and a secret value has no effect on the resulting contract address.
188+ contract_deployment_salt : Counter ::new (),
153189 }
154190 }
155191
@@ -477,7 +513,19 @@ impl TestEnvironment {
477513 /// );
478514 /// ```
479515 pub unconstrained fn deploy <let N : u32 >(&mut self , path : str <N >) -> ContractDeployment <N > {
480- ContractDeployment { env : *self , path , secret : self .contract_deployment_secret .next () }
516+ self .deploy_opts (DeployOptions ::new (), path )
517+ }
518+
519+ /// Variant of `deploy` which allows specifying configuration values via `DeployOptions`, such as a custom salt
520+ /// or secret. If not specified, the salt and secret default to values from internal counters.
521+ pub unconstrained fn deploy_opts <let N : u32 >(
522+ &mut self ,
523+ opts : DeployOptions ,
524+ path : str <N >,
525+ ) -> ContractDeployment <N > {
526+ let secret = opts .secret .unwrap_or_else (|| self .contract_deployment_secret .next ());
527+ let salt = opts .salt .unwrap_or_else (|| self .contract_deployment_salt .next ());
528+ ContractDeployment { env : *self , path , secret , salt }
481529 }
482530
483531 /// Performs a private contract function call, including the processing of any nested private calls and enqueued
0 commit comments