summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cairo.html.markdown864
-rw-r--r--func.html.markdown338
-rw-r--r--tact.html.markdown602
-rw-r--r--vyper.html.markdown871
4 files changed, 0 insertions, 2675 deletions
diff --git a/cairo.html.markdown b/cairo.html.markdown
deleted file mode 100644
index dd3ca036..00000000
--- a/cairo.html.markdown
+++ /dev/null
@@ -1,864 +0,0 @@
----
-language: Cairo
-filename: learnCairo.sol
-contributors:
- - ["Darlington Nnam", "https://github.com/Darlington02"]
----
-
-# Cairo
-
-Cairo is a Turing-complete language that allows you write provable programs
-(where one party can prove to another that a certain computation was executed
-correctly) on StarkNet.
-
-## StarkNet
-
-StarkNet is a decentralized ZK-rollup that operates as an Ethereum layer 2
-chain.
-
-In this document, we are going to be going in-depth into understanding Cairo's
-syntax and how you could create and deploy a Cairo smart contract on StarkNet.
-
-**NB: As at the time of this writing, StarkNet is still at v0.10.3, with Cairo
-1.0 coming soon. The ecosystem is young and evolving very fast, so you might
-want to check the [official docs](https://www.cairo-lang.org/docs) to confirm
-this document is still up-to-date. Pull requests are welcome!**
-
-## Setting Up A Development Environment
-
-Before we get started writing codes, we will need to setup a Cairo development
-environment, for writing, compiling and deploying our contracts to StarkNet.
-For the purpose of this tutorial we are going to be using the
-[Protostar Framework](https://github.com/software-mansion/protostar).
-Installation steps can be found in the docs
-[here](https://docs.swmansion.com/protostar/docs/tutorials/installation).
-Note that Protostar supports just Mac and Linux OS, Windows users might need to
-use WSL, or go for other alternatives such as the Official
-[StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html) or
-[Nile from Openzeppelin](https://github.com/OpenZeppelin/nile)
-
-Once you're done with the installations, run the command `protostar -v` to
-confirm your installation was successful. If successful, you should see your
-Protostar version displayed on the screen.
-
-## Initializing a new project
-
-Protostar similar to Truffle for solidity development can be installed once and
-used for multiple projects. To initialize a new Protostar project, run the
-following command:
-
-```
-protostar init
-```
-
-It would then request the project's name and the library's directory name,
-you'd need to fill in this, and a new project will be initialized successfully.
-
-## Compiling, Declaring, Deploying and Interacting with StarkNet Contracts
-
-Within the `src` folder you'll find a boilerplate contract that comes with
-initializing a new Protostar project, `main.cairo`. We are going to be
-compiling, declaring and deploying this contract.
-
-### Compiling Contracts
-
-To compile a Cairo contract using Protostar, ensure a path to the contract is
-specified in the `[contracts]` section of the `protostar.toml` file. Once
-you've done that, open your terminal and run the command:
-
-```
-protostar build
-```
-
-And you should get an output similar to what you see below, with a `main.json`
-and `main_abi.json` files created in the `build` folder.
-<img src="./images/cairo/build.png" alt="building your contract">
-
-### Declaring Contracts
-
-With the recent StarkNet update to 0.10.3, the DEPLOY transaction was
-deprecated and no longer works. To deploy a transaction, you must first declare
-a Contract to obtain the class hash, then deploy the declared contract using the
-[Universal Deployer Contract](https://community.starknet.io/t/universal-deployer-contract-proposal/1864).
-
-Before declaring or deploying your contract using Protostar, you should set the
-private key associated with the specified account address in a file, or in the
-terminal. To set your private key in the terminal, run the command:
-
-```
-export PROTOSTAR_ACCOUNT_PRIVATE_KEY=[YOUR PRIVATE KEY HERE]
-```
-
-Then to declare our contract using Protostar run the following command (for
-visual clarity, the backslash sign symbolizes the continuing line):
-
-```
-protostar declare ./build/main.json \
- --network testnet \
- --account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
- --max-fee auto
-```
-
-where `network` specifies the network we are deploying to, `account` specifies
-account whose private key we are using, `max-fee` specifies the maximum fee to
-be paid for the transaction. You should get the class hash outputted as seen
-below:
-<img src="./images/cairo/declare.png" alt="declaring your contract">
-
-### Deploying Contracts
-
-After obtaining our class hash from declaring, we can now deploy using the
-command below:
-
-```
-protostar \
- deploy 0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc \
- --network testnet \
- --account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
- --max-fee auto
-```
-
-where `0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc` is
-the class hash of our contract.
-<img src="./images/cairo/deploy.png" alt="deploying your contract">
-
-### Interacting with Contracts
-
-To interact with your deployed contract, we will be using `Argent X`
-(alternative: `Braavos`), and `Starkscan` (alternative: `Voyager`). To install
-and setup `Argent X`, see this
-[guide](https://www.argent.xyz/learn/how-to-create-an-argent-x-wallet/).
-
-Copy your contract address, displayed on screen from the previous step, and
-head over to [Starkscan](https://testnet.starkscan.co/) to search for the
-contract. Once found, you can make write calls to the contract in the following
-sequence:
-
-+ click on the "connect wallet" button,
- <img src="./images/cairo/connect.png" alt="connect wallet">
-+ select `Argent X` and approve the connection
- <img src="./images/cairo/connect2.png" alt="connect to argentX">
-+ you can now make read and write calls easily.
-
-## Let's learn Cairo
-
-First let's look at a default contract that comes with Protostar which allows
-you to set balance on deployment, increase, and get the balance.
-
-```
-// Language directive - instructs compiler its a StarkNet contract
-%lang starknet
-
-// Library imports from the Cairo-lang library
-from starkware.cairo.common.math import assert_nn
-from starkware.cairo.common.cairo_builtins import HashBuiltin
-
-// @dev Storage variable that stores the balance of a user.
-// @storage_var is a decorator that instructs the compiler the function
-// below it is a storage variable.
-@storage_var
-func balance() -> (res: felt) {}
-
-// @dev Constructor writes the balance variable to 0 on deployment
-// Constructors sets storage variables on deployment. Can accept arguments too.
-@constructor
-func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}() {
- balance.write(0);
- return();
-}
-
-// @dev increase_balance updates the balance variable
-// @param amount the amount you want to add to balance
-// @external is a decorator that specifies the func below it is an external
-// function.
-@external
-func increase_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(amount: felt){
- with_attr error_message("Amount must be positive. Got: {amount}.") {
- assert_nn(amount);
- }
-
- let (res) = balance.read();
- balance.write(res + amount);
- return ();
-}
-
-// @dev returns the balance variable
-// @view is a decorator that specifies the func below it is a view function.
-@view
-func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}() -> (res: felt) {
- let (res) = balance.read();
- return (res,);
-}
-```
-
-Before proceeding to the main lessons, try to build, deploy and interact with
-this contract.
-NB: You should be at `main.cairo` if you are using Protostar.
-
-### 1. The Felt data type
-
-Unlike solidity, where you have access to various data types, Cairo comes with
-just a single data type `..felts`. Felts stands for Field elements, and are a
-252 bit integer in the range `0<=x<=P` where `P` is a prime number. You can
-create a `Uint256` in Cairo by utlizing a struct of two 128 bits felts.
-
-```
-struct Uint256 {
- low: felt, // The low 128 bits of the value.
- high: felt, // The high 128 bits of the value.
-}
-```
-
-To avoid running into issues with divisions, it's safer to work with the
-`unsigned_div_rem` method from Cairo-lang's library.
-
-### 2. Lang Directive and Imports
-
-To get started with writing a StarkNet contract, you must specify the directive:
-
-```
-%lang starknet
-```
-
-This directive informs the compiler you are writing a contract and not a
-program. The difference between both is contracts have access to StarkNet's
-storage, programs don't and as such are stateless.
-
-There are important functions you might need to import from the official
-Cairo-lang library or Openzeppelin's, e.g.
-
-```
-from starkware.cairo.common.cairo_builtins import HashBuiltin
-from cairo_contracts.src.openzeppelin.token.erc20.library import ERC20
-from starkware.cairo.common.uint256 import Uint256
-from starkware.cairo.common.bool import TRUE
-```
-
-### 3. Data Structures
-
-+ Storage variables: Cairo's storage is a map with `2^251` slots, where each
- slot is a felt which is initialized to `0`. You create one using the
- `@storage_var` decorator.
-
- ```
- @storage_var
- func names() -> (name: felt) {}
- ```
-
-+ Storage mappings: Unlike Solidity where mappings have a separate keyword, in
- Cairo you create mappings using storage variables.
-
- ```
- @storage_var
- func names(address: felt) -> (name: felt) {}
- ```
-
-+ Structs: are a means to create custom data types in Cairo. A `struct` has a
- size, which is the sum of the sizes of its members. The size can be
- retrieved using `MyStruct.SIZE`. You create a struct in Cairo using the
- `struct` keyword.
-
- ```
- struct Person {
- name: felt,
- age: felt,
- address: felt,
- }
- ```
-
-+ Constants: Constants are fixed and as such can't be altered after being set.
- They evaluate to an integer (field element) at compile time. To create a
- constant in Cairo, you use the `const` keyword. It's proper practice to
- capitalize constant names.
-
- ```
- const USER = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
- ```
-
-+ Arrays: Arrays can be defined as a `pointer(felt*)` to the first element of
- the array. As an array is populated, its elements take up contigous memory
- cells. The `alloc` keyword can be used to dynamically allocate a new memory
- segment, which can be used to store an array:
-
- ```
- let (myArray: felt*) = alloc ();
- assert myArray[0] = 1;
- assert myArray[1] = 2;
- assert myArray[3] = 3;
- ```
-
- You can also use the `new` operator to create fixed-size arrays using
- tuples. The new operator is useful as it enables you allocate memory and
- initialize the object in one instruction
-
- ```
- func foo() {
- tempvar arr: felt* = new (1, 1, 2, 3, 5);
- assert arr[4] = 5;
- return ();
- }
- ```
-
-+ Tuples: A tuple is a finite, ordered, unchangeable list of elements. It is
- represented as a comma-separated list of elements enclosed by parentheses.
- Their elements may be of any combination of valid types.
-
- ```
- local tuple0: (felt, felt, felt) = (7, 9, 13);
- ```
-
-+ Events: Events allows a contract emit information during the course of its
- execution, that can be used outside of StarkNet. An event can be created,
- subsequently emitted:
-
- ```
- @event
- func name_stored(address, name) {}
-
- name_stored.emit(address, name);
- ```
-
-### 4. Constructors, External and View functions
-
-+ Constructors: Constructors are a way to intialize state variables on
- contract deployment. You create a constructor using the `@constructor`
- decorator.
-
- ```
- @constructor
- func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
- range_check_ptr}(_name: felt) {
- let (caller) = get_caller_address();
- names.write(caller, _name);
- return ();
- }
- ```
-
-+ External functions: External functions are functions that modifies the state
- of the network. You create an external function using the `@external`
- decorator:
-
- ```
- @external
- func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
- range_check_ptr}(_name: felt){
- let (caller) = get_caller_address();
- names.write(caller, _name);
- stored_name.emit(caller, _name);
- return ();
- }
- ```
-
-+ View functions: View functions do not modify the state of the blockchain.
- You can create a view function using the `@view` decorator.
-
- ```
- @view
- func get_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
- range_check_ptr}(_address: felt) -> (name: felt){
- let (name) = names.read(_address);
- return (name,);
- }
- ```
-
- NB: Unlike Solidity, Cairo supports just External and View function types.
- You can alternatively also create an internal function by not adding any
- decorator to the function.
-
-### 5. Decorators
-
-All functions in Cairo are specified by the `func` keyword, which can be
-confusing. Decorators are used by the compiler to distinguish between these
-functions.
-
-Here are the most common decorators you'll encounter in Cairo:
-
-+ `@storage_var` — used for specifying state variables.
-+ `@constructor` — used for specifying constructors.
-+ `@external` — used for specifying functions that write to a state variable.
-+ `@event` — used for specifying events
-+ `@view` — used to specify functions reading from a state variable
-+ `@contract_interface` — used for specifying function interfaces.
-+ `@l1_handler` — used for specifying functions that processes message sent from
- an L1 contract in a messaging bridge.
-
-### 6. BUILTINS, HINTS & IMPLICIT Arguments
-
-+ `BUILTINS` are predefined optimized low-level execution units, which are
- added to Cairo’s CPU board. They help perform predefined computations like
- pedersen hashing, bitwise operations etc, which are expensive to perform in
- Vanilla Cairo. Each builtin in Cairo is assigned a separate memory location,
- accessible through regular Cairo memory calls using implicit parameters. You
- specify them using the `%builtins` directive
-
- Here is a list of available builtins in Cairo:
-
- + `output` — the output builtin is used for writing program outputs
- + `pedersen` — the pedersen builtin is used for pedersen hashing
- computations
- + `range_check` — This builtin is mostly used for integer comparisons,
- and facilitates check to confirm that a field element is within a range
- `[0, 2^128)`
- + `ecdsa` — the ecdsa builtin is used for verifying ECDSA signatures
- + `bitwise` — the bitwise builtin is used for carrying out bitwise
- operations on felts
-
-+ `HINTS` are pieces of Python codes, which contains instructions that only
- the prover sees and executes. From the point of view of the verifier these
- hints do not exist. To specify a hint in Cairo, you need to encapsulate it
- within `%{` and `%}`. It is good practice to avoid using hints as much as
- you can in your contracts, as hints are not added to the bytecode, and thus
- do not count in the total number of execution steps.
-
- ```
- %{
- # Python hint goes here
- %}
- ```
-
-+ `IMPLICIT ARGUMENTS` are not restricted to the function body, but can be
- inherited by other functions calls that require them. Implicit arguments are
- passed in between curly bracelets, like you can see below:
-
- ```
- func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
- range_check_ptr}(_name: felt){
- let (caller) = get_caller_address();
- names.write(caller, _name);
- stored_name.emit(caller, _name);
- return ();
- }
- ```
-
-### 7. Error Messages and Access Controls
-
-You can create custom errors in Cairo which is outputted to the user upon failed
-execution. This can be very useful for implementing checks and proper access
-control mechanisms. An example is preventing a user to call a function except
-user is `admin`.
-
-```
-// imports
-from starkware.starknet.common.syscalls import get_caller_address
-
-// create an admin constant
-const ADMIN = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
-
-// implement access control
-with_attr error_message("You do not have access to make this action!"){
- let (caller) = get_caller_address();
- assert ADMIN = caller;
-}
-
-// using an assert statement throws if condition is not true, thus
-// returning the specified error.
-```
-
-### 8. Contract Interfaces
-
-Contract interfaces provide a means for one contract to invoke or call the
-external function of another contract. To create a contract interface, you use
-the `@contract_interface` keyword:
-
-```
-@contract_interface
- namespace IENS {
- func store_name(_name: felt) {
- }
-
- func get_name(_address: felt) -> (name: felt) {
- }
- }
-```
-
-Once a contract interface is specified, any contract can make calls to that
-contract passing in the contract address as the first parameter like this:
-
-```
-IENS.store_name(contract_address, _name);
-```
-
-Note that Interfaces exclude the function body/logic and the implicit
-arguments.
-
-### 9. Recursions
-
-Due to the unavailability of loops, Recursion is the go-to for similar
-operations. In simple terms, a recursive function is one which calls itself
-repeatedly.
-
-A good example to demonstrate this is writing a function for getting the nth
-fibonacci number:
-
-```
-@external
-func fibonacci{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(n : felt) -> (result : felt){
- alloc_locals;
- if (n == 0){
- return (0);
- }
- if (n == 1){
- return (1);
- }
- let (local x) = fibonacci(n - 1);
- let (local y) = fibonacci(n - 2);
- return (result=(x + y));
-}
-```
-
-The nth fibonacci term is the sum of the `nth - 1` and the `nth - 2` numbers,
-that's why we get these two as `(x,y)` using recursion.
-
-NB: when implementing recursive functions, always remember to implement a base
-case (`n==0`, `n==1` in our case), to prevent stack overflows.
-
-### 10. Registers
-
-Registers holds values that may change over time. There are 3 major types of
-registers:
-
-+ `ap` (allocation pointer) points to a yet unused memory. Temporary variables
- created using `let`, `tempvar` are held here, and thus susceptible to being
- revoked.
-+ `fp` (frame pointer) points to the frame of the current function. The address
- of all the function arguments and local variables are relative to this
- register and as such can never be revoked.
-+ `pc` (program counter) points to the current instruction.
-
-### 11. Revoked References
-
-Revoked references occur when there is a call instruction to another function,
-between the definition of a reference variable that depends on `ap` (temp
-variables) and its usage. This occurs as the compiler may not be able to compute
-the change of `ap` (as one may jump to the label from another place in the
-program, or call a function that might change ap in an unknown way).
-
-Here is an example to demonstrate what I mean:
-
-```
-@external
-func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}() -> (res: felt) {
- return (res=100);
-}
-
-@external
-func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}() -> (res: felt) {
- let multiplier = 2;
- let (balance) = get_balance();
- let new_balance = balance * multiplier;
- return (res=new_balance);
-}
-```
-
-If you run that code, you'll run into the revoked reference error as we are
-trying to access the `multiplier` variable after calling the `get_balance`
-function.
-
-In simple cases you can resolve revoked references by adding the keyword
-`alloc_locals` within function scopes. In more complex cases you might need to
-create a local variable to resolve it.
-
-```
-// resolving the `double_balance` function:
-@external
-func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}() -> (res: felt) {
- alloc_locals;
- let multiplier = 2;
- let (balance) = get_balance();
- let new_balance = balance * multiplier;
- return (res=new_balance);
-}
-```
-
-### 12. Understanding Cairo's Punctuations
-
-+ `;` (semicolon). Used at the end of each instruction
-+ `()` (parentheses). Used in a function declaration, if statements, and in a
- tuple declaration
-+ `{}` (curly braces). Used in a declaration of implicit arguments and to define
- code blocks.
-+ `[]` (square brackets). Standalone brackets represent the value at a
- particular address location (such as the allocation pointer, `[ap]`). Brackets
- following a pointer or a tuple act as a subscript operator, where `x[2]`
- represents the element with index `2` in `x`.
-+ `*` (single asterisk). Refers to the pointer of an expression.
-+ `%` (percent sign). Appears at the start of a directive, such as `%builtins`
- or `%lang`.
-+ `%{` and `%}` represent Python hints.
-+ `_` (underscore). A placeholder to handle values that are not used, such as an
- unused function return value.
-
-## Full Contract Example
-
-Below is a simple automated market maker contract example that implements most
-of what we just learnt! Re-write, deploy, have fun!
-
-```
-%lang starknet
-
-from starkware.cairo.common.cairo_builtins import HashBuiltin
-from starkware.cairo.common.hash import hash2
-from starkware.cairo.common.alloc import alloc
-from starkware.cairo.common.math import (assert_le, assert_nn_le,
- unsigned_div_rem)
-from starkware.starknet.common.syscalls import (get_caller_address,
- storage_read, storage_write)
-
-
-// CONSTANTS
-//
-// @dev the maximum amount of each token that belongs to the AMM
-const BALANCE_UPPER_BOUND = 2 ** 64;
-
-const TOKEN_TYPE_A = 1;
-const TOKEN_TYPE_B = 2;
-
-// @dev Ensure the user's balances are much smaller than the pool's balance
-const POOL_UPPER_BOUND = 2 ** 30;
-const ACCOUNT_BALANCE_BOUND = 1073741; // (2 ** 30 / 1000)
-
-
-// STORAGE VARIABLES
-//
-// @dev A map from account and token type to corresponding balance
-@storage_var
-func account_balance(account_id: felt, token_type: felt) -> (balance: felt) {}
-
-// @dev a map from token type to corresponding pool balance
-@storage_var
-func pool_balance(token_type: felt) -> (balance: felt) {}
-
-
-// GETTERS
-//
-// @dev returns account balance for a given token
-// @param account_id Account to be queried
-// @param token_type Token to be queried
-@view
-func get_account_token_balance{syscall_ptr: felt*, pedersen_ptr:
-HashBuiltin*, range_check_ptr}(
- account_id: felt, token_type: felt
- ) -> (balance: felt) {
- return account_balance.read(account_id, token_type);
-}
-
-// @dev return the pool's balance
-// @param token_type Token type to get pool balance
-@view
-func get_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- token_type: felt
- ) -> (balance: felt) {
- return pool_balance.read(token_type);
-}
-
-
-// EXTERNALS
-//
-// @dev set pool balance for a given token
-// @param token_type Token whose balance is to be set
-// @param balance Amount to be set as balance
-@external
-func set_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- token_type: felt, balance: felt
- ) {
- with_attr error_message("exceeds maximum allowed tokens!"){
- assert_nn_le(balance, BALANCE_UPPER_BOUND - 1);
- }
-
- pool_balance.write(token_type, balance);
- return ();
-}
-
-// @dev add demo token to the given account
-// @param token_a_amount amount of token a to be added
-// @param token_b_amount amount of token b to be added
-@external
-func add_demo_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- token_a_amount: felt, token_b_amount: felt
- ) {
- alloc_locals;
- let (account_id) = get_caller_address();
-
- modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_A,
- amount=token_a_amount);
- modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_B,
- amount=token_b_amount);
-
- return ();
-}
-
-// @dev intialize AMM
-// @param token_a amount of token a to be set in pool
-// @param token_b amount of token b to be set in pool
-@external
-func init_pool{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- token_a: felt, token_b: felt
- ) {
- with_attr error_message("exceeds maximum allowed tokens!"){
- assert_nn_le(token_a, POOL_UPPER_BOUND - 1);
- assert_nn_le(token_b, POOL_UPPER_BOUND - 1);
- }
-
- set_pool_token_balance(token_type=TOKEN_TYPE_A, balance=token_a);
- set_pool_token_balance(token_type=TOKEN_TYPE_B, balance=token_b);
-
- return ();
-}
-
-
-// @dev swaps token between the given account and the pool
-// @param token_from token to be swapped
-// @param amount_from amount of token to be swapped
-// @return amount_to the token swapped to
-@external
-func swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
- token_from: felt, amount_from: felt
- ) -> (amount_to: felt) {
- alloc_locals;
- let (account_id) = get_caller_address();
-
- // verify token_from is TOKEN_TYPE_A or TOKEN_TYPE_B
- with_attr error_message("token not allowed in pool!"){
- assert (token_from - TOKEN_TYPE_A) * (token_from - TOKEN_TYPE_B) = 0;
- }
-
- // check requested amount_from is valid
- with_attr error_message("exceeds maximum allowed tokens!"){
- assert_nn_le(amount_from, BALANCE_UPPER_BOUND - 1);
- }
-
- // check user has enough funds
- let (account_from_balance) =
- get_account_token_balance(account_id=account_id, token_type=token_from);
- with_attr error_message("insufficient balance!"){
- assert_le(amount_from, account_from_balance);
- }
-
- let (token_to) = get_opposite_token(token_type=token_from);
- let (amount_to) = do_swap(account_id=account_id, token_from=token_from,
- token_to=token_to, amount_from=amount_from);
-
- return (amount_to=amount_to);
-}
-
-
-// INTERNALS
-//
-// @dev internal function that updates account balance for a given token
-// @param account_id Account whose balance is to be modified
-// @param token_type Token type to be modified
-// @param amount Amount Amount to be added
-func modify_account_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- account_id: felt, token_type: felt, amount: felt
- ) {
- let (current_balance) = account_balance.read(account_id, token_type);
- tempvar new_balance = current_balance + amount;
-
- with_attr error_message("exceeds maximum allowed tokens!"){
- assert_nn_le(new_balance, BALANCE_UPPER_BOUND - 1);
- }
-
- account_balance.write(account_id=account_id, token_type=token_type,
- value=new_balance);
- return ();
-}
-
-// @dev internal function that swaps tokens between the given account and
-// the pool
-// @param account_id Account whose tokens are to be swapped
-// @param token_from Token type to be swapped from
-// @param token_to Token type to be swapped to
-// @param amount_from Amount to be swapped
-func do_swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
-range_check_ptr}(
- account_id: felt, token_from: felt, token_to: felt, amount_from: felt
- ) -> (amount_to: felt) {
- alloc_locals;
-
- // get pool balance
- let (local amm_from_balance) = get_pool_token_balance(token_type =
- token_from);
- let (local amm_to_balance) = get_pool_token_balance(token_type=token_to);
-
- // calculate swap amount
- let (local amount_to, _) = unsigned_div_rem((amm_to_balance *
- amount_from), (amm_from_balance + amount_from));
-
- // update token_from balances
- modify_account_balance(account_id=account_id, token_type=token_from,
- amount=-amount_from);
- set_pool_token_balance(token_type=token_from, balance=(amm_from_balance
- + amount_from));
-
- // update token_to balances
- modify_account_balance(account_id=account_id, token_type=token_to,
- amount=amount_to);
- set_pool_token_balance(token_type=token_to, balance=(amm_to_balance -
- amount_to));
-
- return (amount_to=amount_to);
-}
-
-
-// @dev internal function to get the opposite token type
-// @param token_type Token whose opposite pair needs to be gotten
-func get_opposite_token(token_type: felt) -> (t: felt) {
- if(token_type == TOKEN_TYPE_A) {
- return (t=TOKEN_TYPE_B);
- } else {
- return (t=TOKEN_TYPE_A);
- }
-}
-```
-
-## Additional Resources
-
-+ [Official documentation](https://www.cairo-lang.org/docs/)
-+ [Starknet EDU](https://medium.com/starknet-edu)
-+ [Journey through Cairo](https://medium.com/@darlingtonnnam/journey-through-cairo-i-setting-up-protostar-and-argentx-for-local-development-ba40ae6c5524)
-+ [Demystifying Cairo whitepaper](https://medium.com/@pban/demystifying-cairo-white-paper-part-i-b71976ad0108)
-+ [Learn about StarkNet with Argent](https://www.argent.xyz/learn/tag/starknet/)
-
-## Development Frameworks
-
-+ [Protostar](https://docs.swmansion.com/protostar/docs/tutorials/installation)
-+ [Nile](https://github.com/OpenZeppelin/nile)
-+ [StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html)
-
-## Helpful Libraries
-
-+ [Cairo-lang](https://github.com/starkware-libs/cairo-lang)
-+ [Openzeppelin](https://github.com/OpenZeppelin/cairo-contracts)
-
-## Educational Repos
-
-+ [StarkNet Cairo 101](https://github.com/starknet-edu/starknet-cairo-101)
-+ [StarkNet ERC721](https://github.com/starknet-edu/starknet-erc721)
-+ [StarkNet ERC20](https://github.com/starknet-edu/starknet-erc20)
-+ [L1 -> L2 Messaging](https://github.com/starknet-edu/starknet-messaging-bridge)
-+ [StarkNet Debug](https://github.com/starknet-edu/starknet-debug)
-+ [StarkNet Accounts](https://github.com/starknet-edu/starknet-accounts)
-+ [Min-Starknet](https://github.com/Darlington02/min-starknet)
-
-## Security
-
-+ [Amarna static analysis for Cairo programs](https://blog.trailofbits.com/2022/04/20/amarna-static-analysis-for-cairo-programs/)
-+ [Cairo and StarkNet security by Ctrl03](https://ctrlc03.github.io/)
-+ [How to hack almost any Cairo smart contract](https://medium.com/ginger-security/how-to-hack-almost-any-starknet-cairo-smart-contract-67b4681ac0f6)
-+ [Analyzing Cairo code using Armana](https://dic0de.substack.com/p/analyzing-cairo-code-using-amarna?sd=pf)
-
-## Future TO-DOs
-
-Update tutorial to fit Cairo 1.0
diff --git a/func.html.markdown b/func.html.markdown
deleted file mode 100644
index a31c1da5..00000000
--- a/func.html.markdown
+++ /dev/null
@@ -1,338 +0,0 @@
----
-language: FunC
-filename: learnFunC.fc
-contributors:
- - ["Ivan Romanovich", "https://t.me/ton_learn"]
- - ["Kirill Malev", "https://fslabs.io"]
----
-
-The FunC language is used to program smart contracts on the [The Open Network](https://ton.org) blockchain. Contract logic is executed in TVM, the stack-based TON Virtual Machine.
-
-FunC is a statically typed, which is similar to C.
-
-# Basic syntax, the first Smart Contract — Data Types, Storage, Functions
-
-```c
-;; Single line comment
-
- {- This is a multi-line comment
- {- this is a comment in the comment -}
- -}
-
- (int) sum(int a, int b) {
- ;; This is a function that gets two integer parameters
- ;; and return integer result
- return a + b;
- ;; All integers are signed and are 257 bit long. Overflow throws exception
- ;; expressions must end with a semicolon
- }
-
- () f(int i, cell c, slice s, builder b, cont c, tuple t) {
- ;; FunC has 7 atomic types:
- ;; int - 257 bit signed integers,
- ;; cell - basic for TON opaque data structure,
- ;; which contains up to 1,023 bits and up to 4 references to other cells,
- ;; slice and builder - special objects to read from and write to cells,
- ;; continuation - another flavor of cell that contains
- ;; ready-to-execute TVM byte-code.
- ;; tuple is an ordered collection of up to 255 components,
- ;; having arbitrary value types, possibly distinct.
- ;; Finally tensor type (A,B, ...) is an ordered collection ready for
- ;; mass assigning like: (int, int) a = (3, 5);
- ;; Special case of tensor type is the unit type ().
- ;; It represents that a function doesn’t return any value,
- ;; or has no arguments.
- }
-
- ;; During execution, the contract has read access to local context:
- ;; its storage, balance, time, network config, etc.
- ;; Contract may change its storage and code,
- ;; and also may send messages to other contracts
-
- ;; Let’s write a counter smart contract that gets a number
- ;; from an incoming message,
- ;; adds to already stored numbers and stores result in “storage”
-
- ;; For handling special events, smart contracts have reserved methods:
- ;; recv_internal() handles internal messages from other smart contracts
- ;; recv_external() handles external messages from the outside world —
- ;; e.g., from a user.
-
- () recv_internal(slice in_msg_body) {
- ;; Cells play the role of memory in the stack-based TVM.
- ;; A cell can be transformed into a slice,
- ;; and then the data bits and references to
- ;; other cells from the cell can be obtained
- ;; by loading them from the slice.
- ;; Data bits and references to other cells can be stored
- ;; into a builder, and then the builder can be finalized into a new cell.
- ;; recv_internal gets the slice
- ;; with incoming message data as an argument.
-
- ;; As everything else on TON, permanent storage data is stored as a cell.
- ;; It can be retrieved via the get_data() method
- ;; begin_parse - converts a cell with data into a readable slice
-
- slice ds = get_data().begin_parse();
- ;; `.` is a syntax sugar: a.b() is equivalent to b(a)
-
- ;; load_uint is a function from the FunC standard library;
- ;; it loads an unsigned n-bit integer from a slice
- int total = ds~load_uint(64); ;; `~` is a "modifying" method:
- ;; essentially, it is a syntax sugar: `r = a~b(x)`
- ;; is equivalent to (a,r) = b(a,x)
-
- ;; Now let’s read the incoming value from the message body slice
- int n = in_msg_body~load_uint(32);
-
- total += n;
- ;; integers support usual +-*/ operations as well as (+-*/)= syntax sugar
-
- ;; In order to keep a store integer value, we need to do four things:
- ;; create a Builder for the future cell - begin_cell()
- ;; write a value to total - store_uint(value, bit_size)
- ;; create a Cell from the Builder - end_cell()
- ;; write the resulting cell into permanent storage - set_data()
-
- set_data(begin_cell().store_uint(total, 64).end_cell());
- }
-
-
-
- ;; The FunC program is essentially a list of
- function declarations/definitions and global variable declarations.
-
- ;; Any function in FunC matches the following pattern:
- ;; [<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers>
-
-
- ;; Specifiers:
- ;; The impure specifier indicates that
- ;; function calls should not be optimized
- ;; (whether its result is used or not)
- ;; it is important for methods that change the smart contract data
- ;; or send messages
-
- ;; The method_id specifier allows you to call a GET function by name
-
- ;; For instance, we can create a get method for the contract above
- ;; to allow outside viewers to read counter
-
- int get_total() method_id {
- slice ds = get_data().begin_parse();
- int total = ds~load_uint(64);
-
- ;; Note that (int) and int is the same,
- ;; thus brackets in the function declaration
- ;; and in the return statement are omitted.
- return total;
- }
- ;; Now any observer can read get_total value via lite-client or explorer
-```
-
-# Messages
-
-The actor model is a model of concurrent computation and is at the heart of TON smart contracts. Each smart contract can process one message at a time, change its own state, or send one or several messages. Processing of the message occurs in one transaction, that is, it cannot be interrupted. Messages to one contract are processed consequently one by one. As a result, the execution of each transaction is local and can be parallelized at the blockchain level, which allows for on-demand throughput horizontal scaling and hosting an unlimited number of users and transactions.
-
-```c
-;; For normal internal message-triggered transactions,
-;; before passing control to recv_internal TVM puts the following
-;; elements on stack.
-;;;; Smart contract balance (in nanoTons)
-;;;; Incoming message balance (in nanoTons)
-;;;; Cell with an incoming message
-;;;; Incoming message body, slice type
-;; In turn, recv_internal may use only
-;; the required number of fields (like 1 in the example above or 4 below)
-
-;; Let’s dive into message sending
-
-() recv_internal (
- int balance, int msg_value, cell in_msg_full, slice in_msg_body) {
- ;;
- ;; Every message has a strict layout, thus by parsing it,
- ;; we can get the sender’s address
- ;; first, we need to read some tech flags and
- ;; then take the address using load_msg_addr
- ;; function from FunC standard library - ()
- var cs = in_msg_full.begin_parse();
- var flags = cs~load_uint(4);
- slice sender_address = cs~load_msg_addr();
-
- ;; if we want to send a message, we first need to construct it
- ;; message serialization in most cases may be reduced to
- var msg = begin_cell()
- .store_uint(0x18, 6) ;; tech flags
- .store_slice(addr) ;; destination address
- .store_coins(amount) ;; attached value
- .store_uint(0, 107) ;; more tech flags :)
- .store_slice(in_msg_body) ;; just put some payload here
- .end_cell();
-
- ;; to send messages, use send_raw_message from the standard library.
- ;; it accepts two arguments message and mode
- send_raw_message(msg, 64);
-
- ;; mode parameter specifies how to process the funds passed into
- ;; the smart contract with the message and the smart contract funds
- ;; 64 means send everything from the incoming message —
- ;; what’s left after the commission is deducted
-
- ;; Exceptions can be thrown by conditional primitives throw_if and
- ;; throw_unless and by unconditional throw
- ;; by default, it will automatically cause a bounce message with 64 mode
-
- var some = 7;
- throw_if(102, some == 10);
- ;; Throw exception with code 102 conditionally
- throw_unless(103, some != 10);
- ;; Throw exception with code 103 conditionally
- throw(101); ;; Throw exception with code 101 unconditionally
-}
-```
-
-# Flow control: Conditional Statements and Loops; Dictionaries
-
-```c
-;; FunC, of course, supports if statements
-
-;;;; usual if-else
-if (flag) {
- ;;do_something();
-}
-else {
- ;;do_alternative();
-}
-
-;; If statements are often used as an operation identifier
-;; for a smart contract, for example:
-
-() recv_internal (
- int balance, int msg_value, cell in_msg_full, slice in_msg_body) {
- int op = in_msg_body~load_int(32);
- if (op == 1) {
- ;; smth here
- } else {
- if (op == 2) {
- ;; smth here
- } else {
- ;; smth here
- }
- }
-}
-
-;; Loops
-;; FunC supports repeat, while and do { ... } until loops.
-;; for loop is not supported.
-
-;; repeat
-int x = 1;
-repeat(10) {
- x *= 2;
-}
-;; x = 1024
-
-;; while
-int x = 2;
-while (x < 100) {
- x = x * x;
-}
-;; x = 256
-
-;; until loops
-int x = 0;
-do {
- x += 3;
-} until (x % 17 == 0);
-;; x = 51
-
-;; In practice, loops in TON smart contracts are often used to work with
-;; dictionaries, or as they are also called in TON hashmaps
-
-;; A hashmap is a data structure represented by a tree.
-;; Hashmap maps keys to values ​​of arbitrary type so that
-;; quick lookup and modification are possible.
-
-;; udict_get_next? from FunC standard library in combination with
-;; the loop will help, go through the dictionary
-
-int key = -1;
-do {
- (key, slice cs, int f) = dic.udict_get_next?(256, key);
-
-} until (~ f);
-
-;; udict_get_next? - Calculates the minimum key k in the dictionary dict
-;; that is greater than some given value and returns k,
-;; the associated value, and a flag indicating success.
-;; If the dictionary is empty, returns (null, null, 0).
-```
-
-# Functions
-
-```c
-;; Most useful functions are slice reader and builder writer primitives,
-;; storage handlers and sending messages
-
-;; slice begin_parse(cell c) - Converts a cell into a slice
-;; (slice, int) load_int(slice s, int len) -
-;; Loads a signed len-bit integer from a slice.
-;; (slice, int) load_uint(slice s, int len) -
-;; Loads a unsigned len-bit integer from a slice.
-;; (slice, slice) load_bits(slice s, int len) -
-;; Loads the first 0 ≤ len ≤ 1023 bits from slice into a separate slice.
-;; (slice, cell) load_ref(slice s) - Loads the reference cell from the slice.
-
-;; builder begin_cell() - Creates a new empty builder.
-;; cell end_cell(builder b) - Converts a builder into an ordinary cell.
-;; builder store_int(builder b, int x, int len) -
-;; Stores a signed len-bit integer x into b for 0 ≤ len ≤ 257.
-;; builder store_uint(builder b, int x, int len) -
-;; Stores an unsigned len-bit integer x into b for 0 ≤ len ≤ 256.
-;; builder store_slice(builder b, slice s) - Stores slice s into builder b.
-;; builder store_ref(builder b, cell c) -
-;; Stores a reference to cell c into builder b.
-
-;; cell get_data() - Returns the persistent contract storage cell.
-;; () set_data(cell c) - Sets cell c as persistent contract data.
-
-;; () send_raw_message(cell msg, int mode) -
-;; put message msg into sending queue with mode.
-;; Note, that message will be sent after a successful execution
-;; of the whole transaction
-
-;; Detailed descriptions of all standard functions can be found
-;; in docs https://ton.org/docs/#/func/stdlib
-;;
-```
-
-## Additional resources
-- [FunC Lessons](https://github.com/romanovichim/TonFunClessons_Eng)
-- [TON Development Onboarding](https://www.tonspace.co)
-- [TON Documentation](https://ton.org/docs/#/)
-- [FunC Documentation](https://ton.org/docs/#/func/overview)
-- [TON Smart Contracts examples](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont)
-- [Community portal](https://society.ton.org)
-- [Blockchain portal](https://ton.org)
-- [Stackoverflow](https://stackoverflow.com/questions/tagged/ton)
-
-## Social
-- [Developer community](https://t.me/tondev_eng)
-- [TON Learn](https://t.me/ton_learn)
-- [FunC Lessons Channel](https://github.com/romanovichim/TonFunClessons_Eng)
-- [FunC onboarding](https://t.me/func_guide)
-- [Tondev News](https://t.me/tondevnews)
-
-## Useful blogposts
-- [Setting up a TON Development Environment](https://society.ton.org/setting-up-a-ton-development-environment)
-- [Hello World on TON](https://society.ton.org/ton-hello-world-step-by-step-guide-for-writing-your-first-smart-contract-in-func)
-
-
-## Future To Dos
-- Add smart contracts examples
-- Add more posts
-
-
-This file is mostly copied from [TonFunClessons 15 minutes intro](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/13lesson/15min.md).
-
-P.S. If by any chance you're familiar with [Forth](https://learnxinyminutes.com/docs/forth/), you can also take a look at [Fift](https://ton-blockchain.github.io/docs/fiftbase.pdf).
diff --git a/tact.html.markdown b/tact.html.markdown
deleted file mode 100644
index 73a0d4df..00000000
--- a/tact.html.markdown
+++ /dev/null
@@ -1,602 +0,0 @@
----
-language: Tact
-filename: tact.tc
-contributors:
- - ["Tal Kol", "https://www.orbs.com/"]
- - ["Kirill Malev", "https://fslabs.io"]
- - ["Yash Garg", "https://github.com/yash0501"]
----
-
-Tact language is used to program smart contracts on the
-[The Open Network](https://ton.org) blockchain. Contract logic is executed in
-TVM, the stack-based TON Virtual Machine.
-
-Tact is a statically typed, but language was designed to be friendly for
-developers with JS and Python background.
-
-This page is based on [Tact-by-Example](https://tact-by-example.org/).
-You can use this resource to play around with contracts and check out
-the interactive features.
-
-# Basic syntax, function definition
-
-```c
-// Single line comment
-
- // This is a multi-line comment
- // this is a comment in the comment
-
- get fun greeting(): String {
- // This is a function that returns "hello world" message
- // Return type is specified after a colon :
- return "hello world";
- }
-```
-
-# A Simple Counter contract
-
-This is a simple counter contract that allows users to increment its value.
-
-This contract has a state variable `val` that persists between contract calls
-
-- the counter value. When persisted, this variable is encoded as `uint32` -
- a 32-bit unsigned integer. Contracts pay rent in proportion to the amount
- of persistent space they consume, so compact representations are encouraged.
-
-State variables should be initialized in `init()` that runs on deployment of
-the contract.
-
-## Messages
-
-The actor model is a model of concurrent computation and is at the heart of TON
-smart contracts. Each smart contract can process one message at a time, change
-its own state, or send one or several messages. Processing of the message
-occurs in one transaction, that is, it cannot be interrupted. Messages to one
-contract are processed consequently one by one. As a result, the execution of
-each transaction is local and can be parallelized at the blockchain level,
-which allows for on-demand throughput horizontal scaling and hosting an
-unlimited number of users and transactions.
-
-## Receiving messages
-
-This contract can receive messages from users. Unlike getters that are just
-read-only, messages can do write operations and change the contract's
-persistent state. Incoming messages are processed in receive() methods as
-transactions and cost gas for the sender.
-
-After deploying the contract, send the increment message by pressing the Send
-increment button in order to increase the counter value by one. Afterwards,
-call the getter value() to see that the value indeed changed.
-
-```c
-contract Counter {
-// Tact allows to create a contract
- // persistent state variable of type Int to hold the counter value
- val: Int as uint32;
-
- // initialize the state variable when contract is deployed
- init() {
- self.val = 0;
- }
-
- // handler for incoming increment messages that change the state
- receive("increment") {
- self.val = self.val + 1;
- }
-
- // read-only getter for querying the counter value
- get fun value(): Int {
- return self.val;
- }
-}
-```
-
-# The Deployable Trait
-
-Tact doesn't support classical class inheritance, but contracts can implement
-traits. One of the commonly used traits is `Deployable`. It implements a simple
-receiver for the Deploy message which helps deploy contracts in a standard way.
-
-All contracts are deployed by sending them a message. This can be any message,
-but best practice is to designate the special `Deploy`
-message for this purpose.
-
-This message has a single field, `queryId`, which is provided by the deployer
-(normally zero). If the deploy succeeds, the contract will reply with the
-message `DeployOk` and echo the same `queryId` in the response.
-
-If you're using Tact's [auto-generated](https://docs.tact-lang.org/tools/typescript#tact-contract-in-typescript) TypeScript
-classes to deploy, sending the deploy message should look like:
-
-```c
-const msg = { $$type: "Deploy", queryId: 0n };
- await contract.send(sender, { value: toNano(1) }, msg);
-```
-
-You can see the implementation of the trait [here](https://github.com/tact-lang/tact/blob/main/stdlib/libs/deploy.tact).
-Notice that the file deploy.tact needs to be imported from the standard
-library using the import keyword.
-
-```c
-// this trait has to be imported
-import "@stdlib/deploy";
-
-// the Deployable trait adds a default receiver for the "Deploy" message
-contract Counter with Deployable {
-
- val: Int as uint32;
-
- init() {
- self.val = 0;
- }
-
- receive("increment") {
- self.val = self.val + 1;
- }
-
- get fun value(): Int {
- return self.val;
- }
-}
-```
-
-# Integers
-
-Tact supports a number of primitive data types that are tailored for
-smart contract use.
-
-`Int` is the primary number type. Math in smart contracts is always done
-with integers and never with floating points since floats are [unpredictable](https://learn.microsoft.com/en-us/cpp/build/why-floating-point-numbers-may-lose-precision).
-
-The runtime type `Int` is always 257-bit signed, so all runtime calculations
-are done at 257-bit. This should be large enough for pretty much anything you
-need as it's large enough to hold the number of atoms in the universe.
-
-Persistent state variables can be initialized inline or inside `init()`.
-If you forget to initialize a state variable, the code will not compile.
-
-## State costs
-
-When encoding `Int` to persistent state, we will usually use smaller
-representations than 257-bit to reduce storage cost.
-The persistent state size is specified in every declaration of
-a state variable after the `as` keyword.
-
-Storing 1000 257-bit integers in state [costs](https://ton.org/docs/develop/smart-contracts/fees#how-to-calculate-fees) about
-0.184 TON per year. Storing 1000 32-bit integers only costs
-0.023 TON per year by comparison.
-
-```c
-import "@stdlib/deploy";
-
-contract Integers with Deployable {
-
- // contract persistent state variables
- // integers can be persisted in state in various sizes
- // range -2^256 to 2^256 - 1 (takes 257 bit = 32 bytes + 1 bit)
- i1: Int as int257 = 3001;
- i2: Int as uint256; // range 0 to 2^256 - 1 (takes 256 bit = 32 bytes)
- // range -2^255 to 2^255 - 1 (takes 256 bit = 32 bytes)
- i3: Int as int256 = 17;
- i4: Int as uint128; // range 0 to 2^128 - 1 (takes 128 bit = 16 bytes)
- // range -2^127 to 2^127 - 1 (takes 128 bit = 16 bytes)
- i5: Int as int128;
- i6: Int as coins; // range 0 to 2^120 - 1 (takes 120 bit = 15 bytes)
- // range 0 to 18,446,744,073,709,551,615 (takes 64 bit = 8 bytes)
- i7: Int as uint64 = 0x1c4a;
- // range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
- // (takes 64 bit = 8 bytes)
- i8: Int as int64 = -203;
- i9: Int as uint32 = 0; // range 0 to 4,294,967,295 (takes 32 bit = 4 bytes)
- // range -2,147,483,648 to 2,147,483,647 (takes 32 bit = 4 bytes)
- i10: Int as int32 = 0;
- i11: Int as uint16 = 0; // range 0 to 65,535 (takes 16 bit = 2 bytes)
- i12: Int as int16 = 0; // range -32,768 to 32,767 (takes 16 bit = 2 bytes)
- i13: Int as uint8 = 0; // range 0 to 255 (takes 8 bit = 1 byte)
- i14: Int as int8 = 0; // range -128 to 127 (takes 8 bit = 1 byte)
-
- init() {
- // we can define numbers in hex (base 16)
- self.i2 = 0x83dfd552e6372;
- self.i4 = 1507998500293440234999; // we can define numbers in decimal
- self.i5 = pow(10, 9); // this is 10^9 = 1,000,000,000
- self.i6 = ton("1.23"); // easy to read coin balances
- // (coins type is nano-tons, like cents, just with 9 decimals)
- }
-
- receive("show all") {
- dump(self.i1);
- dump(self.i2);
- dump(self.i3);
- dump(self.i4);
- dump(self.i5);
- dump(self.i6);
- dump(self.i7);
- dump(self.i8);
- }
-
- get fun result(): Int {
- return self.i1;
- }
-}
-```
-
-## Bools, Addresses, Strings, Operators and Constants
-
-### Bool
-
-Bool can be used for boolean variables
-
-```js
-b1: Bool = true;
-b2: Bool = false;
-```
-
-### Address
-
-Address is another primitive data type. It represents standard addresses on
-the TON blockchain.
-TON is divided into multiple chains called workchains. One of the internal
-fields of the address is the workchain id:
-0 - The standard workchain, for regular users. Your contracts will be here.
--1 - The masterchain, usually for validators.
-
-```js
-// bouncable (same foundation wallet)
-a1: Address = address("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N");
-// non-bounceable (same foundation wallet)
-a2: Address = address("UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBI");
-```
-
-### String
-
-Tact has basic support for strings. Strings support unicode and don't
-have any special escape characters like \n.
-Strings are immutable. Once a sequence of characters is created, this
-sequence cannot be modified.
-If you need to concatenate strings in run-time, you can use a StringBuilder.
-This object handles gas efficiently and supports append() of various types to
-the string.
-
-```js
-s1: String = "hello world";
-sb: StringBuilder = beginString();
-sb.append(self.s1);
-```
-
-### Integer Operations
-
-Addition, subtraction, multiplication, division, modulo,
-shift left and right, minimum and maximum numbers, absolute value
-
-```js
-i: Int = -12; // temporary variable, runtime Int type is always int257
-i = i1 * 3 + (i2 - i); // basic math expressions
-i = i1 % 10; // modulo (remainder after division), 3001 % 10 = 1
-i = i1 / 1000; // integer division (truncation toward zero), 3001 / 1000 = 3
-i = i1 >> 3; // shift right (multiply by 2^n)
-i = i1 << 2; // shift left (divide by 2^n)
-i = min(i2, 11); // minimum between two numbers
-i = max(i2, 66); // maximum between two numbers
-i = abs(-1 * i2); // absolute value
-```
-
-### Constants
-
-Unlike variables, constants cannot change. Their values are
-calculated in compile-time and cannot change during execution.
-
-```js
-const StateUnpaid: Int = 0;
-```
-
-## Getters, Receivers and Messages
-
-### Getters
-
-Getters are special contract functions that allow users to query
-information from the contract.
-Contract methods starting with the prefix get fun are all getters.
-Calling getters is free and does not cost gas.
-Getters are read-only, they cannot change the contract persistent state.
-A contract cannot execute a getter of another contract. Getters are only
-executable by end-users off-chain.
-
-```js
-count: Int as uint32 = 17;
-
-get fun counter(): Int {
- return self.count;
-}
-```
-
-### Receivers
-
-Contract methods named receive() are the handlers that process
-each incoming message type.
-Tact will automatically route every incoming message to the correct receiver
-listening for it according to its type. A message is only handled by one receiver.
-
-Handler for "increment" textual message - this is a textual string message,
-these cannot carry input arguments
-
-```js
-receive("increment") {
- self.val = self.val + 1;
-}
-```
-
-### Messages
-
-Messages are defined using the message keyword. They can carry input
-arguments. For integers, you must define the encoding size, just like in
-state variables.
-
-Handler for the "Add" message - this is a binary message that has an input
-argument (amount)
-
-```js
-receive(msg: Add) {
- self.val = self.val + msg.amount;
-}
-```
-
-## Structs
-
-Structs allow you to combine multiple primitives together in a more semantic way.
-Structs can define complex data types that contain multiple fields of
-different types. They can also be nested.
-
-```js
-// Normal struct
-struct Point {
- x: Int as int64;
- y: Int as int64;
-}
-
-// Nested struct
-struct Params {
- name: String = "Satoshi"; // default value
- age: Int? = null; // optional field
- point: Point; // nested structs
-}
-```
-
-## Message Sender and Throwing Errors
-
-### Message Sender
-
-Every incoming message is sent from some contract that has
-an address. You can query the address of the message sender by calling sender()
-
-```js
-deployer: Address = sender();
-```
-
-### Errors
-
-When an error is thrown, the transaction reverts. By writing a
-require() on a condition that isn't met
-
-```js
-require(self.val < 5, "Counter is too high");
-```
-
-## Messages Between Contracts, Sending and Receiving TON Coins
-
-### Messages Between Contracts
-
-Different contracts can only communicate with
-each other by sending each other messages.
-
-This example sends a message to the to address with value of 1 TON and body
-of a comment with a string "Hello, World!".
-SendIgnoreErrors means that even when error occurs during message sending
-next messages would be sent anyway.
-
-```js
-let to: Address = ...;
-let value: Int = ton("1");
-send(SendParameters{
- to: to, // address of receiver
- value: value, // amount of TON you want to send
- mode: SendIgnoreErrors, // 8-bit flag configuring how to send message
- bounce: true, // if set to true (default) then message
- // will be bounced back to sender
- body: "Hello, World!".asComment() // message body as Cell
-});
-```
-
-### Receiving TONs
-
-You can query the contract balance with myBalance() - note
-that the value is in nano-tons (like cents, just with 9 decimals). The balance
-already contains the incoming message value.
-You can also get the incoming TON balance with context().value
-
-```js
-val: Int as int64 = myBalance()
-// or
-// print how much TON coin were sent with this message
-dump(context().value);
-```
-
-### Sending TONs
-
-We can send any amount of TON to any address just like we created
-a send call between different contracts
-
-Send mode SendRemainingValue will add to the outgoing value any excess left
-from the incoming message after all gas costs are deducted from it.
-
-```js
-amount: Int as coins = ton("1");
-send(SendParameters{
- to: sender(),
- bounce: true,
- value: amount,
- mode: SendRemainingValue + SendIgnoreErrors
-});
-```
-
-## If/Else statements and Loops
-
-### If
-
-Tact supports if statements in a similar syntax to most programming
-languages. Curly braces are required.
-We can have the else and else if similar to other programming languages.
-
-```js
-if (val > 1000) {
- dump("larger than 1000");
-} else if (val > 500) {
- dump("between 500 and 1000");
-} else {
- dump("smaller than 500");
-}
-```
-
-### Loops
-
-Tact does not support traditional 'for' loops, 'break' and 'continue'
-statements in loops.
-The repeat loop statement input number must fit within an int32.
-
-```js
-// repeat exactly 10 times
-
-repeat (10) {
- i = i + 1;
- sum = sum + i;
-}
-
-// While loop
-
-let x: Int = 10;
-while(x > 0) {
- x = x - 1;
-}
-
-// do-until loop
-
-let x: Int = 10;
-do {
- x = x - 1;
-} until (x <= 0);
-```
-
-## Functions
-
-Functions in Tact start with the fun keyword. Functions can receive multiple
-input arguments and can optionally return a single output value. You can
-return a struct if you want to return multiple values.
-
-```js
-fun average(a: Int, b: Int): Int {
- return (a + b) / 2;
-}
-```
-
-## Maps and Arrays
-
-### Maps
-
-Maps are a dictionary type that can hold an arbitrary number of items,
-each under a different key.
-The keys in maps can either be an Int type or an Address type.
-You can check if a key is found in the map by calling the get() method.
-Replace the value under a key by calling the set() method.
-
-```js
-mi1: map<Int, TokenInfo>; // maps with Int as key
-ma1: map<Address, TokenInfo>; // maps with Address as key
-```
-
-### Arrays
-
-To create an array, define a map with 'Int' type as key as well as value.
-
-```js
-arr: map<Int, Int>; // this is our array implemented with a map
-```
-
-## Ownable Standard Library
-
-The Ownable trait allows the contract to set an owner role, which can have
-higher priviliges from everybody else.
-For this you would need to import the "@stdlib/ownable" library and inherit
-it in your contract
-
-- Use the self.requireOwner() call to verify that the person making that
- function call is the owner of contract
-- 'ChangeOwner{newOwner: Address}' message which allows the owner to
- transfer ownership.
-- Define state variables named 'owner: Address' and 'stopped: Bool' and
- call 'self.requireNotStopped()' on actions that should be stopped.
-- Define state variables named 'owner: Address' and "stopped: Bool' and
- call 'self.requireNotStopped()' on actions that should be stopped.
-
-```js
-import "@stdlib/ownable";
-import "@stdlib/deploy";
-
-contract Counter with Deployable, Ownable {
- owner: Address;
-
- init() { // initialize a contract with default values like 'constructor'
- self.owner = sender(); // we can initialize owner to any value we want, the deployer in this case
- self.val = 0;
- }
-
- // this message in only available to the owner
- receive("double") {
- self.requireOwner();
- self.val = self.val * 2;
- }
-
- // this message will only work until the contract was stopped
- receive("increment") {
- self.requireNotStopped();
- self.val = self.val + 1;
- }
-
- // this message will only work as long as the contract is not stopped
- receive("increment2") {
- self.requireNotStopped();
- self.val = self.val + 1;
- }
-}
-```
-
-## Additional resources
-
-- [TON Documentation](https://ton.org/docs/#/)
-- [Tact Docs](https://docs.tact-lang.org/)
-- [Tact by Example](https://tact-by-example.org/)
-- [Community portal](https://society.ton.org)
-- [Blockchain portal](https://ton.org)
-- [Stackoverflow](https://stackoverflow.com/questions/tagged/ton)
-
-## Social
-
-- [Tact community](https://t.me/tactlang)
-- [Developer community](https://t.me/tondev_eng)
-- [TON Learn](https://t.me/ton_learn)
-- [Tondev News](https://t.me/tondevnews)
-- [TON Technical Updates](https://t.me/thetontech)
-
-## Useful blogposts
-
-- [Setting up a TON Development Environment](https://society.ton.org/setting-up-a-ton-development-environment)
-- [Hello World on TON](https://society.ton.org/ton-hello-world-step-by-step-guide-for-writing-your-first-smart-contract-in-func)
-
-## Future To Dos
-
-- Add smart contracts examples
-- Add more links to documentations
-
-This file is based on [Tact By Example](https://tact-by-example.org).
-
-P.S. If by any chance you're familiar with [Forth](https://learnxinyminutes.com/docs/forth/),
-you can also take a look at [Fift](https://ton-blockchain.github.io/docs/fiftbase.pdf).
diff --git a/vyper.html.markdown b/vyper.html.markdown
deleted file mode 100644
index dd319ae5..00000000
--- a/vyper.html.markdown
+++ /dev/null
@@ -1,871 +0,0 @@
----
-language: Vyper
-filename: learnVyper.vy
-contributors:
- - ["Kenny Peluso", "kennyp.herokuapp.com"]
----
-
-> The content of this document is largely inspired by ["Learn Solidity in Y Minutes"](https:#github.com/adambard/learnxinyminutes-docs/blob/master/solidity.html.markdown)
-
-Vyper lets you program on [Ethereum](https:#www.ethereum.org/), a
-blockchain-based virtual machine that allows the creation and
-execution of smart contracts, without requiring centralized or trusted parties. It was
-designed to improve upon Solidity, another smart contract language for Ethereum, by
-limiting unsafe practices and enhancing readability; Vyper seeks to optimize the
-security and auditability of smart contracts.
-
-Vyper is an experimental, statically typed, contract programming language meant to
-resemble Python. Like objects in OOP, each contract contains state variables, functions,
-and common data types. Contract-specific features include event notifiers for listeners,
-and custom global variables, global constants.
-
-Some Ethereum contract examples include crowdfunding, voting, and blind auctions.
-
----
-
-## Table of Contents
-
-- Intro
-- Example
-1. Data types and associated methods
-2. Data structures
-3. Simple operators
-4. Global variables of note
-5. Functions and more
- a. functions
- b. events
-6. Branching and loops
-7. Objects/contracts
- a. calling external contracts
- b. ERC20 built-in
- c. following an interface
-8. Other keywords
- a. selfdestruct
-9. Contract design notes
- a. obfuscation
- b. storage optimization
- c. data access in blockchain
- d. cron job
- e. observer pattern
-10. Security
-11. Style notes
-12. Natspec comments
-- Other documents
-
----
-
-## Intro
-
-From [the docs](https://media.readthedocs.org/pdf/vyper/latest/vyper.pdf)
-the foundational tenants of Vyper are:
-
-1. *Security*
-2. *Language and compiler simplicity*
-3. *Auditability*
-
-This allows for the following features:
-
-1. *Bounds and overflow checking*
- - On the arithmetic and array level
- - There are no dynamic arrays in Vyper
-2. *Support for signed integers and decimal fixed point numbers*
-3. *Decidability* - You can always compute precise upper bound on gas cost
-4. *Strong typing* - for built-in and custom types
-5. *Small and understandable compiler code*
-6. *Limited support for pure functions*
- - Anything marked `@constant` is not allowed to change the state
-
-Following the principles and goals, Vyper does not provide the following features:
-
-1. *Modifiers* (defining parts of functions elsewhere)
-2. *Class inheritance*
-3. *Inline assembly*
-4. *Function overloading*
-5. *Operator overloading*
-6. *Recursive calling*
-7. *Infinite-length loops*
-8. *Binary fixed point* (decimal fixed point is used for its exactness)
-
-WITH THE RAPID CHANGES IN ETHEREUM, THIS DOCUMENT IS UNLIKELY TO STAY UP TO
-DATE, SO YOU SHOULD FOLLOW THE LATEST VYPER DOCS AND ETHEREUM BLOG FOR THE LATEST.
-ALL CODE HERE IS PROVIDED AS IS, WITH SUBSTANTIAL RISK OF ERRORS OR DEPRECATED CODE
-PATTERNS.
-
-This document primarily discusses syntax, and so excludes many
-popular design patterns.
-
-As Vyper and Ethereum are under active development, experimental or beta
-features are typically marked, and subject to change. Pull requests welcome.
-
-This document describes Vyper version `0.1.0-beta.8`.
-
-*All of the following code exists for educational purposes only!*
-*None of the following code should be used in production as-is!*
-
-## Example
-
-```python
-# First, a simple todo list contract
-# Implements CRUD operations for tasks
-
-# todo.vy (note .vy extension)
-### **** START EXAMPLE **** ###
-
-# Start with Natspec comment
-# used for documentation
-
-# @title SimpleBank v1
-# @author kennyp
-# @notice This is a simple bank.
-
-# Vyper contracts must obey a particular order:
-# struct -> interface -> events -> globals and constants -> functions
-# Additionally, like Python, Vyper functions must be defined in the file
-# before they're called.
-
-# Structs
-
-struct Task:
- done: bool
- deleted: bool
- task: string[100]
- metadata: bytes32
-
-# Interfaces
-
-contract AnotherContract():
- def fetch() -> bytes32: constant
- def inform(_taskId: uint256, _status: uint256) -> bool: modifying
-
-# Events
-
-# Events - publicize actions to external listeners
-# `indexed` means that it's easier to search/filter on this field
-TaskStatus: event({_taskId: indexed(uint256), _status: uint256})
-
-# Global Variables
-
-# State variables are values which are permanently stored in contract storage
-# State vars consist of any value persisting beyond any function's scope
-# and are permanently stored in contract storage
-
-# You can define your own, custom, unmutable constants
-CREATED: constant(uint256) = 0
-COMPLETED: constant(uint256) = 1
-DELETED: constant(uint256) = 2
-
-# The `public` built-in allows for this address to be read externally
-# without defining a `get()` constant function
-owner: public(address)
-other: public(address)
-
-# uint256 means "unsigned positive integer between 0 and 2^256 - 1"
-# Overflow protection is built-in to Vyper
-taskCount: uint256
-tasks: map(uint256, Task) # dictionary: key=uint256, value: Task struct
-
-# Private Functions
-
-# Start each function with Pythonic decorators
-# These decorators resemble Natspec but are actually enforced by Vyper's compiler
-# These decorators are:
-# @public XOR @private (either one or the other)
-# @public (if any contract/user can call it)
-# @private (if only internal functions can call it)
-# @payable (if the function is payable i.e. accepting ETH)
-# @constant (if the function is not modifying anything on-chain)
-@private
-def _changeTaskStatus( \
- _sender: address, \
- _taskId: uint256, \
- _status: uint256, \
- ):
- # backslashes (\) allow for multi-line code
- # Natspec comments are particularly helpful for documentation and readability
- # Natspec can be included using familiar Pythonic docstring syntax
- """
- @notice
- @dev `_sender` MUST be `self.owner`
- @param _sender Who is triggering this function
- @param _task The description of the task (only useful when task added)
- """
- # NOTE: Private functions do not have access to `msg.sender`
- # SIDE NOTE: `msg.sender` refers to whoever immediately called the function of
- # immediate scope. In other words, if I call a function that calls another
- # in-contract, public function, then `msg.sender` turns from my address to
- # the address of the current contract.
- assert _sender == self.owner # failed assertions cause calls/transactions to fail
- # Note that unlike Solidity, `self.` is required to query the contract's state
- # Control flow is Pythonic, as is much of Vyper:
- _task: string[100] # initialized to default value
- _data: bytes32 = sha3(convert(_sender, bytes32)) # owner is obfuscated (but still visible in logs)
- if _status == CREATED: # control flow mimics python
- # How a new struct is instantiated:
- self.tasks[_taskId] = Task({ \
- done: False, deleted: False, task: _task, metadata: _data \
- })
- elif _status == COMPLETED:
- # Modifying an existing struct:
- self.tasks[_taskId].done = True
- elif _status == DELETED:
- self.tasks[_taskId].deleted = True
- AnotherContract(self.other).inform(_taskId, _status) # modifying external call
- log.TaskStatus(_taskId, _status) # emit an event
-
-# Public Functions
-
-# Pythonic constructor - can receive none or many arguments
-@public
-def __init__(_owner: address, _other_contract: address):
- """
- @dev Called once and only upon contract depoyment
- """
- self.owner = _owner
- self.other = _other_contract
-
-# NOTE: Pythonic whitespace rules are mandated in Vyper
-
-@public
-def addTask(_task: string[100]) -> uint256:
- """
- @notice Adds a task to contract
- @param _task Description of task
- @return Id of newly minted task
- """
- # msg.sender gives the address of who/what contract is calling this function
- self._changeTaskStatus(msg.sender, self.taskCount, CREATED)
- self.tasks[self.taskCount].task = _task
- self.taskCount += 1
- return self.taskCount - 1
-
-@public
-def addSpecialTask(_task: string[100]) -> uint256:
- """
- @notice Adds a task with metadata pulled from elsewhere
- @param _task Description of task
- @return Id of newly minted task
- """
- self._changeTaskStatus(msg.sender, self.taskCount, CREATED)
- self.tasks[self.taskCount].task = _task
- self.tasks[self.taskCount].metadata = AnotherContract(self.other).fetch()
- self.taskCount += 1
- return self.taskCount - 1
-
-@public
-def completeTask(_taskId: uint256):
- """
- @notice Marks a task as "completed"
- @param _taskId Id of task to complete
- """
- self._changeTaskStatus(msg.sender, _taskId, COMPLETED)
-
-@public
-def deleteTask(_taskId: uint256):
- """
- @notice Adds a task to contract
- @param _taskId Id of task to delete
- """
- self._changeTaskStatus(msg.sender, _taskId, DELETED)
-
-@public
-@constant # allows function to run locally/off blockchain
-def getTask(_taskId: uint256) -> string[100]:
- """
- @notice Getter for a task's description
- @param _taskId Id of task with desired description
- @return Description of task
- """
- return self.tasks[_taskId].task
-
-### **** END EXAMPLE **** ###
-
-
-# Now, the basics of Vyper
-
-
-# ---
-
-
-# 1. DATA TYPES AND ASSOCIATED METHODS
-# uint256 used for currency amount and for dates (in unix time)
-x: uint256
-
-# int of 128 bits, cannot be changed after contract deployment
-# with 'constant', compiler replaces each occurrence with actual value
-a: constant(int128) = 5
-
-# All state variables (those outside a function)
-# are by default 'internal' and accessible inside contract
-# Need to explicitly set to 'public' to allow external contracts to access
-# A getter is automatically created, but NOT a setter
-# Can only be called in the contract's scope (not within functions)
-# Add 'public' field to indicate publicly/externally accessible
-a: public(int128)
-
-# No random functions built in, use other contracts for randomness
-
-# Type casting is limited but exists
-b: int128 = 5
-x: uint256 = convert(b, uint256)
-
-# Types of accounts:
-# Contract Account: f(creator_addr, num_transactions)=address set on contract creation
-# External Account: (person/external entity): f(public_key)=address
-
-# Addresses - An address type can hold an Ethereum address which
-# equates to 20 bytes or 160 bits. It returns in hexadecimal notation
-# with a leading 0x. No arithmetic allowed
-owner: public(address)
-
-# Members can be invoked on all addresses:
-owner.balance # returns balance of address as `wei_value`
-owner.codesize # returns code size of address as `int128`
-owner.is_contract # `True` if Contract Account
-
-# All addresses can be sent ether via `send()` built-in
-@public
-@payable
-def sendWei(any_addr: address):
- send(any_addr, msg.value)
-
-# Bytes available
-a: bytes[2]
-b: bytes[32]
-c: bytes32
-# `b` and `c` are 2 different types
-
-# Bytes are preferable to strings since Vyper currently offers better
-# support for bytes i.e. more built-ins to deal with `bytes32`, `bytes32`
-# can be returned from functions and strings[] can't be, UTF8 (string encoding)
-# uses more storage, etc.
-
-# There are no dynamically sized bytes, similar to how there are no
-# dynamic arrays
-
-# Fixed-size byte arrays (Strings)
-a: string[100]
-b: string[8]
-c: string[108] = concat(a, b) # check the latest docs for more built-ins
-
-# Time
-t1: timedelta
-t2: timestamp
-# Both types are built-in "custom type" variants of `uint256`
-# `timedelta` values can be added but not `timestamp` values
-
-# Money
-m: wei_value
-# Also has the base type `uint256` like `timestamp` and `timedelta`
-# 1 unit of WEI (a small amount of ETH i.e. ether)
-
-# Custom types
-# specify units used in the contract:
-units: {
- cm: "centimeter",
- km: "kilometer"
-}
-# usage:
-a: int128(cm)
-b: uint256(km)
-
-# BY DEFAULT: all values are set to 0 on instantiation
-
-# `clear()` can be called on most types
-# Does NOT destroy value, but sets value to 0, the initial value
-
-
-# ---
-
-
-# 2. DATA STRUCTURES
-# Arrays
-bytes32[5] nicknames; # static array
-bytes32[] names; # dynamic array
-uint newLength = names.push("John"); # adding returns new length of the array
-# Length
-names.length; # get length
-names.length = 1; # lengths can be set (for dynamic arrays in storage only)
-
-# Multidimensional Arrays
-# At initialization, array dimensions must be hard-coded or constants
-# Initialize a 10-column by 3-row, multidimensional fixed array
-ls: (uint256[10])[3] # parentheses are optional
-@public
-def setToThree():
- # Multidimensional Array Access and Write
- # access indices are reversed
- # set element in row 2 (3rd row) column 5 (6th column) to 3
- self.ls[2][5] = 3
-
-# Dictionaries (any simple type to any other type including structs)
-theMap: map(uint256, bytes32)
-theMap[5] = sha3("charles")
-# theMap[255] result is 0, all non-set key values return zeroes
-# To make read public, make a getter that accesses the mapping
-@public
-def getMap(_idx: uint256) -> bytes32:
- """
- @notice Get the value of `theMap` at `_idx`
- """
- return self.theMap[_idx]
-
-self.getMap(5) # returns sha3("charles") in bytes32
-
-# Nested mappings
-aMap: map(address, map(address, uint256))
-# NOTE: Mappings are only allowed as state variables
-# NOTE: Mappings are not iterable; can only be accessed
-
-# To delete (reset the mapping's value to default at a key)
-clear(balances["John"])
-clear(balances); # sets all elements to 0
-
-# Unlike other languages, CANNOT iterate through all elements in
-# mapping, without knowing source keys - can build data structure
-# on top to do this
-
-# Structs
-struct Struct:
- owner: address
- _balance: uint256 # balance is a reserved keyword, is a member for addresses
-
-exampleStruct: Struct
-
-@public
-def foo() -> uint256:
- self.exampleStruct = Struct({owner: msg.sender, _balance: 5})
- self.exampleStruct._balance = 10
- self.exampleStruct._balance = 5 # set to new value
- clear(self.exampleStruct._balance)
- clear(self.exampleStruct)
- return self.exampleStruct._balance
-
-
-# Data locations: Memory vs. storage vs. calldata - all complex types (arrays,
-# structs) have a data location
-# 'memory' does not persist, 'storage' does
-# Default is 'storage' for local and state variables; 'memory' for func params
-# stack holds small local variables
-
-# for most types, can explicitly set which data location to use
-
-
-# ---
-
-
-# 3. SIMPLE OPERATORS
-# Comparisons, bit operators and arithmetic operators are provided
-# exponentiation: **
-# modulo: %
-# maximum: max(x, y)
-# AND: bitwise_and(x, y)
-# bitwise shift: shift(x, _shift)
-# where x,y are uint256
-# _shift is int128
-
-# 4. GLOBAL VARIABLES OF NOTE
-# ** self **
-self # address of contract
-# often used at end of contract life to transfer remaining balance to party:
-self.balance # balance of current contract
-self.someFunction() # calls func externally via call, not via internal jump
-
-# ** msg - Current message received by the contract **
-# Ethereum programmers take NOTE: this `msg` object is smaller than elsewhere
-msg.sender # address of sender
-msg.value # amount of ether provided to this contract in wei, the function should be marked `@payable`
-msg.gas # remaining gas
-
-# ** tx - This transaction **
-# Ethereum programmers take NOTE: this `tx` object is smaller than elsewhere
-tx.origin # address of sender of the transaction
-
-# ** block - Information about current block **
-block.timestamp # time at current block (uses Unix time)
-# Note that `block.timestamp` can be manipulated by miners, so be careful
-block.number # current block number
-block.difficulty # current block difficulty
-
-# ** storage - Persistent storage hash **
-storage['abc'] = 'def'; # maps 256 bit words to 256 bit words
-
-
-# ---
-
-
-# 5. FUNCTIONS AND MORE
-
-# A. FUNCTIONS
-# Simple function
-function increment(uint x) returns (uint) {
- x += 1;
- return x;
-}
-
-# Functions can return many arguments
-@public
-@constant
-def increment(x: uint256, y: uint256) -> (uint256, uint256):
- x += 1
- y += 1
- return (x, y)
-
-# Call previous function
-@public
-@constant
-def willCall() -> (uint256, uint256):
- return self.increment(1,1)
-
-# One should never have to call a function / hold any logic outside
-# outside the scope of a function in Vyper
-
-# '@constant'
-# indicates that function does not/cannot change persistent vars
-# Constant function execute locally, not on blockchain
-y: uint256
-@public
-@constant
-def increment(x: uint256) -> uint256:
- x += 1
- y += 1 # this line would fail
- # y is a state variable => can't be changed in a constant function
-
-
-# 'Function Decorators'
-# Used like python decorators but are REQUIRED by Vyper
-# @public - visible externally and internally (default for function)
-# @private - only visible in the current contract
-# @constant - doesn't change state
-# @payable - receive ether/ETH
-# @nonrentant(<unique_key>) - Function can only be called once, both externally
-# and internally. Used to prevent reentrancy attacks
-
-# Functions hare not hoisted
-# Functions cannot be assigned to a variable
-# Functions cannot be recursive
-
-# All functions that receive ether must be marked 'payable'
-@public
-@payable
-def depositEther():
- self.balances[msg.sender] += msg.value
-
-
-# B. EVENTS
-# Events are notify external parties; easy to search and
-# access events from outside blockchain (with lightweight clients)
-# typically declare after contract parameters
-
-# Declare
-LogSent: event({_from: indexed(address), address: indexed(_to), _amount: uint256})
-# Call
-log.LogSent(from, to, amount)
-
-/**
-For an external party (a contract or external entity), to watch using
-the Web3 Javascript library:
-
-# The following is Javascript code, not Vyper code
-Coin.LogSent().watch({}, '', function(error, result) {
- if (!error) {
- console.log("Coin transfer: " + result.args.amount +
- " coins were sent from " + result.args.from +
- " to " + result.args.to + ".");
- console.log("Balances now:\n" +
- "Sender: " + Coin.balances.call(result.args.from) +
- "Receiver: " + Coin.balances.call(result.args.to));
- }
-}
-**/
-
-# Common paradigm for one contract to depend on another (e.g., a
-# contract that depends on current exchange rate provided by another)
-
-
-# ---
-
-
-# 6. BRANCHING AND LOOPS
-
-# All basic logic blocks from Python work - including if/elif/else, for,
-# while, break, continue, return - but no switch
-
-# Syntax same as Python, but no type conversion from non-boolean
-# to boolean (comparison operators must be used to get the boolean val)
-
-# REMEMBER: Vyper does not allow resursive calls or infinite loops
-
-
-# ---
-
-
-# 7. OBJECTS/CONTRACTS
-# REMEMBER: Vyper does not allow for inheritance or imports
-
-# A. CALLING EXTERNAL CONTRACTS
-# You must define an interface to an external contract in the current contract
-
-contract InfoFeed():
- def getInfo() -> uint256: constant
-
-info: uint256
-
-@public
-def __init__(_source: address):
- self.info = InfoFeed(_source).getInfo()
-
-
-# B. ERC20 BUILT-IN
-# Using the `ERC20` keyword implies that the contract at the address
-# follows the ERC20 token standard, allowing you to safely call
-# functions like `transfer()`, etc.
-
-tokenAddress: address(ERC20)
-
-@public
-def transferIt(_to: address, _amt: uint256(wei)):
- self.tokenAddress.transfer(_to, _amt)
-
-
-# C. FOLLOWING AN INTERFACE
-# Vyper is experimenting with using the following syntax at the top of
-# a `.vy` file to specify what interfaces are followed by the contract
-# This allows interfaces to be better organized, registered, and recognized
-
-import interfaces.some_interface as SomeInterface
-implements: SomeInterface
-# <rest of contract>
-
-
-# ---
-
-
-# 8. OTHER KEYWORDS
-
-# A. selfdestruct()
-# selfdestruct current contract, sending funds to address (often creator)
-selfdestruct(SOME_ADDRESS);
-
-# removes storage/code from current/future blocks
-# helps thin clients, but previous data persists in blockchain
-
-# Common pattern, lets owner end the contract and receive remaining funds
-@public
-def endItAll() {
- assert msg.sender == self.creator # Only let the contract creator do this
- selfdestruct(self.creator) # Makes contract inactive, returns funds
-
-# May want to deactivate contract manually, rather than selfdestruct
-# (ether sent to selfdestructed contract is lost)
-
-
-# B. sha3()
-# Encrypts strings and other data
-# Very important on the blockchain
-# Takes 1 argument, `concat()` can be called beforehand
-# All strings passed are concatenated before hash action
-sha3(concat("ab", "cd")) # returns bytes32
-
-
-# ---
-
-
-# 9. CONTRACT DESIGN NOTES
-
-# A. Obfuscation
-# All variables are publicly viewable on blockchain, so anything
-# that is private needs to be obfuscated (e.g., hashed w/secret)
-# Oftentimes, a "commit-reveal" scheme is employed
-
-# Step 1. Commit
-# Place a commitment by sending output of `sha3()`
-sha3("a secret"); # bytes32 commit
-sha3(concat("secret", "other secret", "salt")); # commit multiple things
-# The `sha3()` calculation should occur off-chain, only the bytes32
-# output should be inputted into some `commit()` function
-commits: map(address, bytes32)
-@public
-def commit(commitment: bytes32):
- self.commits[msg.sender] = commitment
-
-# Step 2. Reveal
-# Send your previously committed data so the contract can check
-# if your commitment was honest
-@public
-def reveal(_secret: string[100], _salt: string[100]) -> bool:
- return sha3(concat(_secret, _salt)) == self.commits[msg.sender]
-
-
-# B. Storage optimization
-# Writing to blockchain can be expensive, as data stored forever; encourages
-# smart ways to use memory (eventually, compilation will be better, but for now
-# benefits to planning data structures - and storing min amount in blockchain)
-
-# Cost can often be high for items like multidimensional arrays
-# (cost is for storing data - not declaring unfilled variables)
-
-
-# C. Data access in blockchain
-# Cannot restrict human or computer from reading contents of
-# transaction or transaction's state
-
-# While 'private' prevents other *contracts* from reading data
-# directly - any other party can still read data in blockchain
-
-# All data to start of time is stored in blockchain, so
-# anyone can observe all previous data and changes
-
-
-# D. Cron Job
-# Contracts must be manually called to handle time-based scheduling;
-# can create external code to regularly ping or provide incentives
-# (ether) for others to ping
-
-
-# E. Observer Pattern
-# An Observer Pattern lets you register as a subscriber and
-# register a function which is called by the oracle (note, the oracle
-# pays for this action to be run)
-# Some similarities to subscription in Pub/sub
-
-# This is an abstract contract, both client and server classes import,
-# the client should implement
-
-### **** START EXAMPLE **** ###
-
-contract SomeOracleCallback():
- def oracleCallback(_value: uint256, _time: timestamp, _info: bytes32): modifying
-
-MAX_SUBS: constant(uint256) = 100
-numSubs: public(uint256) # number of subscribers
-subs: map(uint256, address) # enumerates subscribers
-
-@public
-def addSub(_sub: address) -> uint256:
- """
- @notice Add subscriber
- @param _sub Address to add
- @return Id of newly added subscriber
- """
- self.subs[self.numSubs] = _sub
- self.numSubs += 1
- return self.numSubs - 1
-
-@private
-def notify(_value: uint256, _time: timestamp, _info: bytes32) -> bool:
- """
- @notice Notify all subscribers
- @dev Check `numSubs` first; Watch out for gas costs!
- @param _value whatever
- @param _time what have you
- @param _info what else
- @return True upon successful completion
- """
- j: uint256
- for i in range(MAX_SUBS):
- j = convert(i, uint256) # `i` is int128 by default
- if j == self.numSubs:
- return True
- SomeOracleCallback(self.subs[j]).oracleCallback(_value, _time, _info)
-
-@public
-def doSomething():
- """
- @notice Do something and notify subscribers
- """
- # ...something...
- whatever: uint256 = 6
- what_have_you: timestamp
- what_else: bytes32 = sha3("6")
- self.notify(whatever, what_have_you, what_else)
-
-# Now, your client contract can addSubscriber by importing SomeOracleCallback
-# and registering with Some Oracle
-
-### **** END EXAMPLE **** ###
-
-
-# ---
-
-
-# 10. SECURITY
-# Bugs can be disastrous in Ethereum contracts - and even popular patterns in
-# Vyper may be found to be antipatterns
-
-# See security links at the end of this doc
-
-
-# ---
-
-
-# 11. STYLE NOTES
-# Based on Python's PEP8 style guide
-# Full Style guide: http:#solidity.readthedocs.io/en/develop/style-guide.html
-
-# Quick summary:
-# 4 spaces for indentation
-# Two lines separate contract declarations (and other top level declarations)
-# Avoid extraneous spaces in parentheses
-# Can omit curly braces for one line statement (if, for, etc)
-# else should be placed on own line
-
-# Specific to Vyper:
-# arguments: snake_case
-# events, interfaces, structs: PascalCase
-# public functions: camelCase
-# private functions: _prefaceWithUnderscore
-
-
-# ---
-
-
-# 12. NATSPEC COMMENTS
-# used for documentation, commenting, and external UIs
-
-# Contract natspec - always above contract definition
-# @title Contract title
-# @author Author name
-
-# Function natspec
-# Should include in docstring of functions in typical Pythonic fashion
-# @notice Information about what function does; shown when function to execute
-# @dev Function documentation for developer
-
-# Function parameter/return value natspec
-# @param someParam Some description of what the param does
-# @return Description of the return value
-```
-
-## Additional resources
-- [Installation](https://vyper.readthedocs.io/en/latest/installing-vyper.html)
-- [Vyper Docs](https://media.readthedocs.org/pdf/vyper/latest/vyper.pdf)
-- [Vyper GitHub (under active dev)](https://github.com/ethereum/vyper)
-- [Tools and Resources](https://github.com/ethereum/vyper/wiki/Vyper-tools-and-resources)
-- [Online Compiler](https://vyper.online/)
-
-## Sample contracts
-- [Uniswap](https://github.com/Uniswap/contracts-vyper)
-- [Generalized Governance](https://github.com/kpeluso/gdg)
-- [Dynamic Arrays](https://github.com/kpeluso/vyper-dynamic-array)
-
-## Security
-Vyper is secure by design, but it may be helpful to understand what Vyper is
-protecting you from.
-- [Thinking About Smart Contract Security](https:#blog.ethereum.org/2016/06/19/thinking-smart-contract-security/)
-- [Smart Contract Security](https:#blog.ethereum.org/2016/06/10/smart-contract-security/)
-- [Hacking Distributed Blog](http:#hackingdistributed.com/)
-
-## Style
-- [Vyper Style Guide WIP](https://github.com/ethereum/vyper/issues/905)
- - Heavily derived from [Solidity's style guide](http:#solidity.readthedocs.io/en/latest/style-guide.html) ...
- - ... which, in turn, is heavily derived from Python's [PEP 8](https:#www.python.org/dev/peps/pep-0008/) style guide.
-
-## Editors
-- [Vyper for VS Code (alpha)](https://github.com/p-/vscode-vyper)
-
-## Future To Dos
-- Update to current Vyper release
-- List of common design patterns
-
-*Feel free to send a pull request with any edits - or email* `pelusoken -/at-/ gmail`
-