The execute contract at the interchain-token-service doesn't initialize the token balance at the source chain when deploying an interchain token
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L112


# Vulnerability details

## Description
In the context of interchain transfer messages, the apply_balance_tracking function firstly updates the token balance on the source chain by subtracting the amount sent from the stored value then adding this same amount to the token balance on the destination chain, as can be seen here:
```rust
update_token_balance(
                storage,
                token_id.clone(),
                source_chain.clone(),
                *amount,
                false,
            )
            .change_context_lazy(|| Error::BalanceUpdateFailed(source_chain, token_id.clone()))?;

            // Update the balance on the destination chain
            update_token_balance(
                storage,
                token_id.clone(),
                destination_chain.clone(),
                *amount,
                true,
            )
```

When deploying an interchain token, the token balance is initialized for the destination chain, but not for the source chain:
```rust
ItsMessage::DeployInterchainToken { token_id, .. } => {
            start_token_balance(storage, token_id.clone(), destination_chain.clone(), true)
                .change_context(Error::InvalidStoreAccess)?
        }
```

This is not entirely correct, as the interchain transfers will attempt remove stored balance from the source chain.  If the program initializes the source chain's balance to zero or not initialize the balance at all, interchain transfers will revert with overflow errors:
OverflowError::new(OverflowOperation::Sub) 
https://docs.rs/cosmwasm-std/latest/src/cosmwasm_std/math/uint256.rs.html#251-256

## Impact
Interchain transfers have a zero-day that stops them from being processed due to overflows on balance tracking logic.
## Proof of Concept
The tests artificially initialize the source chain balance in order to fit the program. Since the tests are not part of the programs logic, it is not possible to extrapolate such logic is reproducible in production.
In the tests, the update_token_balance function is called outside of the execute contract's functions:
```rust
 fn balance_tracking_interchain_transfer() {
 ...
 // Simulate an initial balance on the source chain
        state::update_token_balance(
            deps.as_mut().storage,
            token_id.clone(),
            source_chain.clone(),
            amount,
            true,
        )
        .unwrap();
...
}
```

As stated in the comment, this is to simulate an initial balance on the source chain. The execute contract, however, doesn't have a function that enables one-sided update_token_balance.  
Therefore this is an artificial initial balance.

## Tools Used
Manual review
## Recommended Mitigation Steps
The deployment of interchain tokens ought to take into account whether the token id alrea