Skip to content

Commit f642953

Browse files
kenny-stacksgitbook-bot
authored andcommitted
GITBOOK-3: Add Clarity 4 functions and keywords
1 parent d63a4c1 commit f642953

File tree

2 files changed

+336
-8
lines changed

2 files changed

+336
-8
lines changed

docs/reference/clarity/functions.md

Lines changed: 298 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,23 +224,61 @@ Takes a list and a value of the same entry type, and returns a new list with max
224224

225225
***
226226

227-
## as-contract
227+
## as-contract?
228228

229-
Introduced in: **Clarity 1**
229+
Introduced in: **Clarity 4**
230230

231-
**input:** `A`\
232-
**output:** `A`\
233-
**signature:** `(as-contract expr)`
231+
{% hint style="info" %}
232+
The previous version of `as-contract`, introduced in Clarity 1, has changed to `as-contract?` in Clarity 4, with several new security enhancements. If you are using Clarity 1-3, the previous signature and description for `as-contract` can be found in the dropdown below.
233+
{% endhint %}
234234

235-
**description:**\
236-
Executes `expr` with the tx-sender switched to the contract's principal and returns the result.
235+
<details>
236+
237+
<summary>Previous <code>as-contract</code></summary>
238+
239+
**input:** `A` **output:** `A` **signature:** `(as-contract expr)`
240+
241+
**description:** Executes `expr` with the tx-sender switched to the contract's principal and returns the result.
237242

238243
**example:**
239244

