Skip to content

Commit 2f9ba40

Browse files
committed
Add scoping information to docs and clarify mutability of function/contract parameters
1 parent 13f6a0b commit 2f9ba40

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

website/docs/language/contracts.md

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ contract HTLC(pubkey sender, pubkey recipient, int expiration, bytes32 hash) {
3131

3232
### Constructor Arguments
3333

34-
The constructor arguments are provided when initializing a specific instance of a smart contract. The provided constructor arguments are added to the start of the contract's script before the opcode logic. Because the constructor arguments are part of the full smart contract script, they are conceptually similar to hard-coded constants in your contract logic. Constructor arguments are a way to create 'global constants' accessible from different functions inside your contract.
34+
The constructor arguments are provided when initializing a specific instance of a smart contract. The provided constructor arguments are added to the start of the contract's script before the opcode logic. Because the constructor arguments are part of the full smart contract script, they are conceptually similar to hard-coded values in your contract logic. Constructor arguments are a way to create 'global variables' accessible from different functions inside your contract. Note that constructor arguments are variables and can be reassigned inside the contract functions.
3535

3636
:::info
3737
The typings for the constructor arguments are only semantic and used when initializing the contract with the SDK. This means when not using the SDK you could still pass a different byte length item to `bytes32 hash`.
@@ -61,18 +61,20 @@ contract TransferWithTimeout(pubkey sender, pubkey recipient, int timeout) {
6161

6262
### Function Arguments
6363

64-
The function arguments are provided when attempting to spend from the contract. This means that these arguments can be crafted in a specific way by anyone to see if they can exploit the contract logic. Because of this it is important to realize these are 'untrusted arguments'.
64+
Function arguments are provided by the user in the unlocking script of the transaction inputs when spending from the contract. Note that function arguments are variables and can be reassigned inside the function body.
65+
66+
Because the arguments are provided by the user when spending from the contract, these are 'untrusted arguments'. This means that these arguments can be crafted in a specific way by anyone to see if they can exploit the contract logic.
67+
68+
:::note
69+
Function parameters are passed in the reversed order of their declaration. This can be important when debugging, optimizing or when creating transactions manually.
70+
:::
6571

6672
In CashScript the types for the function arguments are **not** enforced automatically at the contract level. This can be especially relevant for types like `bool`, `bytesX` and other semantic bytes types. Instead this type information is only used by the SDK to check whether these arguments match the expected type during transaction building.
6773

6874
:::caution
6975
The typings for the function arguments are only semantic, this means the length of bounded bytes types like `bytes20` are **not** contract enforced automatically. Instead add an explicit length check `require(item.length == 20)`.
7076
:::
7177

72-
:::note
73-
Function parameters are passed in the reversed order of their declaration. This can be important when debugging, optimizing or when creating transactions manually.
74-
:::
75-
7678
## Statements
7779
CashScript functions are made up of a collection of statements that determine whether money may be spent from the contract.
7880

@@ -172,6 +174,51 @@ contract P2PKH(bytes20 pkh) {
172174
}
173175
```
174176

177+
## Scope
178+
179+
CashScript uses nested scopes for parameters, variables and global functions. There cannot be two identical names within the same scope or within a nested scope.
180+
181+
There are the following scopes in the nesting order:
182+
183+
- **Global scope** - contains global functions and global variables (e.g. `sha256`, `hash160`, `checkSig`, etc.)
184+
- **Contract scope** - contains contract parameters
185+
- **Function scope** - contains function parameters and local variables
186+
- **Local scope** - contains local variables introduced by control flow blocks (e.g. `if`, `else`)
187+
188+
#### Example
189+
```solidity
190+
// Global scope (contains global functions and global variables like sha256, hash160, checkSig, etc.)
191+
192+
// Contract scope (contains contract parameters - sender, recipient, timeout)
193+
contract TransferWithTimeout(
194+
pubkey sender,
195+
pubkey recipient,
196+
int timeout
197+
) {
198+
// Function scope (contains function parameters - recipientSig)
199+
function transfer(sig recipientSig) {
200+
require(checkSig(recipientSig, recipient));
201+
}
202+
203+
// Function scope (contains function parameters - senderSig)
204+
function timeout(sig senderSig) {
205+
require(checkSig(senderSig, sender));
206+
207+
// Local scope (contains local variable - newTimeout)
208+
// This is just an example local scope, not a real contract
209+
if (timeout > 100_000) {
210+
int newTimeout = 100_000;
211+
require(tx.time >= newTimeout);
212+
} else {
213+
require(tx.time >= timeout);
214+
}
215+
216+
// After the local scope, 'newTimeout' is no longer accessible
217+
}
218+
}
219+
220+
```
221+
175222
## Comments
176223
Comments can be added anywhere in the contract file. Comment semantics are similar to languages like JavaScript or C. This means that single-line comments can be added with `// ...`, while multiline comments can be added with `/* ... */`.
177224

0 commit comments

Comments
 (0)