# TitlesGraph::acknowledgeEdge() methods do not write acknowledgments to storage

TitlesGraph._setAcknowledged caches edges[edgeId] in a memory return variable, so acknowledgeEdge never persists the acknowledged flag to storage.

- Payout: Contest reward
- Severity: medium
- Program: Titles
- Credited: 4rdiii
- Disclosed: 2024-04-17
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-04-titles-judging/issues/212
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-04-titles%3AM-5
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:business-logic

**Target:** TitlesGraph Solidity contract (acknowledgeEdge/_setAcknowledged)
**Root cause:** _setAcknowledged declares its return variable as `Edge memory edge` and assigns `edges[edgeId_]` into it, so the `acknowledged` mutation only touches the memory copy and is discarded after the call.
**Steps:**
1. Deploy TitlesGraph and create an edge via `createEdge(from, to, "")` from the `from` node entity.
2. Call `acknowledgeEdge(keccak256(abi.encode(from, to)), "")` as the `to` node creator.
3. Read back `titlesGraph.edges(getEdgeId(from, to))` and observe `acknowledged == false`.
4. Fix: change return type to `Edge storage edge` so the assignment aliases storage.
**How found:** Code reading of _setAcknowledged: noticed the return variable was declared `memory` while being assigned from `edges[edgeId_]`, then wrote a Foundry test asserting the acknowledged flag persists and saw it fail.
**Insight:** In Solidity, assigning a storage struct to a `memory` local/return variable silently copies it; any mutation is lost. Grep for `memory` return types on internal setters that assign from a mapping and mutate a field.
