-
Notifications
You must be signed in to change notification settings - Fork 706
Description
Limiting asset access: restrict-assets?
Originally proposed here.
restrict-assets?
establishes a context with a deny-all outflow policy for a
specific principal during the evaluation of its body expressions. It accepts a
set of allowances, defined using with-stx
, with-ft
, with-nft
, and
with-stacking
, which selectively grant outflow allowances. After the body
expressions finish, the Clarity VM checks the gross outflow from the scoped
principal against the granted allowances. If any allowance is exceeded,
restrict-assets?
returns an error; otherwise, it returns ok
with the result
of the last body expression.
The most important use case of these new builtins is to allow a contract to
protect its own assets. To ensure that the contract's assets are safe by
default, the new as-contract?
expression is similar to the existing
as-contract
expression, but will implicitly behave as though there is a
restrict-assets?
expression around its body, specifying the contract principal
as the asset owner. The old as-contract
is no longer available in Clarity 4.
Similar to restrict-assets?
, as-contract?
accepts a set of with-stx
,
with-ft
, with-nft
, and with-stacking
expressions which selectively grant
outflow allowances from the contract's assets.
with-stx
grants an outflow allowance for a specific amount of STX via calls
to thestx-transfer?
function.with-ft
grants an outflow allowance for a specific amount of the specified
fungible token.with-nft
grants an outflow allowance for a specific identifier of the
specified NFT.with-stacking
grants an outflow allowance for a specific amount of STX via
calls to thestack-stx
ordelegate-stx
functions of the active PoX
contract.
Use of with-stx
, with-ft
, with-nft
, or with-stacking
outside of
restrict-assets?
or as-contract?
results in an analysis error.
-
restrict-assets?
-
Input:
asset-owner
:principal
: The principal whose assets are being
protected.((with-stx|with-ft|with-nft|with-stacking)*)
: The set of allowances to
grant during the evaluation of the body expressions.AnyType* A
: The Clarity expressions to be executed within the context,
with the final expression returning typeA
, whereA
is not a
response
-
Output:
(response A int)
-
Signature:
(restrict-assets? asset-owner ((with-stx|with-ft|with-nft|with-stacking)*) expr-body1 expr-body2 ... expr-body-last)
-
Description: Executes the body expressions, then checks the asset
outflows against the granted allowances, in declaration order. If any
allowance is violated, the body expressions are reverted, an error is
returned, and an event is emitted with the full details of the violation to
help with debugging. Note that theasset-owner
and allowance setup
expressions are evaluated before executing the body expressions. The final
body expression cannot return aresponse
value in order to avoid returning
a nestedresponse
value from therestrict-assets?
(nested responses are
error-prone). Returns:(ok x)
if the outflows are within the allowances, wherex
is the
result of thebody
expression and has typeA
.(err index)
if an allowance was violated, whereindex
is the 0-based
index of the first violated allowance in the list of granted allowances,
or -1 if an asset with no allowance caused the violation.
-
Example:
(define-public (foo) (restrict-assets? tx-sender () (try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ) ;; Returns (err -1) (define-public (bar) (restrict-assets? tx-sender () (+ u1 u2) ) ) ;; Returns (ok u3)
-
-
with-stx
- Input:
amount
:uint
: The amount of uSTX to grant access to.
- Output: Not applicable
- Signature:
(with-stx amount)
- Description: Adds an outflow allowance for
amount
uSTX from the
asset-owner
of the enclosingrestrict-assets?
oras-contract?
expression. - Example:
(restrict-assets? tx-sender ((with-stx u1000000)) (try! (stx-transfer? u2000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (err 0) (restrict-assets? tx-sender ((with-stx u1000000)) (try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (ok true)
- Input:
-
with-ft
- Input:
contract-id
:principal
: The contract defining the FT asset.token-name
:(string-ascii 128)
: The name of the FT or"*"
for any FT
defined incontract-id
.amount
:uint
: The amount of FT to grant access to.
- Output: Not applicable
- Signature:
(with-ft contract-id token-name amount)
- Description: Adds an outflow allowance for
amount
of the fungible
token defined incontract-id
with nametoken-name
from theasset-owner
of the enclosingrestrict-assets?
oras-contract?
expression. Note,
token-name
should match the name used in thedefine-fungible-token
call
in the contract. - Example:
(restrict-assets? tx-sender ((with-ft (contract-of token-trait) "stackaroo" u50)) (try! (contract-call? token-trait transfer u100 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none)) ) ;; Returns (err 0) (restrict-assets? tx-sender ((with-ft (contract-of token-trait) "stackaroo" u50)) (try! (contract-call? token-trait transfer u20 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none)) ) ;; Returns (ok true)
- Input:
-
with-nft
- Input:
contract-id
:principal
: The contract defining the NFT asset.token-name
:(string-ascii 128)
: The name of the NFT or"*"
for any
NFT defined incontract-id
.identifier
:T
: The identifier of the token to grant access to.
- Output: Not applicable
- Signature:
(with-nft contract-id token-name identifier)
- Description: Adds an outflow allowance for the non-fungible token
identified byidentifier
defined incontract-id
with nametoken-name
from theasset-owner
of the enclosingrestrict-assets?
oras-contract?
expression. Note,token-name
should match the name used in the
define-non-fungible-token
call in the contract. - Example:
(restrict-assets? tx-sender ((with-nft (contract-of nft-trait) "stackaroo" u123)) (try! (contract-call? nft-trait transfer u4 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (err 0) (restrict-assets? tx-sender ((with-nft (contract-of nft-trait) "stackaroo" u123)) (try! (contract-call? nft-trait transfer u123 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM)) ) ;; Returns (ok true)
- Input:
-
with-stacking
- Input:
amount
:uint
: The amount of uSTX that can be locked.
- Output: Not applicable
- Signature:
(with-stacking amount)
- Description: Adds a stacking allowance for
amount
uSTX from the
asset-owner
of the enclosingrestrict-assets?
oras-contract?
expression. This restricts calls todelegate-stx
andstack-stx
in the
active PoX contract to lock up to the amount of uSTX specified. - Example:
(restrict-assets? tx-sender ((with-stacking u1000000000000)) (try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx u1100000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none )) ) ;; Returns (err 0) (restrict-assets? tx-sender ((with-stacking u1000000000000)) (try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx u900000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none )) ) ;; Returns (ok true)
- Input:
-
as-contract?
-
Input:
((with-stx|with-ft|with-nft|with-stacking)*)
: The set of allowances to
grant during the evaluation of the body expressions.AnyType* A
: The Clarity expressions to be executed within the context,
with the final expression returning typeA
, whereA
is not a
response
-
Output:
(response A int)
-
Signature:
(as-contract? ((with-stx|with-ft|with-nft|with-stacking)*) expr-body1 expr-body2 ... expr-body-last)
-
Description: Switches the current context's
tx-sender
and
contract-caller
values to the contract's principal and executes the body
expressions within that context, then checks the asset outflows from the
contract against the granted allowances, in declaration order. If any
allowance is violated, the body expressions are reverted, an error is
returned, and an event is emitted with the full details of the violation to
help with debugging. Note that the allowance setup expressions are evaluated
before executing the body expressions. The final body expression cannot
return aresponse
value in order to avoid returning a nestedresponse
value from therestrict-assets?
(nested responses are error-prone).
Returns:(ok x)
if the outflows are within the allowances, wherex
is the
result of thebody
expression and has typeA
.(err index)
if an allowance was violated, whereindex
is the 0-based
index of the first violated allowance in the list of granted allowances, or -1
if an asset with no allowance caused the violation.
-
Example:
(define-public (foo) (as-contract? () (try! (stx-transfer? u1000000 tx-sender recipient)) ) ) ;; Returns (err -1) (define-public (bar) (as-contract? ((with-stx u1000000)) (try! (stx-transfer? u1000000 tx-sender recipient)) ) ) ;; Returns (ok true)
-
See SIP proposal
Metadata
Metadata
Assignees
Labels
Type
Projects
Status