diff --git a/contracts/commitment_nft/src/lib.rs b/contracts/commitment_nft/src/lib.rs index 1c60db0d..d97fba9e 100644 --- a/contracts/commitment_nft/src/lib.rs +++ b/contracts/commitment_nft/src/lib.rs @@ -1,3 +1,41 @@ +//! # Commitment NFT Contract +//! +//! Mints and manages Soroban NFTs that represent user commitments. Each NFT +//! records commitment parameters (duration, max loss, type, amount) and tracks +//! whether the underlying commitment is still active. +//! +//! ## Auth Model and Single Deployer Assumption +//! +//! `initialize` must be called exactly once, immediately after deployment, +//! by the entity that holds the private key of the `admin` address it +//! registers. This is the **single deployer assumption**: the transaction that +//! deploys the contract should also invoke `initialize` in the same +//! transaction or atomically thereafter, so no third party can front-run it +//! with a different admin. `admin.require_auth()` is called inside +//! `initialize` to enforce this — the transaction must be signed by the admin +//! key. +//! +//! Subsequent admin operations (pausing, whitelisting minters, upgrading) +//! require the same `admin.require_auth()` check via the `require_admin` +//! helper. +//! +//! ## Trust Boundaries +//! +//! | Caller role | What they can do | +//! |-------------|-----------------| +//! | Admin | Initialize, pause/unpause, set core contract, manage minter whitelist, upgrade, migrate, emergency mode | +//! | Core contract (`set_core_contract`) | Call `mint` as an authorized minter | +//! | Whitelisted minter (`add_authorized_contract`) | Call `mint` | +//! | NFT owner | `transfer` (inactive NFTs only) | +//! | Anyone | All view functions (`get_metadata`, `owner_of`, etc.) | +//! +//! ## Reentrancy +//! +//! All state-mutating functions use a flag-based reentrancy guard +//! (`DataKey::ReentrancyGuard`). The guard is set on entry and cleared before +//! every return path (including errors), so nested calls from the same +//! contract invocation are rejected with `ReentrancyDetected`. + #![no_std] //! Commitment NFT contract. //! @@ -180,7 +218,42 @@ pub struct CommitmentNFTContract; #[contractimpl] impl CommitmentNFTContract { - /// Initialize the NFT contract + /// Initialize the commitment NFT contract. + /// + /// # Single Deployer Assumption + /// + /// This function enforces the single deployer assumption: the caller must + /// control the `admin` address being registered. `admin.require_auth()` is + /// called before any state is written, ensuring the transaction must be + /// signed by the admin key. This prevents front-running attacks where a + /// third party deploys the contract and calls `initialize` with a different + /// admin before the legitimate deployer acts. + /// + /// The recommended deployment pattern is to invoke `initialize` in the same + /// transaction as the contract upload, leaving no window for front-running. + /// + /// This function may only be called once. Any subsequent call returns + /// [`ContractError::AlreadyInitialized`]. + /// + /// # Parameters + /// + /// - `admin`: Address that will hold admin authority over the contract. + /// Must authorize this transaction via `require_auth`. + /// + /// # Errors + /// + /// - [`ContractError::AlreadyInitialized`] — contract has already been + /// initialized. + /// + /// # Security Notes + /// + /// - `admin.require_auth()` is invoked after the `AlreadyInitialized` + /// guard, so a second caller cannot learn whether the contract is already + /// initialized without paying for auth on a no-op. + /// - Emergency mode and pausable state are **not** checked here because + /// those controls are meaningless before initialization completes. + /// - Storage keys written: `Admin`, `TokenCounter` (0), `TokenIds` ([]), + /// and the `paused` key (`false`). pub fn initialize(e: Env, admin: Address) -> Result<(), ContractError> { // Reject zero address for admin if is_zero_address(&e, &admin) { @@ -192,10 +265,12 @@ impl CommitmentNFTContract { return Err(ContractError::AlreadyInitialized); } - // Store admin address - e.storage().instance().set(&DataKey::Admin, &admin); + // Enforce single deployer assumption: the admin key must sign this + // transaction. Placed after the AlreadyInitialized check so that a + // retry attempt incurs no auth cost. + admin.require_auth(); - // Initialize token counter to 0 + e.storage().instance().set(&DataKey::Admin, &admin); e.storage().instance().set(&DataKey::TokenCounter, &0u32); // Initialize empty token IDs vector (persistent storage for scalability) diff --git a/contracts/commitment_nft/test_snapshots/tests/test_balance_of_after_minting.1.json b/contracts/commitment_nft/test_snapshots/tests/test_balance_of_after_minting.1.json index 2a23a9c7..6c187128 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_balance_of_after_minting.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_balance_of_after_minting.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [], @@ -1320,6 +1338,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_balance_updates_after_transfer.1.json b/contracts/commitment_nft/test_snapshots/tests/test_balance_updates_after_transfer.1.json index 0b5e04e8..48e45cd6 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_balance_updates_after_transfer.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_balance_updates_after_transfer.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", @@ -1031,6 +1049,39 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_data": { @@ -1102,7 +1153,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", "key": { "ledger_key_nonce": { - "nonce": 5541220902715666415 + "nonce": 4837995959683129791 } }, "durability": "temporary" @@ -1117,7 +1168,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", "key": { "ledger_key_nonce": { - "nonce": 5541220902715666415 + "nonce": 4837995959683129791 } }, "durability": "temporary", diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_admin.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_admin.1.json index 387a3f1d..46e50f30 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_admin.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_admin.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata.1.json index 0755f54c..1d607464 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [], @@ -816,6 +834,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata_empty.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata_empty.1.json index 8fdcd65a..28f09f85 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata_empty.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_all_metadata_empty.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_metadata.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_metadata.1.json index c270e104..2261105c 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_metadata.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_metadata.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [] ], @@ -404,6 +422,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_metadata_nonexistent_token.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_metadata_nonexistent_token.1.json index 53e5f428..afe11e61 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_metadata_nonexistent_token.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_metadata_nonexistent_token.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_get_nfts_by_owner.1.json b/contracts/commitment_nft/test_snapshots/tests/test_get_nfts_by_owner.1.json index 49f8d1a4..5ac3a8ec 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_get_nfts_by_owner.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_get_nfts_by_owner.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [], @@ -1320,6 +1338,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_initialize_requires_admin_auth.1.json b/contracts/commitment_nft/test_snapshots/tests/test_initialize_requires_admin_auth.1.json new file mode 100644 index 00000000..477e5fd6 --- /dev/null +++ b/contracts/commitment_nft/test_snapshots/tests/test_initialize_requires_admin_auth.1.json @@ -0,0 +1,219 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ] + ], + "ledger": { + "protocol_version": 21, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "symbol": "paused" + }, + "val": { + "bool": false + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TokenCounter" + } + ] + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "TokenIds" + } + ] + }, + "val": { + "vec": [] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "initialize" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "initialize" + } + ], + "data": "void" + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/contracts/commitment_nft/test_snapshots/tests/test_initialize_stores_authorizing_admin.1.json b/contracts/commitment_nft/test_snapshots/tests/test_initialize_stores_authorizing_admin.1.json new file mode 100644 index 00000000..46e50f30 --- /dev/null +++ b/contracts/commitment_nft/test_snapshots/tests/test_initialize_stores_authorizing_admin.1.json @@ -0,0 +1,267 @@ +{ + "generators": { + "address": 2, + "nonce": 0 + }, + "auth": [ + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 21, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "symbol": "paused" + }, + "val": { + "bool": false + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "TokenCounter" + } + ] + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "vec": [ + { + "symbol": "TokenIds" + } + ] + }, + "val": { + "vec": [] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "initialize" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "initialize" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "get_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/contracts/commitment_nft/test_snapshots/tests/test_initialize_twice_fails.1.json b/contracts/commitment_nft/test_snapshots/tests/test_initialize_twice_fails.1.json index 238ab7fe..bfe0509a 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_initialize_twice_fails.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_initialize_twice_fails.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_is_active.1.json b/contracts/commitment_nft/test_snapshots/tests/test_is_active.1.json index 0f16c848..ac5ea09d 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_is_active.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_is_active.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [] ], @@ -404,6 +422,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_is_active_nonexistent_token.1.json b/contracts/commitment_nft/test_snapshots/tests/test_is_active_nonexistent_token.1.json index 7a90fdbd..e711182f 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_is_active_nonexistent_token.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_is_active_nonexistent_token.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_is_expired.1.json b/contracts/commitment_nft/test_snapshots/tests/test_is_expired.1.json index 9ffc3452..24ccabaf 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_is_expired.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_is_expired.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [] @@ -405,6 +423,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_is_expired_nonexistent_token.1.json b/contracts/commitment_nft/test_snapshots/tests/test_is_expired_nonexistent_token.1.json index c616b0e3..4a545602 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_is_expired_nonexistent_token.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_is_expired_nonexistent_token.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_metadata_timestamps.1.json b/contracts/commitment_nft/test_snapshots/tests/test_metadata_timestamps.1.json index 9b095e97..2f1ae0e5 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_metadata_timestamps.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_metadata_timestamps.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [] ], @@ -404,6 +422,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_mint.1.json b/contracts/commitment_nft/test_snapshots/tests/test_mint.1.json index 8bccf52d..5d404d69 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_mint.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_mint.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [] @@ -405,6 +423,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_mint_multiple.1.json b/contracts/commitment_nft/test_snapshots/tests/test_mint_multiple.1.json index 828b3962..5c6f1ded 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_mint_multiple.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_mint_multiple.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [], @@ -817,6 +835,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_owner_of.1.json b/contracts/commitment_nft/test_snapshots/tests/test_owner_of.1.json index 46bd5473..25b6ba1c 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_owner_of.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_owner_of.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [] ], @@ -404,6 +422,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_owner_of_nonexistent_token.1.json b/contracts/commitment_nft/test_snapshots/tests/test_owner_of_nonexistent_token.1.json index 4a71e6ec..dcbcc349 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_owner_of_nonexistent_token.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_owner_of_nonexistent_token.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_settle.1.json b/contracts/commitment_nft/test_snapshots/tests/test_settle.1.json index c2cf9ed1..91ee5169 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_settle.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_settle.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", @@ -471,6 +489,39 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_data": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_settle_already_settled.1.json b/contracts/commitment_nft/test_snapshots/tests/test_settle_already_settled.1.json index aafdcda8..37ec1b35 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_settle_already_settled.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_settle_already_settled.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", @@ -469,6 +487,39 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_data": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_settle_not_expired.1.json b/contracts/commitment_nft/test_snapshots/tests/test_settle_not_expired.1.json index 9ab2188b..823dba22 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_settle_not_expired.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_settle_not_expired.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", @@ -468,6 +486,39 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 5541220902715666415 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_data": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_token_exists.1.json b/contracts/commitment_nft/test_snapshots/tests/test_token_exists.1.json index 833c9cbf..209431be 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_token_exists.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_token_exists.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [], [], @@ -406,6 +424,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_transfer_nonexistent_token.1.json b/contracts/commitment_nft/test_snapshots/tests/test_transfer_nonexistent_token.1.json index 1e0445f0..5b7ddad9 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_transfer_nonexistent_token.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_transfer_nonexistent_token.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [] ], "ledger": { @@ -94,6 +112,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/contracts/commitment_nft/test_snapshots/tests/test_transfer_not_owner.1.json b/contracts/commitment_nft/test_snapshots/tests/test_transfer_not_owner.1.json index dc016195..2b0808c9 100644 --- a/contracts/commitment_nft/test_snapshots/tests/test_transfer_not_owner.1.json +++ b/contracts/commitment_nft/test_snapshots/tests/test_transfer_not_owner.1.json @@ -4,7 +4,25 @@ "nonce": 0 }, "auth": [ - [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "initialize", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [], [] ], @@ -404,6 +422,39 @@ 4095 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_code": { diff --git a/docs/CONTRACT_FUNCTIONS.md b/docs/CONTRACT_FUNCTIONS.md index aeb79a48..9443a3c5 100644 --- a/docs/CONTRACT_FUNCTIONS.md +++ b/docs/CONTRACT_FUNCTIONS.md @@ -93,6 +93,22 @@ its source-defined types and expected signatures against `commitment_core` and | is_expired(token_id) -> Result | Check expiry based on ledger time. | View. | Requires token exists. | | token_exists(token_id) -> bool | Check if token exists. | View. | Uses persistent storage. | +### commitment_nft deployment checklist + +The following steps must be executed in order when deploying or upgrading `commitment_nft`. Each step is a prerequisite for the next; skipping any step leaves the contract in a broken or insecure state. + +1. **Upload WASM** — submit the compiled WASM to Stellar and record the hash. +2. **Deploy contract** — instantiate the contract from the uploaded WASM hash. +3. **Call `initialize(admin)`** — in the same transaction as deployment (or immediately after, before any other transaction). The `admin` key must sign this transaction. This is the single deployer assumption: the window between `deploy` and `initialize` must be zero or negligible to prevent front-running. +4. **Verify initialization** — call `get_admin()` and confirm it returns the expected admin address. +5. **Call `set_core_contract(core_contract)`** — register the `commitment_core` contract address so `mint` can be called from core. Must be signed by admin. +6. **Optionally call `add_authorized_contract(admin, minter)`** — if additional minter addresses are needed beyond core. +7. **Smoke-test** — call `total_supply()` (expect 0) and `is_paused()` (expect false) to confirm initial state is clean. + +**Single deployer assumption**: `initialize` calls `admin.require_auth()`, so only a transaction signed by the `admin` key can succeed. Any unsigned or differently-signed `initialize` call will be rejected. Deploy and initialize must be atomic (same transaction or XDR envelope) to eliminate the front-run window. + +**Admin key rotation**: use `set_admin(caller, new_admin)` after initialization. `caller` must be the current admin. + ## attestation_engine | Function | Summary | Access control | Notes |