Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

Things I Learned Building with DAML: Notes on Privacy, RWAs, and Mental Models

27 July 2026 at 03:39

First in a series: “Things I learned while building with DAML.”

I came to Canton the way a lot of blockchain engineers do: sideways.

I’d spent a lot of time thinking in Solidity storage slots, msg.sender, reentrancy, ERC-20 approvals, the occasional ZK circuit when privacy mattered. Then I built a prototype of something institutions actually care about: tokenized gold custody, dual-signature vault attestations, compliance-gated escrow, and fund subscription/redemption on the Canton Network, using DAML and the CIP-56 token standard.

I expected another smart contract language with different syntax.

What I got was a different question.

Ethereum asks: *What does everyone agree on?*

Canton asks: *Who actually needs to agree?*

That shift completely changes how you model financial systems. This piece is about that shift and about being/ fair to both stacks when people reach for “Ethereum + ZK” versus “DAML on Canton” for real-world assets.

What I actually built (so this isn’t vapor)

Before the philosophy, the artifact.

The prototype covers a full custody-to-fund loop roughly like this:

- Vault layer: gold bars with serials, purity checks against system config, a serial registry (no contract keys Canton multi-domain reality), vault receipts for regulators.

- Operators & attestations: weighmaster + weigh device for dual-confirmed weight, assayers, transporters, auditors; permissions mapped exhaustively to attestation kinds.

- Token layer: GoldHolding implementing CIP-56 Holding / transfer-factory interfaces an issuance ledger so over-mint against a bar is structurally hard a small prototype CashHolding for settlement legs.

- Escrow propose → accept-and-fund → settle, with a list of compliance checks as data (KYC, limits, presence freshness, open movements, open discrepancies…).

- Fund ops share classes, NAV points, redemption gates, fees with banker’s rounding, in-kind redemption above a threshold.

- Off-ledger TypeScript connectors for NAV publishing, vault tablet attestations, and a thin ISO 20022 (setr.010/012) adapter.

The interesting part for an EVM person isn’t the feature list. It’s that almost every design decision was about parties, visibility, and workflows not about packing more logic into a globally visible bytecode blob.

Smart contracts are templates, not programs

One thing that surprised me about DAML: you don’t think in terms of “contracts” the way Solidity trains you to.

In Solidity, a contract is often a long-lived program with mutable storage. You deploy it once. Callers poke functions. State variables update in place.

In DAML, you define templates schemas for agreements between parties. Creating a contract instantiates an agreement. Exercising a choice advances it. Many choices archive the old contract and create a new one. The ledger isn’t a bag of storage slots; it’s a set of active agreements with lifecycles.

It feels closer to modeling a business process or even, oddly, closer to HTML than to writing EVM bytecode. You describe who must sign, who may see, who may act. The runtime enforces that description.

Here’s a tiny slice from the vault layer:

template GoldBar
with
custodian : Party
regulator : Party
serialNumber : Text
weightGrams : Decimal
purity : Decimal
vaultLocation : Text
custodianRef : Text
where
signatory custodian
observer regulator
ensure weightGrams > 0.0

The custodian must authorize creation. The regulator can see the bar without being able to invent one. Purity thresholds against system config live in the registering choice because ensure can’t fetch other contracts but the authorization shape is already visible in the template.

Contrast the EVM reflex:

// Everyone who can call sees the same storage.
// Visibility is not part of the type; access control is bolted on.
mapping(bytes32 => GoldBar) public bars;
function registerBar(…) external onlyCustodian {
bars[serial] = GoldBar(…);
}

Both can be correct. They encode different defaults about who the system is for.

Solidity teaches you to think like a VM.

DAML teaches you to think like a lawyer drafting an agreement that happens to execute.

That was the biggest mindset shift for me.

Explicit parties beat ambient msg.sender

In Solidity, authorization often collapses to:

require(msg.sender == custodian);

In DAML, the language gives you three distinct roles in the model itself:

- signatory: must authorize creation (and typically archival consequences)

- observer: can see the contract without controlling it

- controller: may exercise a particular choice

Escrow settlement isn’t “anyone who knows the address.” It’s this buyer, under these checks, before this expiry, with cash-issuer authority threaded explicitly when holdings are archived because DAML authority doesn’t magically transit through nested fetches the way a careless Solidity onlyOwner might pretend to.

That verbosity is a feature when you’re modeling custody, dual control, and regulated observers. It’s overhead when you want a two-line meme coin.

Different optimization targets.

Shared execution vs shared agreements

Ethereum asks: what does everyone agree on?

DAML asks: who actually needs to agree?

That one-line swap is the whole article, if you’re in a hurry.

Ethereum optimizes for shared execution.

One canonical state. One global truth. Anyone can re-execute the same transaction history (in principle) and land on the same balances. That’s why DeFi composability feels magical: your vault can trust Uniswap’s pool the way it trusts math because both live in the same transparent machine.

DAML / Canton optimizes for shared agreements.

