You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: storage.rs
    path of file: ./repos/namada/crates/trans_token/src
    
    the code of the file until where you have to start completion: use namada_core::address::{Address, InternalAddress};
use namada_core::hints;
use namada_core::token::{self, Amount, DenominatedAmount};
use namada_storage as storage;
use namada_storage::{StorageRead, StorageWrite};

use crate::storage_key::*;

/// Initialize parameters for the token in storage during the genesis block.
pub fn write_params<S>(
    storage: &mut S,
    address: &Address,
) -> storage::Result<()>
where
    S: StorageRead + StorageWrite,
{
    storage.write(&minted_balance_key(address), Amount::zero())?;
    Ok(())
}

/// Read the balance of a given token and owner.
pub fn read_balance<S>(
    storage: &S,
    token: &Address,
    owner: &Address,
) -> storage::Result<token::Amount>
where
    S: StorageRead,
{
    let key = balance_key(token, owner);
    let balance = storage.read::<token::Amount>(&key)?.unwrap_or_default();
    Ok(balance)
}

/// Read the total network supply of a given token.
pub fn read_total_supply<S>(
    storage: &S,
    token: &Address,
) 
    
    fn test_burn_native_tokens() {
        let mut storage = TestStorage::default();
        let native_token = address::testing::nam();

        // Get some addresses
        let addr1 = address::testing::gen_implicit_address();
        let addr2 = address::testing::gen_implicit_address();
        let addr3 = address::testing::gen_implicit_address();

        let balance1 = token::Amount::native_whole(1);
        let balance2 = token::Amount::native_whole(2);
        let balance3 = token::Amount::native_whole(3);
        let tot_init_balance = balance1 + balance2 + balance3;

        credit_tokens(&mut storage, &native_token, &addr1, balance1).unwrap();
        credit_tokens(&mut storage, &native_token, &addr2, balance2).unwrap();
        credit_tokens(&mut storage, &native_token, &addr3, balance3).unwrap();

        // Check total initial supply
        let total_supply = read_total_supply(&storage, &native_token).unwrap();
        assert_eq!(total_supply, tot_init_balance);

        // Burn some tokens
        let burn1 = token::Amount::from(547_432);
        burn_tokens(&mut storage, &native_token, &addr1, burn1).unwrap();

        // Check new balances
        let addr1_balance =
            read_balance(&storage, &native_token, &addr1).unwrap();
        assert_eq!(addr1_balance, balance1 - burn1);
        let total_supply = read_total_supply(&storage, &native_token).unwrap();
        assert_eq!(total_supply, tot_init_balance - burn1);

        // Burn more tokens from addr1 than it has remaining
        let burn2 = token::Amount::from(1_000_000);
        burn_tokens(&mut storage, &native_token, &addr1, burn2).unwrap();

        // Check new balances
        let addr1_balance =
            read_balance(&storage, &native_token, &addr1).unwrap();
        assert_eq!(addr1_balance, token::Amount::zero());
        let total_supply = read_total_supply(&storage, &native_token).unwrap();
        assert_eq!(total_supply, tot_init_balance - balance1);

        // Burn more tokens from addr2 than are in the total supply
        let burn3 = tot_init_balance + token::Amount::native_whole(1);
        burn_tokens(&mut storage, &native_token, &addr2, burn3).unwrap();

        // Check balances again
        let addr2_balance =
            read_balance(&storage, &native_token, &addr2).unwrap();
        assert_eq!(addr2_balance, token::Amount::zero());
        let total_supply = read_total_supply(&storage, &native_token).unwrap();
        assert_eq!(total_supply, balance3);
    }