If referral or liquidator is the same address as the account, then liquidation/referral fees will be lost due to local storage being overwritten after the `claimable` amount is credited to liquidator or referral
Any user (address) can be liquidator and/or referral, including account's own address (the user can self-liquidate or self-refer). During the market settlement, liquidator and referral fees are credited to liquidator/referral's `local.claimable` storage. The issue is that the account's local storage is held in the memory during the settlement process, and is saved into storage after settlement/update. This means that `local.claimable` storage changes for the account are not reflected in the in-memory cached copy and discarded when the cached copy is saved after settlement.\\nThis leads to liquidator and referral fees being lost when these are the account's own address.\\nDuring market account settlement process, in the `_processOrderLocal`, liquidator and referral fees are credited to corresponding accounts via:\\n```\\n// rest of code\\n    _credit(liquidators[account][newOrderId], accumulationResult.liquidationFee);\\n    _credit(referrers[account][newOrderId], accumulationResult.subtractiveFee);\\n// rest of code\\nfunction _credit(address account, UFixed6 amount) private {\\n    if (amount.isZero()) return;\\n\\n    Local memory newLocal = _locals[account].read();\\n    newLocal.credit(amount);\\n    _locals[account].store(newLocal);\\n}\\n```\\n\\nHowever, for the account the cached copy of `_locals[account]` is stored after the settlement in _storeContext:\\n```\\nfunction _storeContext(Context memory context, address account) private {\\n    // state\\n    _global.store(context.global);\\n    _locals[account].store(context.local);\\n// rest of code\\n```\\n\\nThe order of these actions is:\\n```\\nfunction settle(address account) external nonReentrant whenNotPaused {\\n    Context memory context = _loadContext(account);\\n\\n    _settle(context, account);\\n\\n    _storeContext(context, account);\\n}\\n```\\n\\nLoad `_locals[account]` into memory (context.local)\\nSettle: during settlement `_locals[account].claimable` is increased for liquidator and referral. Note: this is not reflected in `context.local`\\nStore cached context: `_locals[account]` is overwritten with the `context.local`, losing `claimable` increased during settlement.\\nThe scenario above is demonstrated in the test, add this to test/unit/market/Market.test.ts:\\n```\\nit('self-liquidation fees lost', async () => {\\nconst POSITION = parse6decimal('100.000')\\nconst COLLATERAL = parse6decimal('120')\\n\\nfunction setupOracle(price: string, timestamp : number, nextTimestamp : number) {\\n    const oracleVersion = {\\n    price: parse6decimal(price),\\n    timestamp: timestamp,\\n    valid: true,\\n    }\\n    oracle.at.whenCalledWith(oracleVersion.timestamp).returns(oracleVersion)\\n    oracle.status.returns([oracleVersion, nextTimestamp])\\n    oracle.request.returns()\\n}\\n\\ndsu.transferFrom.whenCalledWith(user.address, market.address, COLLATERAL.mul(1e12)).returns(true)\\ndsu.transferFrom.whenCalledWith(userB.address, market.address, COLLATERAL.mul(1e12)).returns(true)\\n\\nvar time = TIMESTAMP;\\n\\nsetupOracle('1', time, time + 100);\\nawait market.connect(user)\\n    ['update(address,uint256,uint256,uint256,int256,bool)'](user.address, POSITION, 0, 0, COLLATERAL, false);\\n\\ntime += 100;\\nsetupOracle('1', time, time + 100);\\nawait market.connect(userB)\\n    ['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, POSITION, 0, COLLATERAL, false);\\n\\ntime += 100;\\nsetupOracle('1', time, time + 100);\\n\\ntime += 100;\\nsetupOracle('0.7', time, time + 100);\\n\\n// self-liquidate\\nsetupOracle('0.7', time, time + 100);\\nawait market.connect(userB)\\n    ['update(address,uint256,uint256,uint256,int256,bool)'](userB.address, 0, 0, 0, 0, true);\\n\\n// settle liquidation\\ntime += 100;\\nsetupOracle('0.7', time, time + 100);\\nawait market.settle(userB.address);\\nvar info = await market.locals(userB.address);\\nconsole.log("Claimable userB: " + info.claimable);\\n```\\n\\nConsole log:\\n```\\nClaimable userB: 0\\n```\\n
Modify `Market._credit` function to increase `context.local.claimable` if account to be credited matches account which is being updated.
If user self-liquidates or self-refers, the liquidation and referral fees are lost by the user (and are stuck in the contract, because they're still subtracted from the user's collateral).
```\\n// rest of code\\n    _credit(liquidators[account][newOrderId], accumulationResult.liquidationFee);\\n    _credit(referrers[account][newOrderId], accumulationResult.subtractiveFee);\\n// rest of code\\nfunction _credit(address account, UFixed6 amount) private {\\n    if (amount.isZero()) return;\\n\\n    Local memory newLocal = _locals[account].read();\\n    newLocal.credit(amount);\\n    _locals[account].store(newLocal);\\n}\\n```\\n