There isn’t a single global RPC that returns the world state. Each participant node sees the contracts it’s entitled to see. Settlement is about getting the right parties to the same conclusion on the slice of state they share not about broadcasting every position to every stranger on the network.

When we wrote end-to-end privacy scripts for the gold prototype, the assertions weren’t “the chain shows X.” They were:

- Investor B sees none of investor A’s holdings, subscriptions, or KYC contracts.

- The regulator sees vault-layer facts without seeing investor cash books.

- The custodian doesn’t get NAV methodology internals beyond what’s disclosed.

Banks rarely want global transparency. They want shared truth between the parties involved and a clean story for supervisors who are observers.

That doesn’t make Ethereum wrong. It makes “public by default” a product choice with consequences.

Privacy by default vs privacy as an add-on

On Ethereum, privacy is something you add.

- Private mempools and encrypted orderflow for MEV.

- ZK proofs so you can convince a public verifier of a private statement.

- FHE so you can compute on ciphertext when even intermediate plaintext is too hot.

Those are serious technologies. They’re also expensive in engineering surface area: circuits, provers, trusted setups or transparent alternatives, key management, auditability of the crypto, gas, latency.

In DAML, visibility is part of the data model from day one. If you’re not a stakeholder on a contract, you don’t get the payload. Privacy isn’t a bolt-on proving system; it’s how the ledger partitions knowledge.

Neither approach is free.

A fairer unpack of the add-ons:

ZK on EVM is not “DAML but worse.” It’s a different primitive. You keep a public settlement substrate and attach a proof that a private computation or private data satisfies a public predicate. That’s incredibly powerful when strangers must coordinate: LPs in a pool, holders of a tokenized fund share trading on an open venue, journalists checking a reserve claim. The cost is real circuits, prover ops, audit surface but the social payoff is “the market can verify without being invited into the room.”

FHE on EVM (or adjacent confidential compute) attacks a harder problem: let multiple parties compute on encrypted inputs without decrypting mid-flight. Think sealed-bid auctions, confidential risk scoring, or shared analytics over positions nobody wants to reveal. It’s earlier than ZK for production RWA stacks, and the performance/ops tax is steep. When it matures, it will matter most where even the operators shouldn’t see plaintext something DAML’s stakeholder model doesn’t automatically give you if a party is itself a curious intermediary.

DAML’s privacy is closer to “need-to-know messaging with enforceable rights” than to “ciphertext on a public bulletin board.” That’s usually what a custodian, fund admin, and auditor want for operating the book. It is not automatically what a secondary market wants when price discovery depends on many anonymous participants trusting the same rules.

The question I hear too often is:

Should institutions use Ethereum + ZK?

Sometimes yes. A better question is often:

When does proving something publicly make more sense than simply sharing it privately?

If the audience that must be convinced is the open market holders, LPs, journalists, on-chain analysts ZK on a public substrate is a natural fit. Proof of reserves. Solvency. Correctness of a dark-pool matching rule without revealing orders.

If the audience that must be convinced is the counterparties and the regulator and everyone else should see nothing DAML’s need-to-know model is often the shorter path. You’re not proving a statement to the world; you’re sharing the agreement with the people in the agreement.

Both are “privacy.” They answer different social questions.

Finality, not TPS

Crypto Twitter obsesses over throughput.

Institutions obsess over deterministic settlement.

Did the DvP complete? Are both legs final? Can operations book it? Can legal point to a single outcome if something blows up at 4:01pm?

Canton is excellent at institution-to-institution settlement workflows for exactly that reason: the unit of design is the multi-party transaction over shared contracts, not “how many Uniswap swaps fit in a block.”

That doesn’t mean EVM chains can’t settle RWAs — they do, increasingly. It means if your KPI is TPS theater, you’re measuring the wrong thing for custody and fund ops. If your KPI is *irreversible agreement among the right parties*, you’re closer to how banks already think.

When each stack is interesting for RWAs

Fairness means naming wins on both sides.

Prefer DAML / Canton when…

- The workflow is multi-party and regulated: custodian, investor, fund manager, auditor, transporter.

- Disclosure is asymmetric by law or policy (regulator sees vault; peer investor must not see your book).

- You need lifecycle fidelity proposals, acceptances, expiries, dual control, consuming choices that map to “this agreement is done.”

- Privacy is a requirement, not a roadmap item.

- Counterparties are known legal entities, not anonymous addresses competing in a public mempool.

Our gold prototype lived here: presence freshness that can “self-freeze” settlement if attestations go stale; movement checks that block escrow while a bar is in transit; discrepancy reports that halt site settlement until write-down or resolve. Those are *process* controls. They want to be first-class in the model.

Prefer public EVM (and EVM + ZK) when…

- You need permissionless secondary markets and DeFi collateral composability.

- Success depends on anyone integrating wallets, aggregators, lending markets without bilateral onboarding.

- You must prove a fact to the world (reserves, NAV integrity, compliance predicates) while keeping underlying data hidden ZK shines.

