Skip to main content
Last updated

Guards

create-capability-guard

Use create-capability-guard to create a predicate function that ensures that specific conditions are true and can be enforced to grant the specified CAPABILITY.

By convention, capabilities are defined using all uppercase letters.

Basic syntax

To create a predicate function that guards the specified CAPABILITY, use the following syntax:

pact
(create-capability-guard CAPABILITY)
pact
(create-capability-guard CAPABILITY)

Arguments

Use the following argument to specify the CAPABILITY for the create-capability-guard Pact function.

ArgumentTypeDescription
CAPABILITYcapabilitySpecifies the capability that the predicate function guards.

Return values

The create-capability-guard function returns a guard that enforces the acquisition of the specified CAPABILITY.

Examples

The following example demonstrates how to use the create-capability-guard function to create a guard for the GOVERNANCE capability:

pact
(defun create-gas-payer-guard:guard()    (create-capability-guard (GOVERNANCE)))
pact
(defun create-gas-payer-guard:guard()    (create-capability-guard (GOVERNANCE)))

The conditions specified for the GOVERNANCE capability must evaluate to true for the capability to be acquired and related code where the capability is required to be executed.

The following example illustrates how to create a guard for an ESCROW_MANAGEMENT account:

pact
(defconst ESCROW_ID    (create-principal      (create-capability-guard (ESCROW_MANAGEMENT))    )    "The escrow will hold all KDA in circulation on the chain")
pact
(defconst ESCROW_ID    (create-principal      (create-capability-guard (ESCROW_MANAGEMENT))    )    "The escrow will hold all KDA in circulation on the chain")

create-capability-pact-guard

Use create-capability-pact-guard to create a predicate function that ensures that specific conditions are true and can be enforced to grant the specified CAPABILITY for steps defined in a defpact multi-step transaction.

By convention, capabilities are defined using all uppercase letters.

Basic syntax

To create a predicate function that guards the specified CAPABILITY in a defpact multi-step transaction, use the following syntax:

pact
(create-capability-pact-guard CAPABILITY)
pact
(create-capability-pact-guard CAPABILITY)

Arguments

Use the following argument to specify the CAPABILITY for the create-capability-pact-guard Pact function.

ArgumentTypeDescription
CAPABILITYcapabilitySpecifies the capability that the predicate function guards.

Return values

The create-capability-pact-guard function returns a guard that enables the code associated with the specified CAPABILITY to be executed in the context of a defpact multi-step transaction.

Examples

The following example demonstrates how to use the create-capability-pact-guard function to create a guard for the ESCROW owner capability in adefpact step:

pact
(create-capability-pact-guard (ESCROW owner))
pact
(create-capability-pact-guard (ESCROW owner))

The following example creates a guard for the SALE_PRIVATE capability associated with the pact-id for the sales contract being executed:

pact
  (defun offer:bool    ( id:string      seller:string      amount:decimal    )    @doc "Initiate sale with by SELLER by escrowing AMOUNT of TOKEN until TIMEOUT."    @model      [ (property (!= id ""))        (property (!= seller ""))        (property (>= amount 0.0))      ]    (require-capability (SALE_PRIVATE (pact-id)))    (let      (        (sender (debit id seller amount))        (receiver (credit id (sale-account) (create-capability-pact-guard (SALE_PRIVATE (pact-id))) amount))      )      (emit-event (TRANSFER id seller (sale-account) amount))      (emit-event (RECONCILE id amount sender receiver)))  ) 
pact
  (defun offer:bool    ( id:string      seller:string      amount:decimal    )    @doc "Initiate sale with by SELLER by escrowing AMOUNT of TOKEN until TIMEOUT."    @model      [ (property (!= id ""))        (property (!= seller ""))        (property (>= amount 0.0))      ]    (require-capability (SALE_PRIVATE (pact-id)))    (let      (        (sender (debit id seller amount))        (receiver (credit id (sale-account) (create-capability-pact-guard (SALE_PRIVATE (pact-id))) amount))      )      (emit-event (TRANSFER id seller (sale-account) amount))      (emit-event (RECONCILE id amount sender receiver)))  ) 

create-module-guard

Use create-module-guard to create a predicate function with the specified name that ensures that specific conditions are true for the current module.

