Daml vs Solidity audits: 3 scope decisions before a security review
Hi all,
We published a piece on how scoping a Daml security review differs from scoping an EVM audit. Every audit starts with understanding how the application executes, manages state and authorizes actions, and on Canton each of those works differently. Here are the three decisions, in short:
1. Review Daml’s authorization model
In Solidity, access control lives in code, and the reviewer traces it through execution paths. In Daml, signatories, observers and controllers are declared in the template, and the protocol enforces them. They can’t be bypassed through API manipulation. So part of the access-control analysis moves into the template model.
template Contact
with
owner : Party
party : Party
address : Text
telephone : Text
where
signatory owner
observer party
choice UpdateTelephone
: ContractId Contact
with
newTelephone : Text
controller owner
do
create this with
telephone = newTelephone
A Daml Script test confirms that a party who isn’t the controller can’t exercise the choice:
submitMustFail party do
exerciseCmd contactCid UpdateTelephone with
newTelephone = "098 7654 321"newTelephone
2. Define the coverage model
Daml test coverage measures templates created and choices exercised. It isn’t EVM-style path coverage. In the article’s example, the report shows 3 of 3 templates created (100%) but 2 of 5 choices exercised (40%). The 40% means two of the five defined choices were tested, nothing more.
3. Pin the SDK and Daml-LF target
Feature availability changes between versions. In the article’s test, a template with contract keys failed to compile under SDK 3.4.11 and compiled under SDK 3.5.2 with --target=2.3. The documentation you rely on also has to match the runtime you’re reviewing.
Scoping checklist
- Runtime: record the SDK version and Daml-LF target.
- Authorization: identify signatories, observers and controllers.
- Coverage: define what the test runner’s coverage figures measure.
- Feature behavior: tie security claims to the relevant documentation and runtime version.
- Testing methods: identify Daml and Canton methods separately from EVM techniques.
- Initial assessment: use an automated review, such as the Hacken AI Auditor, to map the security surface.
The resulting scope should describe the Daml ledger model, the application’s contract behavior, its party authorization rules, and the runtime-specific properties that affect security.
Full article with the code and test output:
HackenDaml vs Solidity Smart Contract Audits: 3 Scope Decisions for Researchers
A smart contract audit starts with understanding how the application executes, manages state, and authorises actions. Those assumptions differ between EVM-based applications and Daml applications running on Canton. Daml is a smart contract language...
The first decision is the one that changes most, and it changes in a direction that is easy to under-scope. Once the party set is declared in the template and the protocol enforces it, the bypass question mostly goes away. What is left is whether the declared set is the intended one.
Your own Contact template is a fair illustration. observer party means the counterparty reads address and telephone for as long as that contract is active. The protocol will enforce that faithfully, every time. Whether it should be true at all is a question about the business, and neither the compiler nor an execution path has a view on it.
So the two findings want different reviewers. Tracing execution finds a missing check. Reading the template against intent finds a controller that should not be there, or an observer that should not.
Your checklist has a line for identifying who the declared parties are. Does it have one for checking them against what the application is meant to permit, and who on the client side signs that off?
(post deleted by author)
No. That line does not belong on this list. The section is what you pin when you open daml.yaml. The file itself answers the SDK version and the --target. The other three ask the review to name the uniqueness page, the coverage metric, and which methods are imported. None of the five asks whether the declared party set matches the application’s requirements. That set is fixed by the requirements, and the client names the person who accepts it.
Interesting discussion. The distinction between declared authorization and intended authorization is particularly important.
Canton can correctly enforce the controllers, signatories and observers defined in a DAML model, but that doesn’t necessarily mean those parties reflect the business rules the application was intended to enforce.
This is one of the areas we’ve been exploring with Grisoco AI’s DAML/Canton security pipeline. We look at authorization in the context of the surrounding workflow and then, where applicable, replay authorization findings against a disposable Canton ledger.
The ledger replay gives us evidence about what Canton actually permits — while the review layer asks the separate question of whether it should have been permitted in the first place.
We’re still in beta and actively refining this approach, so I’d be interested in how others working on DAML security think this gap between declared authority, enforced authority, and intended authority should be validated in practice.
Fair, that sits with the requirements. It does make the requirements document something you would want pinned at scoping, the same way you pin the SDK version and the target. Without a named document that fixes the party set, the review can show the template is enforced. It has nothing to show the template is right against.