Skip to content

Commit f312342

Browse files
Document constructor auth mocking on register (#1950)
### What Document on the contract registration functions (`register`, `register_at`, and the deprecated `register_contract` and `register_contract_wasm`) that a contract's constructor is invoked with authorization mocked during registration, and direct callers who need to test constructor authorization to deploy the contract through the deployer instead. ### Why Following #1738, `register` and `register_at` switch the environment to recording auth for the constructor call, so any `require_auth` a constructor makes is automatically authorized and cannot be exercised through registration. That behavior was undocumented, leaving no guidance that constructor authorization must instead be tested by deploying the contract the way it is deployed on-chain, via `env.deployer().with_address(...)` and `deploy_v2`, which runs the constructor subject to the environment's authorization. ### Known limitations The documentation on the Stellar Asset Contract registration functions (`register_stellar_asset_contract_v2` and `register_stellar_asset_contract`) is intentionally left unchanged, as those functions register a built-in contract with no user-defined constructor and the deploy-to-test-auth guidance does not apply to them. Close #1738
1 parent 014a940 commit f312342

1 file changed

Lines changed: 40 additions & 0 deletions

File tree

soroban-sdk/src/env.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,22 @@ impl Env {
789789
/// If you need to specify the address the contract should be registered at,
790790
/// use [`Env::register_at`].
791791
///
792+
/// ### Authorization
793+
///
794+
/// If the contract has a constructor, it is called during registration
795+
/// with authorization mocked: the environment switches to recording auth
796+
/// for the constructor call, so any [`Address::require_auth`] calls the
797+
/// constructor makes are automatically authorized and succeed regardless
798+
/// of the authorization configured on the environment. Because of this,
799+
/// `register` cannot be used to test a constructor's authorization.
800+
///
801+
/// To test constructor authorization, deploy the contract the way it is
802+
/// deployed on-chain using the deployer returned by [`Env::deployer`],
803+
/// e.g. [`Deployer::with_address`] followed by
804+
/// [`deploy_v2`][crate::deploy::DeployerWithAddress::deploy_v2]. Deploying
805+
/// that way runs the constructor subject to the environment's
806+
/// authorization, so `require_auth` behaves as it would on-chain.
807+
///
792808
/// ### Examples
793809
/// Register a contract defined in the current crate, by specifying the type
794810
/// name:
@@ -853,6 +869,22 @@ impl Env {
853869
/// Returns the address of the registered contract that is the same as the
854870
/// contract id passed in.
855871
///
872+
/// ### Authorization
873+
///
874+
/// If the contract has a constructor, it is called during registration
875+
/// with authorization mocked: the environment switches to recording auth
876+
/// for the constructor call, so any [`Address::require_auth`] calls the
877+
/// constructor makes are automatically authorized and succeed regardless
878+
/// of the authorization configured on the environment. Because of this,
879+
/// `register_at` cannot be used to test a constructor's authorization.
880+
///
881+
/// To test constructor authorization, deploy the contract the way it is
882+
/// deployed on-chain using the deployer returned by [`Env::deployer`],
883+
/// e.g. [`Deployer::with_address`] followed by
884+
/// [`deploy_v2`][crate::deploy::DeployerWithAddress::deploy_v2]. Deploying
885+
/// that way runs the constructor subject to the environment's
886+
/// authorization, so `require_auth` behaves as it would on-chain.
887+
///
856888
/// ### Examples
857889
/// Register a contract defined in the current crate, by specifying the type
858890
/// name:
@@ -914,6 +946,10 @@ impl Env {
914946
/// If a contract has a constructor defined, then it will be called with
915947
/// no arguments. If a constructor takes arguments, use `register`.
916948
///
949+
/// The constructor call has authorization mocked, the same as
950+
/// [`register`][Self::register]; see that function for how to test
951+
/// constructor authorization.
952+
///
917953
/// Registering a contract that is already registered replaces it.
918954
/// Use re-registration with caution as it does not exist in the real
919955
/// (on-chain) environment. Specifically, the new contract's constructor
@@ -1033,6 +1069,10 @@ impl Env {
10331069
/// with that contract ID. Providing `None` causes the Env to generate a new
10341070
/// contract ID that is assigned to the contract.
10351071
///
1072+
/// If the contract has a constructor, it is called during registration
1073+
/// with authorization mocked, the same as [`register`][Self::register];
1074+
/// see that function for how to test constructor authorization.
1075+
///
10361076
/// Registering a contract that is already registered replaces it.
10371077
/// Use re-registration with caution as it does not exist in the real
10381078
/// (on-chain) environment. Specifically, the new contract's constructor

0 commit comments

Comments
 (0)