Module guards are typically used to enable a module to perform administrative operations independently outside of the module itself, for example, to own coins in an external ledger, or to perform administrative operations internally on its database, for example, to own and manage certain assets.

Basic syntax

To define a predicate function name that guards administrative activity for the current module, use the following syntax:

pact
(create-module-guard name)
pact
(create-module-guard name)

Arguments

Use the following argument to specify the name for the create-module-guard Pact function.

ArgumentTypeDescription
namestringSpecifies the name of the predicate function that guards administrative activity for the current module.

Return values

The create-module-guard function returns a guard with the specified namethat enables the current module to perform administrative operations.

Example

The following example demonstrates how to use the create-module-guard function to define a guard named "module-admin-guard" for the current module:

pact
(create-module-guard "module-admin-guard")
pact
(create-module-guard "module-admin-guard")

If the evaluation of the module-admin-guard returns true, the current module is granted administrative privileges.

create-pact-guard

Use create-pact-guard to define a predicate function with the specified name that captures the results of the pact-id function for a defpact transaction.

When enforced, the guard will only return true if the pact-id at enforcement is the same as the pact-id captured by the create-pact-guard function. This check ensures that the guard will only succeed within the multi-step transaction identified by the pact-id.

Basic syntax

To define a predicate function by name that captures the results of the pact-id function, use the following syntax:

pact
create-pact-guard name
pact
create-pact-guard name

Arguments

Use the following argument to specify the name for the create-pact-guard Pact function.

ArgumentTypeDescription
namestringSpecifies the name of the predicate function that captures the pact-id for a defpact multi-step transaction.

Return values

The create-pact-guard function returns a guard with the specified name that captures the pact-id' for a defpact multi-step transaction.

Example

The following example demonstrates how to use the create-pact-guard function to define a guard named "pact-id-guard" that captures the pact-id' for a defpact multi-step transaction:

pact
(create-pact-guard "pact-id-guard")
pact
(create-pact-guard "pact-id-guard")

This guard ensures that it will only succeed within the multi-transaction identified by the pact id.

create-principal

Use create-principal to create a principal account that unambiguously identifies a specified guard predicate function.

For an introduction to principal accounts, see Accounts, keys, and principals.

Basic syntax

To create a principal that identifies a guard predicate function, use the following syntax:

pact
create-principal guard
pact
create-principal guard

Arguments

Use the following argument to specify the guard for the create-principal Pact function.

ArgumentTypeDescription
guardguardSpecifies the guard for which to create a principal.

Return values

The create-principal function returns a string representing a principal that unambiguously identifies the specified guard predicate function.

Example

The following example demonstrates how to use the create-principal function to create a principal that unambiguously identifies the keyset guard:

