Technical
The Loam diamond, described in the terms a reviewer checks it in: which facets are actually deployed, what each one can call, who can call it, and how the pieces are wired together. The facet map below is read live from the diamond's own loupe, never copied from a deployment record โ an upgrade changes what is live, not what a doc says.
Facets
Every facet currently cut into the diamond, read live via IDiamondLoupe.facets(). A deployment record captures a moment; this call captures now.
Functions
The read surface any integrator or reviewer needs, with real signatures โ call these directly against the diamond address in the panel below with cast call or any ABI-aware client. previewMint and previewRedeem change no state: they can be called before signing anything, to see the exact result a mint or redeem would produce.
Access control
Every upgrade to the diamond runs through one path, verified on chain rather than assumed from convention. DiamondCutFacet.diamondCut calls LibDiamond.enforceIsContractOwner() before it does anything else (src/diamond/facets/DiamondCutFacet.sol:23), and the diamond's own owner() returns the TimelockController address below โ not a wallet, not the Safe directly.
The Safe holds PROPOSER_ROLE on the timelock, and it holds EXECUTOR_ROLE too โ it is the only executor, and the zero address does not hold that role, so execution is not open to the public. Holding it shortens nothing: the timelock refuses to execute a queued proposal until its 48-hour delay has elapsed, so the Safe cannot execute a change before the delay runs. When the delay has run, the account that calls diamondCut is the timelock itself โ it is the diamond's owner(), and therefore msg.sender to the cut. There is no direct-call path from the Safe, the canceller, the guardian, or anywhere else to diamondCut that bypasses the timelock.
The canceller and the guardian are not independent parties. getOwners() on the Safe returns three signers with a threshold of 2, and two of those signers are the canceller and guardian addresses published above. These are role separations inside one signer set, not separate organisations. One call exposes it, so it is stated here rather than left to be found.
Two classes of privileged action do not run through the timelock at all. AdminFacet.latchRedemption(string) and AdminFacet.latchMint(string) are onlyRole(GUARDIAN_ROLE): the guardian can halt every redemption, or every mint, immediately and with no delay. Each requires a non-empty reason string, which is emitted on-chain with the latch, and the Safe can lift a latch โ also immediately. Separately, AdminFacet carries a set of parameter setters gated on DEFAULT_ADMIN_ROLE, which the Safe holds, and those take effect the moment they are called: the cushion floor and ceiling, the performance fee, the referrer, the Field exposure cap, the earmark ceiling, the max swap slippage, the stem-scan budget, and disableVenueDivergenceGate (that last one is callable by the guardian as well). They change parameters, not code. What the 48-hour delay covers is diamondCut itself, role grants, the mint and redeem fees, the venue, and devAddr.
Separately, the vLOAM staking contract has no equivalent chain to trace, because there is nothing upgradeable in it to trace:
There is no owner, no pause function, no setter, and no proxy on the vLOAM contract. Nothing can change the staking curve after deployment, and nothing can drain custody through an admin function, because no such function was written.
Naming
The deployed contracts still say "Surco" โ the interfaces are named ISurco, and the current, live NAV function is navPintoPerSurco(), not a renamed equivalent. This is not evidence of a fork of someone else's work; it is the same codebase carried forward under a new brand.
The rename to Loam was deliberately not applied at the contract level. An external function's name is compiled into its 4-byte selector โ renaming navPintoPerSurco() to, say, navPintoPerLoam() would produce a different selector, which every integrator, indexer, and script currently calling the old one would silently stop matching. Relabeling the brand at the expense of breaking every existing integration at once was rejected in favor of leaving the ABI alone. The rename lives in the product name, the token symbol where applicable, and the docs โ not in function selectors.
Proxy pattern
The token's page on Basescan does not resolve facet reads or show a "Read as Proxy" tab the way a typical upgradeable token does. This is a detector gap, not a hidden contract: Etherscan's (and Basescan's) automatic proxy detector is built for EIP-1967, the single-implementation-slot proxy standard. The Loam diamond is an EIP-2535 diamond, which routes different function selectors to different facet contracts through IDiamondLoupe rather than one implementation slot โ a pattern the EIP-1967 detector was never written to recognize.
It would be possible to point Basescan's proxy detector at a single facet to force it to resolve โ but doing so would publish that one facet's ABI as if it were the whole token's, misrepresenting a multi-facet contract as a single-implementation one. That is deliberately not done. The correct way to read the diamond's real function surface is IDiamondLoupe.facets(), shown live at the top of this page, or the individual facet addresses it returns.
vLOAM
vLOAM is non-transferable by design, and a non-transferable balance emits no Transfer events โ staking and unstaking never call the ERC-20 Transfer event because there is no transfer to log. Any indexer or portfolio tool that builds balances purely from Transfer logs will show zero vLOAM for every holder. That absence is the correct, expected behavior of the contract, not a bug or a sign of a broken integration.
To read vLOAM correctly: call balanceOf(address) directly against the contract, or index the events it actually emits โ Staked, Withdrawn, and Settled โ rather than Transfer.