|  | 
|  | 1 | +# Durable Contract Details | 
|  | 2 | + | 
|  | 3 | +Zoe allows you to write smart contracts that manage interactions between cooperative, but possibly untrusting, | 
|  | 4 | +parties. Some contracts perform a single simple task like trading one good for another, and then are | 
|  | 5 | +done. Others stay around and manage assets and interactions over time. The first kind don't need persistence | 
|  | 6 | +or the ability to upgrade, while the second kind need to make use of more sophisticated functionality. | 
|  | 7 | + | 
|  | 8 | +When a contract is intended to continue running and serving many customers over a long time, its objects and | 
|  | 9 | +data need to be persistent, its owners or managers may need to be able to adjust parameters or perform other | 
|  | 10 | +governance actions, and it needs to be upgradeable so that the code can adapt over time. | 
|  | 11 | + | 
|  | 12 | +## Durable Objects | 
|  | 13 | + | 
|  | 14 | +The first step toward contracts that can be upgraded is storing all the data that a later incarnation will | 
|  | 15 | +need. This means putting relevant state in | 
|  | 16 | +[Baggage](http://localhost:5173/guides/zoe/contract-upgrade.html#baggage), and ensuring that reachable objects | 
|  | 17 | +that will be accessible to users have an identity that can be maintained as the behavior changes with contract | 
|  | 18 | +upgrades. | 
|  | 19 | + | 
|  | 20 | +We use zone.exo(), zone.exoClass(), and zone.exoClassKit() to  define durable objects.  | 
|  | 21 | + | 
|  | 22 | +[Zone](http://localhost:5173/glossary/#zone) provides an interface for defining objects and classes that | 
|  | 23 | +supports both ephemeral objects (allocated on the heap), and durable objects that can persist and that | 
|  | 24 | +SwingSet will page in or out on demand. | 
|  | 25 | + | 
|  | 26 | +Our persistent objects are designed to encapsulate their state, and can present different facets to different | 
|  | 27 | +clients to distinguish different aspects of authority. `zone.exoClass()` defines a kind with a single facet, | 
|  | 28 | +while `zone.exoClassKit()` defines a kind with multiple facets. (Here are some relevant [naming | 
|  | 29 | +conventions](https://docs.agoric.com/guides/ertp/#method-naming-structure).) | 
|  | 30 | + | 
|  | 31 | +``` | 
|  | 32 | +zone.exoClassKit(tag, guard, init, methodKit, options) | 
|  | 33 | +zone.exoClass(tag, guard, init, methods, options) | 
|  | 34 | +zone.exo(tag, guard, methods, options) | 
|  | 35 | +``` | 
|  | 36 | + | 
|  | 37 | +The next several sub-sections explain how the parameters to those functions are used. | 
|  | 38 | + | 
|  | 39 | +### Tag: naming kinds of objects | 
|  | 40 | + | 
|  | 41 | +The `tag` provides the identity of the kind of object, which is associated with the defined behavior. When a | 
|  | 42 | +contract (or other vat) is restarted or upgraded, SwingSet requires that all kinds that were previously | 
|  | 43 | +defined in a vat be defined again. With an upgrade, the behavior can be changed. We use the term "null | 
|  | 44 | +upgrade" to refer to upgrades that don't change the behavior. | 
|  | 45 | + | 
|  | 46 | +### Init: specifying state | 
|  | 47 | + | 
|  | 48 | +The `init` parameter defines a function that is used to define the state associated with each instance of an | 
|  | 49 | +object. Notice that `exo()` doesn't take `init` as a parameter; this limits the defined (singleton) object to | 
|  | 50 | +referencing values defined in the enclosing scope. Classes can also refer to variables in their defining | 
|  | 51 | +scope, but any values inherited from the scope will be accessible to all instances of that type. The `init` | 
|  | 52 | +function's parameters become the parameters of the maker function returned by `exoClass()` and | 
|  | 53 | +`exoClassKit()`.  `init`'s return value is the state that will be preserved by SwingSet for each | 
|  | 54 | +object. `exo()` doesn't have an init parameter, so it creates and returns the singleton immediately rather | 
|  | 55 | +than returning a maker. | 
|  | 56 | + | 
|  | 57 | +The Exo objects (or just "Exos") defined by these functions are both persistent and virtualizable. SwingSet | 
|  | 58 | +knows their complete state, so it can page them out when space is tight, and page them back in when they are | 
|  | 59 | +referenced again. | 
|  | 60 | + | 
|  | 61 | +Fields of the object returned by the `init` function become fields of the persistent state. (These cannot | 
|  | 62 | +currently be changed on upgrade, though we're considering relaxing that restriction.) Within methods they can | 
|  | 63 | +each be accessed as fields of `this.state`. Our convention is to extract the fields that will be used in a | 
|  | 64 | +method on its first line, like `const { a, b } = this.state;` Once that has been done, those variable can be | 
|  | 65 | +read or written as normal javascript variables, and the values will persist. (For more details, see [the note | 
|  | 66 | +here](https://docs.agoric.com/guides/zoe/contract-upgrade.html#kinds)). | 
|  | 67 | + | 
|  | 68 | +### Methods: defining behavior | 
|  | 69 | + | 
|  | 70 | +The methods argument of `exoClass()` is a bag of methods, written in [concise method | 
|  | 71 | +syntax](https://github.com/Agoric/agoric-sdk/wiki/Arrow-Function-Style#far-classes-do-not-use-arrow-function-style). | 
|  | 72 | +`exoClass()` defines a single facet. | 
|  | 73 | + | 
|  | 74 | +The methodKit parameter to `exoClassKit` is a record of labelled bags of methods. Each label defines a facet | 
|  | 75 | +of the object. All facets of each object share access to the same state, but each facet is a separate | 
|  | 76 | +capability. Within the methods, other facets can be reached by name within `this.facets`. The maker you get | 
|  | 77 | +from `exoClassKit()` builds a new object each time it is called, and return all the facets. The caller can | 
|  | 78 | +decide which of the facets to pass to each recipient. | 
|  | 79 | + | 
|  | 80 | +### Guards: defensive methods | 
|  | 81 | + | 
|  | 82 | +These objects and facets are designed to be durable and shareable across address space boundaries. Since code | 
|  | 83 | +in different vats might not be mutually trusting, code needs to be defensive about parameters received from | 
|  | 84 | +remote callers. Interface Guards let us express in code what parameters each method expects and can handle | 
|  | 85 | +safely. If a caller provides a parameter that doesn't match the template specified in the guard, SwingSet | 
|  | 86 | +returns an exception to the caller without notifying the receiver. If the return value doesn't match, the | 
|  | 87 | +function returns an exception to the caller. | 
|  | 88 | + | 
|  | 89 | +`exoClass()` takes a guard for a single interface, defined by | 
|  | 90 | + | 
|  | 91 | +``` | 
|  | 92 | +M.interface('name', { | 
|  | 93 | +  methodA: M.call(paramsAShape).returns(resultAShape), | 
|  | 94 | +  methodB: M.callWhen(M.await(paramsBShape)).returns(resultBShape), | 
|  | 95 | +} | 
|  | 96 | +``` | 
|  | 97 | + | 
|  | 98 | +`M.call()` verifies that all parameters match the guard before passing them through to the | 
|  | 99 | +method. `M.callWhen(M.await(paramsBGuard))` awaits the resolution of the parameter, and then verifies that the | 
|  | 100 | +result matches before invoking the method. When a guard is written this latter way, the method doesn't have to | 
|  | 101 | +be `async`. In both cases, the method  doesn't have to check for compliance with the guard. | 
|  | 102 | + | 
|  | 103 | +[Shapes can specify](https://endojs.github.io/endo/interfaces/_endo_patterns.PatternMatchers.html) simple | 
|  | 104 | +types like `M.string()`, `M.remotable()`, and `M.number()`, as well as complex structures of records and | 
|  | 105 | +arrays. The list of parameters can specify required and optional parameters, as well as allowing unspecified | 
|  | 106 | +rest parameters. | 
|  | 107 | + | 
|  | 108 | +If you want to make use of the power of this type-checking within methods, you can call `mustMatch(specimen, | 
|  | 109 | +pattern)` or `matches(specimen, pattern)` directly. The former throws if the pattern doesn't match, while the | 
|  | 110 | +latter returns a boolean. | 
|  | 111 | + | 
|  | 112 | +### Options: finish and stateShape | 
|  | 113 | + | 
|  | 114 | +All the type definers can also take an [options | 
|  | 115 | +argument](https://endojs.github.io/endo/types/_endo_exo.FarClassOptions.html) at the end, which is commonly | 
|  | 116 | +used for a `finish()` function to complete initialization, or a stateShape, which can enforce invariants on | 
|  | 117 | +the state values. | 
|  | 118 | + | 
|  | 119 | +`finish()`, if provided, is called after instances have been created but before they are returned to the | 
|  | 120 | +caller. They can be used to send an initial state update, or to complete initialization which couldn't be done | 
|  | 121 | +in `init`. `finish` has access to state and facets if needed. | 
|  | 122 | + | 
0 commit comments