pact
(create-principal (read-keyset 'keyset))
pact
(create-principal (read-keyset 'keyset))

This principal can then be used for various purposes such as access control in Pact code.

create-user-guard

Use create-user-guard to define a custom guard closure whose arguments are strictly evaluated at definition time and supplied to the indicated function at enforcement time.

Basic syntax

To define a custom guard closure for use in Pact, use the following syntax:

pact
(create-user-guard closure)
pact
(create-user-guard closure)

Arguments

Use the following argument to specify the closure for the create-user-guard Pact function.

ArgumentTypeDescription
closureclosureSpecifies the custom guard closure to define. The closure is a function that takes no arguments and returns a boolean value.

Return values

The create-user-guard function returns a guard that uses the specified custom closure function that returns a boolean value.

Example

The following example demonstrates how to use the create-user-guard function to obtain a keyset, then use the keyset as a custom guard closure function:

pact
(create-user-guard (read-keyset 'my-keyset))
pact
(create-user-guard (read-keyset 'my-keyset))

In this example, (read-keyset 'my-keyset) is used as the closure function to capture a keyset to use when the user guard is enforced. This code allows you to define custom user guards based on specific keysets or conditions.

The following example defines a user guard for the enforce-fungible-transfer function that must evaluate to true to allow a fungible transfer:

pact
(defun escrow-guard(sale-id:string)   (util.guards1.guard-any [      (create-capability-guard (REFUND_CAP sale-id))      (create-user-guard (enforce-fungible-transfer sale-id))   ])) (defun enforce-fungible-transfer:bool (sale-id:string)   (require-capability (FUNGIBLE-TRANSFER-CALL sale-id) ))
pact
(defun escrow-guard(sale-id:string)   (util.guards1.guard-any [      (create-capability-guard (REFUND_CAP sale-id))      (create-user-guard (enforce-fungible-transfer sale-id))   ])) (defun enforce-fungible-transfer:bool (sale-id:string)   (require-capability (FUNGIBLE-TRANSFER-CALL sale-id) ))

is-principal

Use is-principal to determine whether a principal string conforms to the principal format without proving its validity.

Basic syntax

To check whether a principal string conforms to the principal format, use the following syntax:

pact
(is-principal principal)
pact
(is-principal principal)

Arguments

Use the following argument to specify the principal string you want to check using the is-principal Pact function.

ArgumentTypeDescription
principalstringSpecifies the principal string to be checked.

Return value

The is-principal function returns a boolean value indicating whether the specified principal string conforms to the principal format.

Examples

The following example demonstrates how to use the is-principal function in the Pact REPL to check whether the specified string conforms to the principal format:

pact
pact> (is-principal "k:58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c")true
pact
pact> (is-principal "k:58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c")true

The following example demonstrates how to use the is-principal function in an enforce statement:

pact
(defcap LOCK_DEPOSIT(sender:string)   (enforce (is-principal sender) "Sender must be a principal account"))
pact
(defcap LOCK_DEPOSIT(sender:string)   (enforce (is-principal sender) "Sender must be a principal account"))

In this example, the is-principal function ensures that the sender account conforms to the format for principal accounts. If the format is valid, the enforce statement returns true and the LOCK_DEPOSIT capability is granted. If the sender isn't a valid principal format, the enforce statement returns the "Sender must be a principal account" error message.

The following example checks the format of a principal account associated with a capability guard in an enforce statement:

pact
(enforce (is-principal "c:bF51UeSqhrSjEET1yUWBYabDTfujlAZke4R70I4rrH") "Invalid account structure: non-principal account")<interactive>:0:0:Error: Invalid account structure: non-principal account
pact
(enforce (is-principal "c:bF51UeSqhrSjEET1yUWBYabDTfujlAZke4R70I4rrH") "Invalid account structure: non-principal account")<interactive>:0:0:Error: Invalid account structure: non-principal account

In this example, the length of the specified string doesn't conform to the format for a principal account, so the enforce statement returns the error message.

keyset-ref-guard

Use keyset-ref-guard to create a guard for the keyset registered as keyset-ref using the define-keyset function. Concrete keysets are themselves guard types. This function is specifically to store references alongside other guards in the database.

Basic syntax

To create a guard for a keyset registered with the define-keyset function, use the following syntax:

pact
(keyset-ref-guard keyset-ref)
pact
(keyset-ref-guard keyset-ref)

Arguments

Use the following argument to specify the keyset reference for which you want to create a guard using the keyset-ref-guard Pact function.

ArgumentTypeDescription
keyset-refstringSpecifies the reference to the keyset registered with the define-keyset function.

Return value

The keyset-ref-guard function returns a guard type corresponding to the specified keyset reference.

Examples

The following example demonstrates how to use the keyset-ref-guard function to create a guard for the keyset registered as "my-keyset" using the define-keyset function:

pact
(keyset-ref-guard "my-keyset")
pact
(keyset-ref-guard "my-keyset")

typeof-principal

Use typeof-principal to return the protocol type of the specified principal value. If the specified value is not a principal type, then an empty string is returned.

Basic syntax

To determine the protocol type of a specified principal value, use the following syntax:

pact
(typeof-principal principal)
pact
(typeof-principal principal)

Argument

Use the following argument to specify the principal value that you want to determine the protocol type for using the typeof-principal Pact function.

ArgumentTypeDescription
principalstringSpecifies the principal value to determine the protocol type for.

Return value

The typeof-principal function returns the protocol type of the specified principal value as a string. If the input value is not a principal type, an empty string is returned.

Examples

The following example demonstrates how to use the typeof-principal function to determine the protocol type of a principal value:

pact
(typeof-principal "k:462e97a099987f55f6a2b52e7bfd52a36b4b5b470fed0816a3d9b26f9450ba69")"k:"
pact
(typeof-principal "k:462e97a099987f55f6a2b52e7bfd52a36b4b5b470fed0816a3d9b26f9450ba69")"k:"

The following example uses the typeof-principal function to create a namespace using the guard associated with the principal account name:

pact
(defun create-principal-namespace:string      ( g:guard        )    " Format principal namespace as Pact hash (BLAKE2b256) of principal \    \ in hex truncated to 160 bits (40 characters), prepended with 'n_'.\    \ Only w: and k: account protocols are supported. "     (let      ((ty (typeof-principal (create-principal g))))       ;; only w: and k: currently supported      (if (or (= ty "k:") (= ty "w:"))        (+ "n_" (take 40 (int-to-str 16 (str-to-int 64 (hash g)))))        (enforce false          (format "Unsupported guard protocol: {}" [ty]))        )))
pact
(defun create-principal-namespace:string      ( g:guard        )    " Format principal namespace as Pact hash (BLAKE2b256) of principal \    \ in hex truncated to 160 bits (40 characters), prepended with 'n_'.\    \ Only w: and k: account protocols are supported. "     (let      ((ty (typeof-principal (create-principal g))))       ;; only w: and k: currently supported      (if (or (= ty "k:") (= ty "w:"))        (+ "n_" (take 40 (int-to-str 16 (str-to-int 64 (hash g)))))        (enforce false          (format "Unsupported guard protocol: {}" [ty]))        )))

validate-principal

Use validate-principal to validate that a principal unambiguously identifies a specified guard.

Basic syntax

To validate a principal against guard, use the following syntax:

(validate-principal guard principal)

Arguments

Use the following arguments to specify the guard and the principal that you want to validate using the validate-principal Pact function.

ArgumentTypeDescription
guardguardSpecifies the guard to validate against.
principalstringSpecifies the principal to be validated.

Return value

The validate-principal function returns a boolean value indicating whether the provided principal unambiguously identifies the specified guard.

Examples

The following example demonstrates how to use the validate-principal function to ensure that the principal obtained from reading a keyset matches the specified principal account:

pact
(enforce (validate-principal (read-keyset 'keyset) account) "Invalid account ID")
pact
(enforce (validate-principal (read-keyset 'keyset) account) "Invalid account ID")

The following example uses validate-principal in a function to ensure the merchant and buyer accounts are guarded principal account:

pact
  (defun create-order (    order-id       : string    merchant       : string    merchant-guard : guard    buyer          : string    buyer-guard    : guard    order-price    : decimal  )    @doc "Creates an order in the order table and reserves funds to the escrow account"    (enforce (!= order-id "") "Order id can not be empty")    (enforce (< 0.0 order-price) "Order price is not a positive number")     (enforce (validate-principal merchant-guard merchant) "Invalid merchant guard")    (enforce (validate-principal buyer-guard buyer) "Invalid buyer guard")     (with-capability (CREATE_ORDER order-id)      (enforce-order-lines        order-id        buyer        buyer-guard        merchant        merchant-guard        order-price      )      (insert order-table order-id         { 'order-status   : CREATED        , 'merchant       : merchant        , 'merchant-guard : merchant-guard        , 'buyer          : buyer        , 'buyer-guard    : buyer-guard        , 'order-price    : order-price        }      )      (reserve-funds order-id buyer (+ order-price))      (reserve-funds order-id merchant (get-merchant-deposit-amount order-price))    )  )
pact
  (defun create-order (    order-id       : string    merchant       : string    merchant-guard : guard    buyer          : string    buyer-guard    : guard    order-price    : decimal  )    @doc "Creates an order in the order table and reserves funds to the escrow account"    (enforce (!= order-id "") "Order id can not be empty")    (enforce (< 0.0 order-price) "Order price is not a positive number")     (enforce (validate-principal merchant-guard merchant) "Invalid merchant guard")    (enforce (validate-principal buyer-guard buyer) "Invalid buyer guard")     (with-capability (CREATE_ORDER order-id)      (enforce-order-lines        order-id        buyer        buyer-guard        merchant        merchant-guard        order-price      )      (insert order-table order-id         { 'order-status   : CREATED        , 'merchant       : merchant        , 'merchant-guard : merchant-guard        , 'buyer          : buyer        , 'buyer-guard    : buyer-guard        , 'order-price    : order-price        }      )      (reserve-funds order-id buyer (+ order-price))      (reserve-funds order-id merchant (get-merchant-deposit-amount order-price))    )  )