@@ -6296,4 +6296,153 @@ fn only_authority_can_change_metadata_uri(#[case] seed: Seed) {
6296
6296
} ) ;
6297
6297
}
6298
6298
6299
- // FIXME: add tests
6299
+ #[ rstest]
6300
+ #[ trace]
6301
+ #[ case( Seed :: from_entropy( ) ) ]
6302
+ fn test_make_token_id_activation ( #[ case] seed : Seed ) {
6303
+ use common:: chain:: make_token_id;
6304
+
6305
+ utils:: concurrency:: model ( move || {
6306
+ let mut rng = test_utils:: random:: make_seedable_rng ( seed) ;
6307
+ // activate feature at height 3
6308
+ let mut tf = TestFramework :: builder ( & mut rng)
6309
+ . with_chain_config (
6310
+ common:: chain:: config:: Builder :: test_chain ( )
6311
+ . chainstate_upgrades (
6312
+ common:: chain:: NetUpgrades :: initialize ( vec ! [
6313
+ (
6314
+ BlockHeight :: zero( ) ,
6315
+ ChainstateUpgradeBuilder :: latest( )
6316
+ . token_id_generation_version(
6317
+ common:: chain:: TokenIdGenerationVersion :: V0 ,
6318
+ )
6319
+ . build( ) ,
6320
+ ) ,
6321
+ (
6322
+ BlockHeight :: new( 3 ) ,
6323
+ ChainstateUpgradeBuilder :: latest( )
6324
+ . token_id_generation_version(
6325
+ common:: chain:: TokenIdGenerationVersion :: V1 ,
6326
+ )
6327
+ . build( ) ,
6328
+ ) ,
6329
+ ] )
6330
+ . unwrap ( ) ,
6331
+ )
6332
+ . genesis_unittest ( Destination :: AnyoneCanSpend )
6333
+ . build ( ) ,
6334
+ )
6335
+ . build ( ) ;
6336
+
6337
+ // Create a token just so that there is an account to use in inputs
6338
+ let ( token_id_0, _, utxo_with_change) = issue_token_from_genesis (
6339
+ & mut rng,
6340
+ & mut tf,
6341
+ TokenTotalSupply :: Lockable ,
6342
+ IsTokenFreezable :: Yes ,
6343
+ ) ;
6344
+
6345
+ // Create a token from account input
6346
+ let issuance = make_issuance ( & mut rng, TokenTotalSupply :: Unlimited , IsTokenFreezable :: No ) ;
6347
+ let token_issuance_fee = tf. chainstate . get_chain_config ( ) . fungible_token_issuance_fee ( ) ;
6348
+ let token_change_authority_fee =
6349
+ tf. chainstate . get_chain_config ( ) . token_change_authority_fee ( BlockHeight :: zero ( ) ) ;
6350
+
6351
+ let tx1 = TransactionBuilder :: new ( )
6352
+ . add_input (
6353
+ TxInput :: AccountCommand (
6354
+ AccountNonce :: new ( 0 ) ,
6355
+ AccountCommand :: LockTokenSupply ( token_id_0) ,
6356
+ ) ,
6357
+ InputWitness :: NoSignature ( None ) ,
6358
+ )
6359
+ . add_input (
6360
+ utxo_with_change. clone ( ) . into ( ) ,
6361
+ InputWitness :: NoSignature ( None ) ,
6362
+ )
6363
+ . add_output ( TxOutput :: Transfer (
6364
+ OutputValue :: Coin ( ( token_issuance_fee + token_change_authority_fee) . unwrap ( ) ) ,
6365
+ Destination :: AnyoneCanSpend ,
6366
+ ) )
6367
+ . add_output ( TxOutput :: IssueFungibleToken ( Box :: new ( issuance. clone ( ) ) ) )
6368
+ . build ( ) ;
6369
+
6370
+ let issue_token_1_tx_id = tx1. transaction ( ) . get_id ( ) ;
6371
+ let token_id_1 = make_token_id (
6372
+ tf. chain_config ( ) ,
6373
+ tf. best_block_index ( ) . block_height ( ) . next_height ( ) ,
6374
+ tx1. transaction ( ) . inputs ( ) ,
6375
+ )
6376
+ . unwrap ( ) ;
6377
+
6378
+ let _ = tf
6379
+ . make_block_builder ( )
6380
+ . add_transaction ( tx1)
6381
+ . build_and_process ( & mut rng)
6382
+ . unwrap ( ) ;
6383
+
6384
+ let token_1_data = TokensAccountingStorageRead :: get_token_data (
6385
+ & tf. storage . transaction_ro ( ) . unwrap ( ) ,
6386
+ & token_id_1,
6387
+ )
6388
+ . unwrap ( ) ;
6389
+ assert ! ( token_1_data. is_some( ) ) ;
6390
+ assert_ne ! ( token_id_1, TokenId :: from_utxo( & utxo_with_change) ) ;
6391
+
6392
+ // Check that at height 3 token is issued not from the first input but from the first utxo input
6393
+ let tx2 = TransactionBuilder :: new ( )
6394
+ . add_input (
6395
+ TxInput :: AccountCommand (
6396
+ AccountNonce :: new ( 1 ) ,
6397
+ AccountCommand :: ChangeTokenAuthority ( token_id_0, Destination :: AnyoneCanSpend ) ,
6398
+ ) ,
6399
+ InputWitness :: NoSignature ( None ) ,
6400
+ )
6401
+ . add_input (
6402
+ TxInput :: from_utxo ( issue_token_1_tx_id. clone ( ) . into ( ) , 0 ) ,
6403
+ InputWitness :: NoSignature ( None ) ,
6404
+ )
6405
+ . add_output ( TxOutput :: IssueFungibleToken ( Box :: new ( issuance. clone ( ) ) ) )
6406
+ . build ( ) ;
6407
+
6408
+ let token_id_2 = make_token_id (
6409
+ tf. chain_config ( ) ,
6410
+ tf. best_block_index ( ) . block_height ( ) . next_height ( ) ,
6411
+ tx2. transaction ( ) . inputs ( ) ,
6412
+ )
6413
+ . unwrap ( ) ;
6414
+ assert_eq ! (
6415
+ token_id_2,
6416
+ TokenId :: from_utxo( & UtxoOutPoint :: new( issue_token_1_tx_id. into( ) , 0 ) )
6417
+ ) ;
6418
+
6419
+ // also make sure token was not created from account input
6420
+ let invalid_token_id_from_account_input = make_token_id (
6421
+ tf. chain_config ( ) ,
6422
+ BlockHeight :: zero ( ) ,
6423
+ tx2. transaction ( ) . inputs ( ) ,
6424
+ )
6425
+ . unwrap ( ) ;
6426
+ assert_ne ! ( token_id_2, invalid_token_id_from_account_input) ;
6427
+
6428
+ let _ = tf
6429
+ . make_block_builder ( )
6430
+ . add_transaction ( tx2)
6431
+ . build_and_process ( & mut rng)
6432
+ . unwrap ( ) ;
6433
+
6434
+ let token_2_data = TokensAccountingStorageRead :: get_token_data (
6435
+ & tf. storage . transaction_ro ( ) . unwrap ( ) ,
6436
+ & token_id_2,
6437
+ )
6438
+ . unwrap ( ) ;
6439
+ assert ! ( token_2_data. is_some( ) ) ;
6440
+
6441
+ let token_2_data_invalid = TokensAccountingStorageRead :: get_token_data (
6442
+ & tf. storage . transaction_ro ( ) . unwrap ( ) ,
6443
+ & invalid_token_id_from_account_input,
6444
+ )
6445
+ . unwrap ( ) ;
6446
+ assert ! ( token_2_data_invalid. is_none( ) ) ;
6447
+ } ) ;
6448
+ }
0 commit comments