### BCDV 1013 - Advanced Smart Contract #### Vyper
Dhruvin Parikh, March 2021
### Topics * Value types and reference types * EVM compatible languages * Benefits & Drawbacks of languages
### Vyper language description * Types * Environment variables & constant * Event logging * Built-in functions * statements and control structures
### Types in Vyper * Value types * Reference types * Initial values
### Value types * Boolean : `bool` * Signed integer (128bit) : `int128` * Unsigned integer (256bit) : `uint256` * Decimals : `decimal` * Address : `address` * 32-bit-wide Byte Array : `bytes32` * Byte Arrays : `Bytes` * Strings : `string`
### Value type : `bool` ``` a: bool = True ``` * Stores only `True` or `False` * Operators * Logical negation : `not x` * Logical conjunction : `x and y` * Logical disjunction : `x or y` * Equality : `x == y` * Inequality : `x != y`
### Value type : `int128` ``` total_paid: int128 ``` * Stores values between -2
127
and (2
127
- 1) * Operators * Comparision : `<`,`<=`,`==`,`!=`, `>=`, `>` * Arithmetic : `+`,`-`,negation(`-x`),`*`,`/`,`**`,`%`
### Value type : `uint256` ``` total_paid: uint256 ``` * Stores values between 0 and (2
256
- 1) * Operators * Comparision : `<`,`<=`,`==`,`!=`, `>=`, `>` * Arithmetic : `+`,`-`,`*`,`/`,`**`,`%`
### Value type : `decimal` ``` value2: decimal = 2.0 ``` * 10 decimal precision between -2
127
and (2
127
- 1) * decimal point is must * Operators * Comparision : `<`,`<=`,`==`,`!=`, `>=`, `>` * Arithmetic : `+`,`-`,negation(`-x`),`*`,`/`,`**`,`%`
### Value type : `address` ``` owner:address ``` * 20 bytes or 160 bits Ethereum address. * `0x` prefixed hex literal * Members * `balance:uint256` - balance of address * `codehash:bytes32` - keccak256(code-at-address) * `codesize:uint256` - deployed contract code size at address * `is_contract:bool` - is contract deployed?
### Value type : `bytes32` ``` # Declaration hash: bytes32 # Assignment self.hash = _hash ``` * Like byte arrays except this is 32-bit-wide * Operators * `keccak256(x)` * `concat(x,...)` - Concatenate multiple inputs * `slice(x, start=_start, len=_len)` - Returns a slice of `_len` starting at `_start`
### Value type : `Bytes` ``` # bytes string assignment bytes_string: Bytes[100] = b"\x01" # hexadecimal assignment hex_bytes: Bytes[100] = 0x01 # binary assignment binary_bytes: Bytes[100] = 0b00000001 ``` * fixed size byte array * `Bytes[maxLen]` - `maxLen` is max # of bytes * annotated as bytes at ABI level
### Value type : `string` ``` # Assignment example_str: String[100] = "Test String" ``` * Fixed-size strings can hold strings with equal or fewer characters than the maximum length of the string. * Fixed-size bytes array is annotated as string at ABI level.
### Reference Types * Fixed-size Lists : e.g. `exampleList: int128[3]` * Structs : `struct` * Mappings : `HashMap[_KeyType, _ValueType]`
### Reference Type : Fixed-size Lists ``` # Defining a list exampleList: int128[3] # Setting values exampleList = [10, 11, 12] exampleList[2] = 42 # Returning a value return exampleList[0] ``` * Syntax - `_name: _ValueType[_Integer]` * Finite number of elements of same type.
### Reference Type : `struct` ``` # Definition struct MyStruct: value1: int128 value2: decimal # Declaration anyStruct : MyStruct # Constructing anyStruct = MyStruct({value: 1, value2 : 2.0}) ``` * custom defined type to group several variables * Structs can be insinde mapping or array * mapping cannot be inside struct
### Reference Type : `HashMap` ``` # Defining a mapping exampleMapping: HashMap[int128, decimal] # Accessing a value exampleMapping[0] = 10.1 ``` * Syntax - `HashMap[_KeyType, _ValueType]` * `_KeyType` - base or bytes type * `_ValueType` - any type including mapping * keccak256 of key is stored inside mapping
### Default Values * `address` : `0x0000000...00000000` (20 bytes) * `bool` : `False` * `bytes32` : `0x0000000...00000000` (32 bytes) * `decimal` : `0.0` * `int128` : `0` * `uint256` : `0`
### Type conversions * Explicitly use Built-in `convert(a: atype, btype)` function * Read more in the
vyper docs
### Variable definition ``` # In Vyper varName: accessControl ( type ) voter: public (address) # In Solidity type accessControl varName address public voter; ```
### Public variables ``` data: public(int128) ``` * Storage variables can be marked as `public` during declaration * Default getter function for public state variable
### Scope and assignment * For storage variables (declared in the module scope), an initial value cannot be set * For memory variables (declared within a function), an initial value must be set * For calldata variables (function input arguments), a default value may be given
### Function visibility * `@external` - called by EOA * `@internal` - use `self` to call internal functions * internal functions does not have access to `msg.value` and `msg.sender`
### Mutability * `@pure` : no state read/write * `@view` : only state read * Nonpayable - state read/write, cannot receive Ether * `@payable` - state read/write, can receive Ether
### Constructor Declaration ``` # Vyper @public def __init__(): # Solidity constructor () { … } ```
### `__default__` ``` event Payment: amount: int128 sender: indexed(address) @external @payable def __default__(): log Payment(msg.value, msg.sender) ``` * Similar to `fallback` in solidity
### `@nonreentrant("lock")` ``` @external @nonreentrant("lock") def make_a_call(_addr: address): # this function is protected from re-entrancy # ... ``` * It places a lock on a function, and all functions with the same key_value. * An attempt by an external contract to call back into any of these functions causes the transaction to revert.
### Function Declaration ``` # Vyper @public def functionName(_varName:type): # Solidity function functionName(type varName) public { … } ```
### Payable Function Declaration ``` # Vyper @public @payable def functionName(_varName:type): # Solidity function functionName(type varName) public payable { … } ```
### Error handling ``` # Vyper assert(some-boolean-operation) # Solidity require(some-boolean-operation,"reason-string"); ```
### Error handling ``` # Vyper assert x > 5, "value to low" raise "something vent wrong" # Solidity require(some-boolean-operation,"reason-string"); revert("reason string") ```
### `self` ``` state_var: uint256 @internal def _times_two(amount: uint256) -> uint256: return amount * 2 @external def set_var(amount: uint256) -> uint256: return self._times_two(amount) @external @view def get_var() -> uint256: return self.state_var ``` * `self` used to access state variables & functions within the contract.
### Block and Transaction Properties * Block * `block.coinbase`, `block.difficulty`, `block.number` * `block.prevhash` = `blockhash(block.number - 1)` * `block.timestamp` * `chain.id` * calldata * `msg.gas`, `msg.sender`, `msg.value`, `tx.origin`
### Built In Constants * `ZERO_ADDRESS:address` - `0x000...0000000` * `EMPTY_BYTES32:bytes32` 0x0000...00000000 * `MAX_INT128:int128` - `2**127 - 1` * `MIN_INT128:int128` - `-2**127` * `MAX_DECIMAL:decimal`- `(2**127 - 1)` * `MIN_DECIMAL:decimal`- `(-2**127)` * `MAX_UINT256:uint256` - `2**256 - 1`
### Custom constants ``` TOTAL_SUPPLY: constant(uint256) = 10000000 total_supply: public(uint256) @external def __init__(): self.total_supply = TOTAL_SUPPLY ```
### Event Logging ``` # Vyper event MyEvent: amount: int128 sender: indexed(address) log MyEvent(msg.value, msg.sender) # Solidity event MyEvent(int128 amount, address indexed sender); emit MyEvent(msg.value, msg.sender); ```
### Interfaces ``` # Definition interface FooBar: def calculate() -> uint256: view def test1(): nonpayable # Import from foo import FooBar # Usage @external def test(some_address: address): FooBar(some_address).calculate() ```
### Brownie * IDE for deploying, interacting, debugging and testing vyper contracts * Detailed installation
instructions
. ``` # Installation $ pip install eth-brownie # Initialize $ brownie init # Compile $ brownie compile ```
### Brownie Project * `contracts/`: Contract sources * `interfaces/`: Interface sources * `scripts/`: Scripts for deployment and interaction * `tests/`: Scripts for testing the project * `brownie-config.yaml`: Configuration file for the project * `build/`: Project data, such as compiler artifacts and unit test results * `reports/`: JSON report files for use in the GUI
### Vyper feature omission *
Modifiers
* Class inheritance * Inline Assembly * Function/operator overloading *
Recursive
calling or
infinite
length loops * Binary fixed points
### Vyper key features * Bound and overflow checking on
array accesses
and on an
arithmetic level
*
Signed integers
and decimals
fixed point
numbers * Upper bound for
gas consumption
* Strong typing * Small and
understandable
compiler code
### Available languages for EVM * Solidity * Vyper * LLL * Flint * Yul * eWASM
### Yul * Intermediate language compiling to different EVM * Supports * `switch`, function, `block`, `var`, literal, loop, `if`, expression, variable *
Example
### LLL * Assembly-like code with keywords * Manipulation of data and bytes themselves *
Example
Exercise
Follow the instructions on the
readme
file of vyper
References
Vyper docs
eth-brownie docs
## End