diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index 52562cb1388..5b8727a364d 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -32,11 +32,12 @@ pub fn compute_unsiloed_contract_initialization_nullifier(context: TCo context.this_address().to_field() } -pub fn assert_initialization_args_match_address_preimage(context: TContext) where TContext: ContextInterface { +pub fn assert_initialization_matches_address_preimage(context: TContext) where TContext: ContextInterface { let address = context.this_address(); let instance = get_contract_instance(address); let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash()); assert(instance.initialization_hash == expected_init, "Initialization hash does not match"); + assert((instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), "Initializer address is not the contract deployer"); } pub fn compute_initialization_hash(init_selector: FunctionSelector, init_args_hash: Field) -> Field { diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs index 09c11e173fe..4fc2792a2cc 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/functions.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -48,10 +48,9 @@ pub fn transform_function( func.def.body.0.insert(0, init_check); } - // Add assertion for initialization arguments + // Add assertion for initialization arguments and sender if is_initializer { - let assert_init_args = create_assert_init_args(); - func.def.body.0.insert(0, assert_init_args); + func.def.body.0.insert(0, create_assert_initializer()); } // Add access to the storage struct @@ -211,18 +210,19 @@ fn create_internal_check(fname: &str) -> Statement { ))) } -/// Creates a call to assert_initialization_args_match_address_preimage to ensure -/// the initialization arguments used in the init call match the address preimage. +/// Creates a call to assert_initialization_matches_address_preimage to be inserted +/// in the initializer. Checks that the args and sender to the initializer match the +/// commitments from the address preimage. /// /// ```noir -/// assert_initialization_args_match_address_preimage(context); +/// assert_initialization_matches_address_preimage(context); /// ``` -fn create_assert_init_args() -> Statement { +fn create_assert_initializer() -> Statement { make_statement(StatementKind::Expression(call( variable_path(chained_dep!( "aztec", "initializer", - "assert_initialization_args_match_address_preimage" + "assert_initialization_matches_address_preimage" )), vec![variable("context")], ))) diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts index b46aac442d3..c3e6a6678df 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract.test.ts @@ -257,6 +257,14 @@ describe('e2e_deploy_contract', () => { /Initialization hash does not match/, ); }); + + it('refuses to initialize an instance from a different deployer', async () => { + const owner = await registerRandomAccount(pxe); + const contract = await registerContract(wallet, StatefulTestContract, { initArgs: [owner, 42], deployer: owner }); + await expect(contract.methods.constructor(owner, 42).simulate()).rejects.toThrow( + /Initializer address is not the contract deployer/i, + ); + }); }); describe('registering a contract class', () => { @@ -472,9 +480,6 @@ describe('e2e_deploy_contract', () => { }); expect(() => deployInstance(wallet, instance)).toThrow(/does not match/i); }); - - // TODO(@spalladino): Implement me! - it('refuses to initialize an instance from a different deployer', async () => {}); }); });