- Retail distribution and liquidity bootstrapping matter more than bilateral confidentiality.

Prefer hybrid when…

- Primary issuance and institutional ops need private shared state, but public representation or a ZK attestation of that state feeds open markets.

- You want Canton (or similar) for the agreement layer and an EVM venue for the liquidity layer with a deliberately designed bridge and disclosure policy.

Hybrid is where a lot of serious RWA architecture is heading. Tribal “EVM vs DAML” posts miss that.

Concrete lessons from the gold build

A few engineering notes that stuck.

1. Compliance as data, not as a rewrite

Escrow took a list of compliance check contract IDs. The same escrow template settled with [KYC, Limit] and failed with [KYC, Limit, Presence] when presence was stale without changing Escrow.daml.

On EVM you’d reach for a strategy pattern or a modular hook. it’s doable. In DAML it felt native: the agreement says “run these checks,” and checks are themselves agreements with providers and subjects.

2. Dual-signature weight

A weight attestation wasn’t “confirmed” until a human weighmaster and a weigh device agreed within tolerance and the same attestor twice was rejected. Dual control isn’t a comment in a PR; it’s a template choice with negative tests.

3. Tokens that can freeze themselves

Pass time beyond attestationMaxAge with no fresh presence attestation and settlement paths that require PresenceFreshnessCheck fail. Fresh attestation unlocks them again. That’s operational reality for physical gold, encoded as workflow not as an admin pause() god-key (though god-keys exist in many EVM systems for worse reasons).

4. CIP-56 as the ERC-20 mindset bridge

Coming from ERC-20, CIP-56’s Holding / TransferInstruction interfaces were the familiar part: standardize how wallets and apps talk to holdings without caring which registry implemented them. The unfamiliar part was everything around who sees the holding.

Consuming choices (a favorite concept)

Exercising a choice can archive a contract and create its successor.

That’s closer to how legal agreements evolve “this SOW is superseded by amendment #3” than to

balances[alice] -= x; 
balances[bob] += x;

in place. Escrow that settles doesn’t flip a status = Settled enum in eternal storage (though you can model that). It consumes the escrow agreement and produces the resulting holdings under new owners. Failed settle leaves both legs intact partial state is a bug you test for.

Once you see consuming choices, a lot of DAML design clicks. Once you miss them, you write DAML like Solidity and fight the language.

What DAML is not (yet) great at

Honesty matters if you want engineers to trust the comparison.

- Ecosystem gravity. Most crypto talent, tooling, auditors, and memes are EVM-native. Hiring and open-source velocity still favor Solidity.

- Permissionless composability. Uniswap-style “plug any token into any pool” is not Canton’s home game. If your RWA product’s moat is DeFi money legos, start on EVM (with ZK where needed) and be honest about disclosure.

- Retail UX myths. Canton is excellent at institution-to-institution settlement. The interesting question isn’t whether that works it does for the workflows it’s built for. It’s whether the same principles can eventually simplify payments for everyone else. That’s a product and policy problem, not a language flex.

- Public verifiability without disclosure. If your stakeholder is “the internet,” ZK on a public L1/L2 is often clearer than explaining participant-local ledgers.

- Tooling familiarity. Foundry, Hardhat, Tenderly, open auditors — EVM engineers drown in options. DAML’s loop (SDK, Script, LocalNet, JSON Ledger API) is coherent, but smaller. Expect a learning tax; budget for it.

None of that makes DAML “worse.” It makes it specialized. Specialization is how serious infrastructure usually wins.

And the reverse honesty: public EVM is not “institutions can’t use this.” They can and do especially when liquidity, distribution, or public attestation dominate. Pretending banks only want Canton is as unserious as pretending every gold custody workflow belongs on a public mempool.

Mental models, not tribal banners

Instead of Ethereum vs DAML, compare the lenses:

Ethereum optimizes for shared execution.

DAML optimizes for shared agreements.

They sound similar. They’re solving different problems.

I’m not done with either. The more I work on RWAs, the more I believe the interesting systems will be bilingual: public where the market must see or verify, private where the counterparties must settle.

If you write Solidity and you’ve never modeled a multi-party workflow in DAML, try one thin vertical escrow with two compliance checks, or a dual-control attestation and notice what becomes easy and what becomes annoying. That annoyance is usually a clue about which problem you were actually solving.

What’s next in this series

Topics I want to dig into next, still from an Ethereum engineer’s notebook:

1. Consuming choices as a first-class design tool (with escrow war stories).

2. Parties vs accounts and why allocateParty` feels alien until it doesn’t.

3. Finality and deterministic settlement what institutions measure that TPS dashboards ignore.

4. CIP-56 for ERC-20 natives mappings, traps, and where the analogy breaks.

If this was useful, model one RWA workflow both ways and tell me which lies you had to tell each stack.

That’s usually where the real architecture starts.


Things I Learned Building with DAML: Notes on Privacy, RWAs, and Mental Models was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

❌
❌