|
| 1 | +# 1. Introduction to Solidity - The Basics |
| 2 | + |
| 3 | +[CryptoZombies](https://cryptozombies.io/) is a game-based tutorial that teaches you all things technical about blockchains and also, how to make smart contracts in Solidity. You are suggested to play the game and use this tutorial as a reference material. |
| 4 | + |
| 5 | +## 1. Data Types |
| 6 | +#### 1.1 Value Types |
| 7 | +Value types are the data that is passed by value. |
| 8 | +##### 1.1.1 Bool |
| 9 | + |
| 10 | +Bool type only has 2 possible values, `true` or `false`. They allow the following operators: |
| 11 | + |
| 12 | +* `!`(logical negation) |
| 13 | +* `&&`(logical and) |
| 14 | +* `||`(logical or) |
| 15 | +* `==`(equality) |
| 16 | +* `!=`(inequality) |
| 17 | + |
| 18 | +##### 1.1.2 Integers |
| 19 | +Size of integers ranges from int8/uint8 to int256/uint256, in steps of 8. They allow the following operators: |
| 20 | + |
| 21 | +* Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to bool) |
| 22 | +* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~`(bitwise negation) |
| 23 | +* Shift operators: `<<`(left shift), `>>`(right shift) |
| 24 | +* Arithmetic operators: `+`, `-`, unary`-`, `*`, `/`, `%`(modulo), `**`(exponentation) |
| 25 | + |
| 26 | +##### 1.1.3 Address |
| 27 | +There are two main types of this class: |
| 28 | + |
| 29 | +* **Address**: Holds a 20 byte value (size of an Ethereum address). |
| 30 | +* **Address Payable**: Same as address, but with the additional members transfer and send. |
| 31 | + |
| 32 | +They allow the following operators: `<=`, `<`, `==`, `!=`, `>=`, `>` |
| 33 | + |
| 34 | +The transfer function fails if the balance of the current contract is not large enough or if the Ether transfer is rejected by the receiving account. The transfer function reverts on failure. |
| 35 | + |
| 36 | +Send is the low-level counterpart of transfer. They are both [members of addresses](https://solidity.readthedocs.io/en/v0.7.0/types.html?highlight=send#members-of-addresses). If the execution fails, the current contract will not stop with an exception, but `send` will retutn `false`. |
| 37 | + |
| 38 | +Example of Transfer & Send |
| 39 | + |
| 40 | +```solidity |
| 41 | + address payable = address(0x123); |
| 42 | + address myAddress = address(this); |
| 43 | + if(x.balance < 10 && myAddress.balance >= 10) |
| 44 | + x.transfer(10); |
| 45 | +``` |
| 46 | + |
| 47 | +##### 1.1.4 Contract Types |
| 48 | + |
| 49 | +* Contracts do not support any operators. |
| 50 | +* The members of contract types are the external functions of the contract including public state variables. |
| 51 | +* For a contract C, type(C) returns type information about the contract. |
| 52 | + |
| 53 | +##### 1.1.5 String Literals |
| 54 | + |
| 55 | +```solidity |
| 56 | +bytes32 a = "stringliteral" |
| 57 | +string b = "stringliteral" |
| 58 | +a == b |
| 59 | +Hex "DEADBEEF" |
| 60 | +"\n\"\'\\abc\ |
| 61 | +def" |
| 62 | +``` |
| 63 | +##### 1.1.6 Enum |
| 64 | + |
| 65 | +```solidity |
| 66 | +pragma solidity>=0.4.16<0.6.0; |
| 67 | +
|
| 68 | +contract test{ |
| 69 | + enum ActionChoices{ GoLeft, GoRight, GoStraight, SitStill } |
| 70 | + ActionChoices choice; |
| 71 | + ActionChoices constant defaultChoice = ActionChoices.GoStraight; |
| 72 | + |
| 73 | + function setGoStraight() public { |
| 74 | + choice = ActionChoices.GoStraight; |
| 75 | + } |
| 76 | + |
| 77 | + function getChoice() public view returns (ActionChoices) { |
| 78 | + return choice; |
| 79 | + } |
| 80 | + |
| 81 | + function getDefaultChoice() public pure returns (uint) { |
| 82 | + return unit(defaultChoice); |
| 83 | + } |
| 84 | +} |
| 85 | +``` |
| 86 | +In the above example, since enum types are not part of ABI, the signature of "getChoice" will be automatically changed to "getChoice() returns (uint8)" for all matters external to Solidity. The integer type used is just large enough to hold all enum values. If you have more than 256 values, "uint16" will be used. |
| 87 | + |
| 88 | +#### 1.2 Reference Types and Data Structures |
| 89 | +Reference types are the data that is passed by reference. They are either Arrays, Structs or Data Locations. |
| 90 | +##### 1.2.1 Arrays |
| 91 | + |
| 92 | +```solidity |
| 93 | +// Arrays |
| 94 | +bytes32[5] nicknames; // static array |
| 95 | +bytes32[] names; // dynamic array |
| 96 | +uint newLength = names.push(); // adding returns new length of the array |
| 97 | +
|
| 98 | +// Length |
| 99 | +names.length; // get length |
| 100 | +names.length = 1; // lengths can be set (for dynamic arrays in storage only) |
| 101 | +
|
| 102 | +// multidimensional array |
| 103 | +uint x[][5]; // arr with 5 dynamic array elements (opp order of most languages) |
| 104 | +``` |
| 105 | +##### 1.2.2 Structs |
| 106 | + |
| 107 | +```solidity |
| 108 | +struct Bank { |
| 109 | + address owner; |
| 110 | + uint balance; |
| 111 | +} |
| 112 | +Bank b = Bank({ |
| 113 | + owner: msg.sender, |
| 114 | + balance: 5 |
| 115 | +}); |
| 116 | +// or |
| 117 | +Bank c = Bank(msg.sender, 5); |
| 118 | +
|
| 119 | +c.balance = 4; // Set to new value |
| 120 | +delete b; // Sets to initial value, set all variables in struct to 0, except mappings |
| 121 | +``` |
| 122 | +##### 1.2.3 [Data Locations](https://solidity.readthedocs.io/en/v0.7.0/types.html?highlight=data%20locations#data-location) |
| 123 | + |
| 124 | +* memory |
| 125 | +* storage |
| 126 | +* calldata |
| 127 | +##### 1.2.4 Mappings |
| 128 | + |
| 129 | +```solidity |
| 130 | +// Dictionaries (any type to any other type) |
| 131 | +mapping (string=>uint) public balances; |
| 132 | +balances["charles"] = 1; |
| 133 | +``` |
| 134 | +Result of `balances["charles"]` is 0, since all non-set key values return zeroes. |
| 135 | + |
| 136 | +``` |
| 137 | +// "public" allows following from another contract |
| 138 | +contractName.balances("charles"); |
| 139 | +// "public" created a getter (but not setter) like the following: |
| 140 | +function balances(string _account) returns (uint balance) { |
| 141 | + return balances[_account]; |
| 142 | +} |
| 143 | +``` |
| 144 | + |
| 145 | +```solidity |
| 146 | +// Nested mappings |
| 147 | +mapping(address => mapping (address => uint)) public custodians; |
| 148 | +
|
| 149 | +// To delete |
| 150 | +delete balances["John"]; |
| 151 | +delete balances; // Set all elements to 0 |
| 152 | +``` |
| 153 | +## 2. [Functions](https://solidity.readthedocs.io/en/v0.7.0/structure-of-a-contract.html?highlight=functions#functions) |
| 154 | +#### 2.1 Function Basics |
| 155 | + |
| 156 | +* function name |
| 157 | +* argType1 arg1, ... |
| 158 | +* access classifier |
| 159 | + * public - all can access |
| 160 | + * external - cannot be accessed internally, only externally |
| 161 | + * internal - only this contract and contracts derived from it can access |
| 162 | + * private - can be accessed only from this contract |
| 163 | +* returnType(optional return var name) |
| 164 | + |
| 165 | +```solidity |
| 166 | +function withdraw(uint withdrawAmount) public returns (uint remainingBal) { |
| 167 | + require(withdrawAmount <= balances[msg.sender]); |
| 168 | + |
| 169 | + balances[msg.sender] -= withdrawAmount; |
| 170 | + |
| 171 | + msg.sender.transfer(withdrawAmount); |
| 172 | + |
| 173 | + return balances[msg.sender]; |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +**IMPORTANT**: Access classifiers determine who can USE your functions, but everyone can see them, since |
| 178 | + |
| 179 | +#### 2.2 [Payable Function](https://solidity.readthedocs.io/en/v0.7.0/060-breaking-changes.html?highlight=payable%20function#new-features) |
| 180 | +Only functions marked as payable can receive Ether. Non-payable functions with Ether values will be routed to default function. |
| 181 | + |
| 182 | +```solidity |
| 183 | +function deposit() public payable returns (uint) { |
| 184 | + // Use 'require' to test user inputs, 'assert' for internal invariants |
| 185 | + // Here we are making sure that there isn't an overflow issue |
| 186 | + require((balances[msg.sender] + msg.value) >= balances[msg.sender]); |
| 187 | + |
| 188 | + balances[msg.sender] += msg.value; |
| 189 | + |
| 190 | + LogDepositMade(msg.sender, msg.value); // fire event |
| 191 | + |
| 192 | + return balances[msg.sender]; |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +#### 2.3 [Fallback Function](https://solidity.readthedocs.io/en/v0.7.0/contracts.html?highlight=fallback#fallback-function) |
| 197 | +Intuitively, this can be thought of as the default behavior when the contract does not recognize the command. |
| 198 | + |
| 199 | +* Invoked when a function is called which does not match any other contract function |
| 200 | +* Only one per contract |
| 201 | +* No arguments, returns nothing |
| 202 | +* Typically payable: enables contract to receive Ether sent directly to it |
| 203 | + |
| 204 | +```solidity |
| 205 | +function() external payable { |
| 206 | + require(msg.value >= prize || msg.sender == owner); |
| 207 | + king.transfer(msg.value); |
| 208 | + king = msg.sender; |
| 209 | + prize = msg.value; |
| 210 | +} |
| 211 | +``` |
| 212 | + |
| 213 | + |
| 214 | +#### 2.4 [Constructors](https://solidity.readthedocs.io/en/v0.7.0/structure-of-a-contract.html?highlight=functions#functions) |
| 215 | + |
| 216 | +* Create an instance of the contract with the given arguments |
| 217 | +* Only one allowed, cannot be overloaded |
| 218 | +* 2 Implementations: |
| 219 | + * function [contractName] (arg1, arg2 ...) |
| 220 | + * constructor (arg1, arg2 ...) |
| 221 | + |
| 222 | +```solidity |
| 223 | +contract SimpleBank { // contract name should be CapWords |
| 224 | + // |
| 225 | + mapping (address => uint) private balances; |
| 226 | +} |
| 227 | +``` |
| 228 | + |
| 229 | +## 3. Global Variables |
| 230 | +#### 3.1 Currency Units |
| 231 | + |
| 232 | +* Currency units are tracked as **uints** |
| 233 | +* A number can take a postfix of **wei**, **finney**, **szabo** or **ether** to convert between denominations of Ether. |
| 234 | + |
| 235 | +```solidity |
| 236 | +// Currency Units |
| 237 | +// Currency is defined using wei, the smallest unit of Ether |
| 238 | +uint minAmunt = 1 wei; |
| 239 | +uint a = 1 ether; // 1 ether == 10**18 wei |
| 240 | +uint b = 1 finney; // 1 ether == 1000 finney |
| 241 | +
|
| 242 | +// Currency uints without a postfix are assumed to be wei |
| 243 | +require(a == 10**18 && b == 10**15); // true |
| 244 | +``` |
| 245 | +#### 3.2 Time |
| 246 | + |
| 247 | +* Solidity tracks time as a Unix TimeStamp, |
| 248 | +* A number can take a postfix of **seconds**, **minutes**, **hours**, etc. to convert between denominations of Ether. |
| 249 | + |
| 250 | +``` |
| 251 | +// Time units |
| 252 | +1 == 1 seconds |
| 253 | +1 minutes == 60 seconds |
| 254 | +
|
| 255 | +now; // returns current Unix TimeStamp |
| 256 | +// Note that this can be manipulated by miners, so use carefully |
| 257 | +``` |
| 258 | +#### 3.3 this |
| 259 | + |
| 260 | +```solidity |
| 261 | +this; // address of contract |
| 262 | +// often used at end of contract life to transfer remaining balance to party |
| 263 | +this.balance; |
| 264 | +this.someFunction(); // calls func externally via call, not via internal jump |
| 265 | +``` |
| 266 | + |
| 267 | +#### 3.4 [MSG, TX](https://solidity.readthedocs.io/en/v0.7.0/units-and-global-variables.html?highlight=msg#block-and-transaction-properties) |
| 268 | + |
| 269 | +```solidity |
| 270 | +// msg - Current message received by the contract |
| 271 | +msg.sender; // address of sender |
| 272 | +msg.value; // amount of ether provided to this contract in wei, function should be marked "payable" |
| 273 | +msg.data; // bytes, complete call data |
| 274 | +msg.gas; // remaining gas |
| 275 | +
|
| 276 | +// tx - This transaction |
| 277 | +tx.origin; // address of sender of the transaction |
| 278 | +tx.gasprice; // gas price of the transaction |
| 279 | +``` |
| 280 | + |
| 281 | +Differnece between `msg.sender` and `tx.origin`: |
| 282 | + |
| 283 | +In this case, for contract B, `msg.sender: address A` and `tx.origin: address A`; |
| 284 | +for contract C, `msg.sender: address B` and `tx.origin: address A`. |
| 285 | + |
| 286 | + |
| 287 | +## 4. External Contracts |
| 288 | +Contracts in Solidity is similar to the concept of classes in object-oriented languages. |
| 289 | + |
| 290 | +```solidity |
| 291 | +contract InfoFeed { |
| 292 | + function info() returns (uint) { |
| 293 | + return 42; |
| 294 | + } |
| 295 | +} |
| 296 | +``` |
| 297 | + |
| 298 | +In another file, we will do the following: |
| 299 | + |
| 300 | +```solidity |
| 301 | +import "./"; |
| 302 | +
|
| 303 | +contract Consumer { |
| 304 | +
|
| 305 | + InfoFeed feed; // points to contract on blockchain |
| 306 | + |
| 307 | + // Set feed to new instance of contract |
| 308 | + function createNewFeed(){ |
| 309 | + // new instance created, constructor call |
| 310 | + feed = new InfoFeed(); |
| 311 | + } |
| 312 | + |
| 313 | + // Set feed to existing contract instance |
| 314 | + function setFeed(address addr) { |
| 315 | + feed = InfoFeed(addr); |
| 316 | + } |
| 317 | + |
| 318 | + function callFeed() { |
| 319 | + feed.info(); |
| 320 | + } |
| 321 | +} |
| 322 | +``` |
| 323 | + |
| 324 | +## 5. [Modifiers](https://solidity.readthedocs.io/en/v0.7.0/cheatsheet.html?highlight=modifiers#modifiers) |
| 325 | +Modifiers validate inputs to functions such as minimal balance or user auth. |
| 326 | + |
| 327 | +For example, for a function that transfers balances from one address to another: |
| 328 | +```solidity |
| 329 | +function transferBalance(address from, address to) public onlyOwner { |
| 330 | + balances[to] += balances[from]; |
| 331 | + balances[from] = 0; |
| 332 | +} |
| 333 | +
|
| 334 | +// '_' (underscore) often included as last line in body, and indicates |
| 335 | +// the function being called should be placed here |
| 336 | +modifier onlyOwner() { |
| 337 | + require(msg.sender == owner); |
| 338 | + _; |
| 339 | +} |
| 340 | +
|
| 341 | +modifier onlyOwner() { |
| 342 | + require(now >= _time); |
| 343 | + _; |
| 344 | +} |
| 345 | +``` |
| 346 | +#### References |
| 347 | + |
| 348 | +1. [Blockchain@Berkeley Slides](https://drive.google.com/file/d/1ceFHDQyZB7WUP-EMnUbki3Ooir1ULBz0/view) |
| 349 | + |
| 350 | +2. [Blockchain@NTU Slides](https://docs.google.com/presentation/d/10f86TBXPca66OE_xw2f2W9ZOVLkp8KR8iLkw7xdQElI/edit?usp=sharing) |
| 351 | + |
| 352 | +[Ethernaut](https://ethernaut.openzeppelin.com/) is a CTF-style game focused on smart contract development and security. |
| 353 | + |
| 354 | +For any grammar details, please refer to the [Solidity documentation](https://solidity.readthedocs.io/en/latest/). |
| 355 | + |
| 356 | +First version by: |
| 357 | + |
| 358 | + |
0 commit comments