Root + Impact
Description
The CRED token contract allows the module owner to mint unlimited tokens to any address without restriction. This centralization risk creates a single point of failure where the owner could manipulate the token supply and economic balance of the protocol.
The mint function lacks any supply cap or rate limiting mechanism, enabling the module owner to mint arbitrary amounts of CRED tokens to any address, which could be used to manipulate battle outcomes or devalue existing token holdings.
@> public(friend) fun mint(
@>     module_owner: &signer,
@>     to: address,
@>     amount: u64
@> ) acquires CredCapabilities {
@>     let caps = borrow_global<CredCapabilities>(signer::address_of(module_owner));
@>     let coins = coin::mint<CRED>(amount, &caps.mint_cap);
@>     if (coin::is_account_registered<CRED>(to)) {
@>         coin::deposit(to, coins);
@>     } else {
@>         coin::destroy_zero(coins);
@>     };
@> }
Risk
Likelihood:
- The module owner can mint tokens at any time since there are no restrictions on the mint function 
- The owner address is hardcoded as @battle_addr, creating a permanent centralization point 
Impact:
- Token supply inflation leading to devaluation of existing holdings 
- Manipulation of battle outcomes by minting tokens to specific users 
- Loss of trust in the protocol due to centralization risks 
Proof of Concept
This PoC demonstrates how the module owner can mint unlimited tokens to manipulate the economy:
let module_owner = account::create_account_for_test(@battle_addr);
let attacker_address = @0x1234567890abcdef;
cred_token::mint(&module_owner, attacker_address, 1000000000000); 
let target_user = @0xabcdef1234567890;
cred_token::mint(&module_owner, target_user, 1000000); 
Recommended Mitigation
The mitigation adds a supply cap mechanism to prevent unlimited minting:
+ struct SupplyCap has key {
+     max_supply: u64,
+     current_supply: u64,
+ }
+ 
+ fun init_module(sender: &signer) {
+     let (burn_cap, freeze_cap, mint_cap) = coin::initialize<CRED>(
+         sender,
+         string::utf8(b"Credibility"),
+         string::utf8(b"CRED"),
+         8,
+         false,
+     );
+     move_to(sender, CredCapabilities { mint_cap, burn_cap });
+     move_to(sender, SupplyCap { max_supply: 1000000000, current_supply: 0 });
+     coin::destroy_freeze_cap(freeze_cap);
+ }
+ 
  public(friend) fun mint(
      module_owner: &signer,
      to: address,
      amount: u64
- ) acquires CredCapabilities {
+ ) acquires CredCapabilities, SupplyCap {
+     let supply = borrow_global_mut<SupplyCap>(@battle_addr);
+     assert!(supply.current_supply + amount <= supply.max_supply, E_SUPPLY_EXCEEDED);
+     supply.current_supply = supply.current_supply + amount;
+     
      let caps = borrow_global<CredCapabilities>(signer::address_of(module_owner));
      let coins = coin::mint<CRED>(amount, &caps.mint_cap);
      if (coin::is_account_registered<CRED>(to)) {
          coin::deposit(to, coins);
      } else {
          coin::destroy_zero(coins);
      };
  }
This mitigation adds a supply cap that prevents unlimited token minting by tracking the current supply against a maximum limit. The cap ensures the token economy remains controlled and prevents centralization abuse.