Using triggers to handle expiration dates

Can I use triggers and MHeartBeat to implement an expiration check based on a contract attribute?

I.e. I would like to archive contracts that expires at a certain date.


You can absolutely do this! In your rule, you can use getTime to get the current time and then compare it to the expiration date on the contract and archive it based on that. The heartbeat will ensure that you check at least as often as the heartbeat even if there are no other ACS changes that would send events to your trigger.

There are a few examples of these time-based triggers in the finlib, e.g, lib-finance/Entitlement.daml at a2387fe3b690301a133254ac4d9eb5eb9bfccf17 · digital-asset/lib-finance · GitHub


It’s important to keep potential race conditions in mind, though. For example, suppose a contract expires at 2021-05-04T18:42:00.000Z. Suppose that you manage to have a trigger submit an archival of the contract at exactly that moment. Between that moment and acceptance of the archival, another ACS query may still see that contract, or another client may attempt to exercise a choice on the contract. And this unwelcome order of events is even likelier if your archival comes some time after the actual expiration time.

As a result, it’s better to think of trigger-based expiry as a “garbage collection” process, where the choices on the contract consider it “marked for GC but not yet swept” if the expiry time has passed. As with GC, you can tune the GC-time/ACS-cleanliness trade-off by tuning the heartbeat frequency. To enforce this, each choice for which expiry is relevant should still check the expiry time defensively.