# Wrong ProfitManager in GuildToken, will always revert for other types of gauges leading to bad debt

GuildToken hardcodes a single ProfitManager in its constructor, so notifyGaugeLoss reverts for any second market's ProfitManager, blocking loss accounting and causing bad debt.

- Payout: Contest reward
- Severity: medium
- Program: Ethereum Credit Guild
- Credited: SBSecurity
- Disclosed: 2024-02-22
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-12-ethereumcreditguild-findings/issues/1001
- Library page: https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AM-10
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:accounting-error vuln:business-logic vuln:dos

**Target:** GuildToken.sol smart contract (gauge loss notification)
**Root cause:** GuildToken stores one profitManager set at construction and notifyGaugeLoss requires msg.sender == that address, but each market has its own ProfitManager, so calls from other markets' ProfitManagers revert UNAUTHORIZED.
**Steps:**
1. Deploy two markets (e.g. gUSDC and gWETH), each with its own ProfitManager and CreditToken, but a single GuildToken constructed with only the first ProfitManager.
2. Add gauges for both terms via `guild.addGauge(1, term)` and `guild.addGauge(2, termWETH)`.
3. Call `profitManager.notifyPnL(term, -1)` on the first market's ProfitManager — succeeds.
4. Call `profitManagerWETH.notifyPnL(termWETH, -1)` on the second market's ProfitManager — reverts with `UNAUTHORIZED` because GuildToken.notifyGaugeLoss checks msg.sender against the constructor-set profitManager.
**How found:** Code reading of GuildToken constructor and notifyGaugeLoss revealed a single hardcoded profitManager address, then reasoning that multi-market deployments each have distinct ProfitManagers; confirmed with a Foundry PoC adding a second market.
**Exploitation:** When a loan in a non-primary market is forgiven or auctioned at a loss, ProfitManager.notifyPnL with negative value calls GuildToken.notifyGaugeLoss, which reverts; gauge loss is never recorded, so the bad loan is not written off and the protocol accrues bad debt unless users repay.
**Insight:** When a shared token/registry contract is constructed with a per-market dependency address, check every require(msg.sender == storedAddress) against multi-instance deployments — the singleton assumption silently breaks the second instance.