240-
```clojure
245+
Copy
246+
247+
```
241248
(as-contract tx-sender) ;; Returns S1G2081040G2081040G2081040G208105NK8PE5.docs-test
242249
```
243250

251+
</details>
252+
253+
**Input**:
254+
255+
* `((with-stx|with-ft|with-nft|with-stacking)*|with-all-assets-unsafe)`: The set of allowances (at most 128) to grant during the evaluation of the body expressions. Note that `with-all-assets-unsafe` is mutually exclusive with other allowances.
256+
* `AnyType* A`: The Clarity expressions to be executed within the context, with the final expression returning type `A`, where `A` is not a `response`
257+
258+
**Output**: `(response A uint)`
259+
260+
**Signature**: `(as-contract? ((with-stx|with-ft|with-nft|with-stacking)*|with-all-assets-unsafe) expr-body1 expr-body2 ... expr-body-last)`
261+
262+
**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 and an error is returned. Note that the allowance setup expressions are evaluated before executing the body expressions. The final body expression cannot return a `response` value in order to avoid returning a nested `response` value from `as-contract?` (nested responses are error-prone). Returns:
263+
264+
* `(ok x)` if the outflows are within the allowances, where `x` is the result of the final body expression and has type `A`.
265+
* `(err index)` if an allowance was violated, where `index` is the 0-based index of the first violated allowance in the list of granted allowances, or `u128` if an asset with no allowance caused the violation.
266+
267+
**Example**:
268+
269+
```
270+
(define-public (foo)
271+
(as-contract? ()
272+
(try! (stx-transfer? u1000000 tx-sender recipient))
273+
)
274+
) ;; Returns (err u128)
275+
(define-public (bar)
276+
(as-contract? ((with-stx u1000000))
277+
(try! (stx-transfer? u1000000 tx-sender recipient))
278+
)
279+
) ;; Returns (ok true)
280+
```
281+
244282
***
245283

246284
## as-max-len?
@@ -591,6 +629,30 @@ Executes a public function on another contract (not the current contract). If th
591629

592630
***
593631

632+
## contract-hash?
633+
634+
Introduced in: **Clarity 4**
635+
636+
**Input**: `principal`
637+
638+
**Output**: `(response (buff 32) uint)`
639+
640+
**Signature**: `(contract-hash? contract-principal)`
641+
642+
**Description**: Returns the SHA-512/256 hash of the code body of the contract principal specified as input, or an error if the principal is not a contract or the specified contract does not exist. Returns:
643+
644+
* `(ok 0x<hash>)`, where `<hash>` is the SHA-512/256 hash of the code body, on success
645+
* `(err u1)` if the principal is not a contract principal
646+
* `(err u2)` if the specified contract does not exist
647+
648+
**Example**:
649+
650+
```
651+
(contract-hash? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF.BNS-V2) ;; Returns (ok 0x9f8104ff869aba1205cd5e15f6404dd05675f4c3fe0817c623c425588d981c2f)
652+
```
653+
654+
***
655+
594656
## contract-of
595657

596658
Introduced in: **Clarity 1**
@@ -1715,6 +1777,42 @@ Returns a new sequence with element at `index` replaced. Returns `none` if index
17151777

17161778
***
17171779

1780+
## restrict-assets?
1781+
1782+
Introduced in: **Clarity 4**
1783+
1784+
**Input**:
1785+
1786+
* `asset-owner`: `principal`: The principal whose assets are being protected.
1787+
* `((with-stx|with-ft|with-nft|with-stacking)*)`: The set of allowances (at most 128) to grant during the evaluation of the body expressions .
1788+
* `AnyType* A`: The Clarity expressions to be executed within the context, with the final expression returning type `A`, where `A` is not a `response`
1789+
1790+
**Output**: `(response A uint)`
1791+
1792+
**Signature**: `(restrict-assets? asset-owner ((with-stx|with-ft|with-nft|with-stacking)*) expr-body1 expr-body2 ... expr-body-last)`
1793+
1794+
**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 and an error is returned. Note that the `asset-owner` and allowance setup expressions are evaluated before executing the body expressions. The final body expression cannot return a `response` value in order to avoid returning a nested `response` value from `restrict-assets?` (nested responses are error-prone). Returns:
1795+
1796+
* `(ok x)` if the outflows are within the allowances, where `x` is the result of the final body expression and has type `A`.
1797+
* `(err index)` if an allowance was violated, where `index` is the 0-based index of the first violated allowance in the list of granted allowances, or `u128` if an asset with no allowance caused the violation.
1798+
1799+
**Example**:
1800+
1801+
```
1802+
(define-public (foo)
1803+
(restrict-assets? tx-sender ()
1804+
(try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM))
1805+
)
1806+
) ;; Returns (err u128)
1807+
(define-public (bar)
1808+
(restrict-assets? tx-sender ()
1809+
(+ u1 u2)
1810+
)
1811+
) ;; Returns (ok u3)
1812+
```
1813+
1814+
***
1815+
17181816
## secp256k1-recover?
17191817

17201818
Introduced in: **Clarity 1**
@@ -1745,6 +1843,28 @@ Verifies that `signature` of `message-hash` was produced by `public-key`. Signat
17451843

17461844
***
17471845

1846+
## secp256r1-verify
1847+
1848+
**Input**: `(buff 32), (buff 64), (buff 33)`
1849+
1850+
**Output**: `bool`
1851+
1852+
**Signature**: `(secp256r1-verify message-hash signature public-key)`
1853+
1854+
**Description**: The `secp256r1-verify` function verifies that the provided `signature` of the `message-hash` was produced by the private key corresponding to `public-key`. The `message-hash` is the SHA-256 hash of the message. The `signature` must be 64 bytes (compact signature). Returns `true` if the signature is valid for the given `public-key` and message hash, otherwise returns `false`.
1855+
1856+
**Example**:
1857+
1858+
```clojure
1859+
(secp256r1-verify 0x033510403a646d23ee4f005061c2ca6af5da7c32c83758e8e9b6ac4cc1c2153c
1860+
0x9608dc164b76d2e19365ffa67b48981e441d323c3109718aee245d6ac8ccd21ddadadb94303c922c0d79d131ea59a0b6ba83e1157695db01189bb4b7e9f14b72 0x037a6b62e3c8b14f1b5933f5d5ab0509a8e7d95a111b8d3b264d95bfa753b00296) ;; Returns true
1861+
(secp256r1-verify 0x0000000000000000000000000000000000000000000000000000000000000000
1862+
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1863+
0x037a6b62e3c8b14f1b5933f5d5ab0509a8e7d95a111b8d3b264d95bfa753b00296) ;; Returns false
1864+
```
1865+
1866+
***
1867+
17481868
## sha256 / sha512 / sha512/256
17491869

17501870
Introduced in: **Clarity 1**
@@ -1942,6 +2062,29 @@ Transfers STX (microstacks) from `sender` to `recipient`. `sender` must be curre
19422062

19432063
***
19442064

2065+
## to-ascii?
2066+
2067+
Introduced in: **Clarity 4**
2068+
2069+
**Input**: `int` | `uint` | `bool` | `principal` | `(buff 524284)` | `(string-utf8 262144)`
2070+
2071+
**Output**: `(response (string-ascii 1048571) uint)`
2072+
2073+
**Signature**: `(to-ascii? value)`
2074+
2075+
**Description**: Returns the `string-ascii` representation of the input value in an `ok` response on success. The only error condition is if the input type is `string-utf8` and the value contains non-ASCII characters, in which case, `(err u1)` is returned. Note that the limitation on the maximum sizes of `buff` and `string-utf8` inputs is due to the Clarity value size limit of 1MB. The `(string-utf8 262144)` is the maximum allowed size of a `string-utf8` value, and the `(buff 524284)` limit is chosen because the ASCII representation of a `buff` is `0x` followed by two ASCII characters per byte in the `buff`. This means that the ASCII representation of a `(buff 524284)` is `2 + 2 * 524284 = 1048570` characters at 1 byte each, and the remainder is required for the `response` value wrapping the `string-ascii`.
2076+
2077+
**Example**:
2078+
2079+
```clojure
2080+
(to-ascii? true) ;; Returns (ok "true")
2081+
(to-ascii? 42) ;; Returns (ok "42")
2082+
(to-ascii? 'SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF) ;; Returns (ok "SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF")
2083+
(to-ascii? 0x12345678) ;; Returns (ok "0x12345678")
2084+
```
2085+
2086+
***
2087+
19452088
## to-consensus-buff?
19462089

19472090
Introduced in: **Clarity 2**
@@ -2086,6 +2229,153 @@ Introduced in: **Clarity 1**
20862229

20872230
***
20882231

2232+
{% hint style="info" %}
2233+
The following 5 `with-*` functions are meant to be used inside the new `restrict-assets?` function. See the tutorial on Restricting Assets in Clarity for more info on how to use this function.
2234+
{% endhint %}
2235+
2236+
## with-all-assets-unsafe
2237+
2238+
Introduced in: **Clarity 4**
2239+
2240+
**Input**: None
2241+
2242+
**Output**: Not applicable
2243+
2244+
**Signature**: `(with-all-assets-unsafe)`
2245+
2246+
**Description**: Grants unrestricted access to all assets of the contract to the enclosing `as-contract?` expression. Note that this is not allowed in `restrict-assets?` and will trigger an analysis error, since usage there does not make sense (i.e. just remove the `restrict-assets?` instead). **Security Warning:** This should be used with extreme caution, as it effectively disables all asset protection for the contract. This dangerous allowance should only be used when the code executing within the `as-contract?` body is verified to be trusted through other means (e.g. checking traits against an allow list, passed in from a trusted caller), and even then the more restrictive allowances should be preferred when possible.
2247+
2248+
**Example**:
2249+
2250+
```clojure
2251+
(define-public (execute-trait (trusted-trait <sample-trait>))
2252+
(begin
2253+
(asserts! (is-eq contract-caller TRUSTED_CALLER) ERR_UNTRUSTED_CALLER)
2254+
(as-contract? ((with-all-assets-unsafe))
2255+
(contract-call? trusted-trait execute)
2256+
)
2257+
)
2258+
)
2259+
```
2260+
2261+
***
2262+
2263+
## with-ft
2264+
2265+
**Input**:
2266+
2267+
* `contract-id`: `principal`: The contract defining the FT asset.
2268+
* `token-name`: `(string-ascii 128)`: The name of the FT or `"*"` for any FT defined in `contract-id`.
2269+
* `amount`: `uint`: The amount of FT to grant access to.
2270+
2271+
**Output**: Not applicable
2272+
2273+
**Signature**: `(with-ft contract-id token-name amount)`
2274+
2275+
**Description**: Adds an outflow allowance for `amount` of the fungible token defined in `contract-id` with name `token-name` from the `asset-owner` of the enclosing `restrict-assets?` or `as-contract?` expression. Note that `token-name` should match the name used in the `define-fungible-token` call in the contract. When `"*"` is used for the token name, the allowance applies to **all** FTs defined in `contract-id`.
2276+
2277+
**Example**:
2278+
2279+
```clojure
2280+
(restrict-assets? tx-sender
2281+
((with-ft (contract-of token-trait) "stackaroo" u50))
2282+
(try! (contract-call? token-trait transfer u100 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none))
2283+
) ;; Returns (err u0)
2284+
(restrict-assets? tx-sender
2285+
((with-ft (contract-of token-trait) "stackaroo" u50))
2286+
(try! (contract-call? token-trait transfer u20 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none))
2287+
) ;; Returns (ok true)
2288+
```
2289+
2290+
***
2291+
2292+
## with-nft
2293+
2294+
**Input**:
2295+
2296+
* `contract-id`: `principal`: The contract defining the NFT asset.
2297+
* `token-name`: `(string-ascii 128)`: The name of the NFT or `"*"` for any NFT defined in `contract-id`.
2298+
* `identifiers`: `(list 128 T)`: The identifiers of the token to grant access to.
2299+
2300+
**Output**: Not applicable
2301+
2302+
**Signature**: `(with-nft contract-id token-name identifiers)`
2303+
2304+
**Description**: Adds an outflow allowance for the non-fungible token(s) identified by `identifiers` defined in `contract-id` with name `token-name` from the `asset-owner` of the enclosing `restrict-assets?` or `as-contract?` expression. Note that `token-name` should match the name used in the `define-non-fungible-token` call in the contract. When `"*"` is used for the token name, the allowance applies to **all** NFTs defined in `contract-id`.
2305+
2306+
**Example**:
2307+
2308+
```clojure
2309+
(restrict-assets? tx-sender
2310+
((with-nft (contract-of nft-trait) "stackaroo" (list u123)))
2311+
(try! (contract-call? nft-trait transfer u4 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM))
2312+
) ;; Returns (err u0)
2313+
(restrict-assets? tx-sender
2314+
((with-nft (contract-of nft-trait) "stackaroo" (list u123)))
2315+
(try! (contract-call? nft-trait transfer u123 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM))
2316+
) ;; Returns (ok true)
2317+
```
2318+
2319+
***
2320+
2321+
## with-stacking
2322+
2323+
**Input**:
2324+
2325+
* `amount`: `uint`: The amount of uSTX that can be locked.
2326+
2327+
**Output**: Not applicable
2328+
2329+
**Signature**: `(with-stacking amount)`
2330+
2331+
**Description**: Adds a stacking allowance for `amount` uSTX from the `asset-owner` of the enclosing `restrict-assets?` or `as-contract?` expression. This restricts calls to the active PoX contract that either delegate funds for stacking or stack directly, ensuring that the locked amount is limited by the amount of uSTX specified.
2332+
2333+
**Example**:
2334+
2335+
```clojure
2336+
(restrict-assets? tx-sender
2337+
((with-stacking u1000000000000))
2338+
(try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx
2339+
u1100000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none
2340+
))
2341+
) ;; Returns (err u0)
2342+
(restrict-assets? tx-sender
2343+
((with-stacking u1000000000000))
2344+
(try! (contract-call? 'SP000000000000000000002Q6VF78.pox-4 delegate-stx
2345+
u900000000000 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM none none
2346+
))
2347+
) ;; Returns (ok true)
2348+
```
2349+
2350+
***
2351+
2352+
## with-stx
2353+
2354+
**Input**:
2355+
2356+
* `amount`: `uint`: The amount of uSTX to grant access to.
2357+
2358+
**Output**: Not applicable
2359+
2360+
**Signature**: `(with-stx amount)`
2361+
2362+
**Description**: Adds an outflow allowance for `amount` uSTX from the `asset-owner` of the enclosing `restrict-assets?` or `as-contract?` expression.
2363+
2364+
**Example**:
2365+
2366+
```
2367+
(restrict-assets? tx-sender
2368+
((with-stx u1000000))
2369+
(try! (stx-transfer? u2000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM))
2370+
) ;; Returns (err u0)
2371+
(restrict-assets? tx-sender
2372+
((with-stx u1000000))
2373+
(try! (stx-transfer? u1000000 tx-sender 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM))
2374+
) ;; Returns (ok true)
2375+
```
2376+
2377+
***
2378+
20892379
## xor
20902380

20912381
Introduced in: **Clarity 1**

0 commit comments

Comments
 (0)