In coin.move:
assert!(
coin_address<CoinType>() == account_addr,
error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH),
);
My guess is it prevents account A from initializing coins on behalf of account B to avoid scam?
But look forward to more clarification!
The intent is to ensure that a coin can ever be initialized once as that is how all the capabilities (burn, freeze, mint) are generated.
Specifically,
assert!(
coin_address<CoinType>() == account_addr,
error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH),
);
prevents anyone other than the actual account that publishes CoinType
from initializing it.
The next bit of code ensures it can only be initialized once:
assert!(
!exists<CoinInfo<CoinType>>(account_addr),
error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED),
);