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:
(create-capability-guard CAPABILITY)
(create-capability-guard CAPABILITY)
Arguments
Use the following argument to specify the CAPABILITY
for the create-capability-guard
Pact function.
Argument | Type | Description |
---|---|---|
CAPABILITY | capability | Specifies 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:
(defun create-gas-payer-guard:guard() (create-capability-guard (GOVERNANCE)))
(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:
(defconst ESCROW_ID (create-principal (create-capability-guard (ESCROW_MANAGEMENT)) ) "The escrow will hold all KDA in circulation on the chain")
(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:
(create-capability-pact-guard CAPABILITY)
(create-capability-pact-guard CAPABILITY)
Arguments
Use the following argument to specify the CAPABILITY
for the create-capability-pact-guard
Pact function.
Argument | Type | Description |
---|---|---|
CAPABILITY | capability | Specifies 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:
(create-capability-pact-guard (ESCROW owner))
(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:
(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))) )
(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:
(create-module-guard name)
(create-module-guard name)
Arguments
Use the following argument to specify the name
for the create-module-guard
Pact function.
Argument | Type | Description |
---|---|---|
name | string | Specifies 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 name
that 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:
(create-module-guard "module-admin-guard")
(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:
create-pact-guard name
create-pact-guard name
Arguments
Use the following argument to specify the name
for the create-pact-guard
Pact function.
Argument | Type | Description |
---|---|---|
name | string | Specifies 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:
(create-pact-guard "pact-id-guard")
(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:
create-principal guard
create-principal guard
Arguments
Use the following argument to specify the guard
for the create-principal
Pact function.
Argument | Type | Description |
---|---|---|
guard | guard | Specifies 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:
(create-principal (read-keyset 'keyset))
(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:
(create-user-guard closure)
(create-user-guard closure)
Arguments
Use the following argument to specify the closure
for the create-user-guard
Pact function.
Argument | Type | Description |
---|---|---|
closure | closure | Specifies 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:
(create-user-guard (read-keyset 'my-keyset))
(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:
(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) ))
(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:
(is-principal principal)
(is-principal principal)
Arguments
Use the following argument to specify the principal
string you want to check using the is-principal
Pact function.
Argument | Type | Description |
---|---|---|
principal | string | Specifies 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> (is-principal "k:58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c")true
pact> (is-principal "k:58705e8699678bd15bbda2cf40fa236694895db614aafc82cf1c06c014ca963c")true
The following example demonstrates how to use the is-principal
function in an enforce
statement:
(defcap LOCK_DEPOSIT(sender:string) (enforce (is-principal sender) "Sender must be a principal account"))
(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:
(enforce (is-principal "c:bF51UeSqhrSjEET1yUWBYabDTfujlAZke4R70I4rrH") "Invalid account structure: non-principal account")<interactive>:0:0:Error: Invalid account structure: non-principal account
(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:
(keyset-ref-guard keyset-ref)
(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.
Argument | Type | Description |
---|---|---|
keyset-ref | string | Specifies 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:
(keyset-ref-guard "my-keyset")
(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:
(typeof-principal principal)
(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.
Argument | Type | Description |
---|---|---|
principal | string | Specifies 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:
(typeof-principal "k:462e97a099987f55f6a2b52e7bfd52a36b4b5b470fed0816a3d9b26f9450ba69")"k:"
(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:
(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])) )))
(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.
Argument | Type | Description |
---|---|---|
guard | guard | Specifies the guard to validate against. |
principal | string | Specifies 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:
(enforce (validate-principal (read-keyset 'keyset) account) "Invalid account ID")
(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:
(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)) ) )
(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)) ) )