### 2024.09.23 1. Remix IDE * File Extension of Solidity : `.sol` * `Ctrl` + `S` -> Compile * `Deploy` -> Simulate Ethereum chain -> run smart contracts 2. Basic ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract HelloWeb3{ string public _string = "Hello Web3!"; } ``` - `// SPDX-License-Identifier: MIT` -> Denotes license identifier (`MIT` for example) - `pragma solidity ^0.8.21;` -> Only allow compiler version `0.8.21` ~ `0.9.0`(`0.8.21` for example) - `contract HelloWeb3` -> Similar as `class` in other programming language (`HelloWeb3` for example). also,we call it "合約" - `string public _string = "Hello Web3!";` -> Declared Variables - `string` : Value type | Type | Explain | Example | | ------- | --------------------------- | --------------- | | int | integer | 3 , 300 , -123 | | uint | unsigned integer(include 0) | 3 , 300 | | uint<k> | k-bit unsigned integer | uint8 , uint64 | | bool | boolean | true , false | | address | address(e.g. ETH account) | 0x1234556 | | enum | enumeration | {Mon=1,Tue,Wed} | * `public` : visibility | Type | Outside Contract | In Contract | Inheritance Contract | | ------------------- |:----------------:| ------------------- |:--------------------:| | public | ✅ | ✅ | ✅ | | private | ❌ | ✅ | ❌ | | external (function) | ✅ | ✅use `this.func()` | ✅use `this.func()` | | internal | ❌ | ✅ | ✅ | - `_string` : Value name,Define by your self - `"Hello Web3!"` : Value --- ```solidity= function <functionName>(<Type> <ParameterName>) <visibility> <modifier> returns (<Type>) ``` `<Type> <parameter1>` : Input parameter,e.g. `int a` &nbsp;&nbsp;&nbsp;&nbsp; Also,you can input more than 1 parameter `<modifier>` : | Value | Explain | | ------- | ------------------------- | | pure | cannot read nor write | | view | can read but cannot write | | (NULL) | can both read and write | | payable | can receive ETH | ### 2024.09.24 1. Variables data storage locations: | Type | stored | modified | | ---------------- | --------- | ------------- | | storage(deafult) | on-chain | ✅ | | memory | in memory | ✅ | | calldata | in memory | ❌(read-only) | scope: ```solidity= contract Example { uint public count; function increment() public pure returns (uint) { uint localCount = 0; return localCount; } } ``` | Type | Location | Complain/Example | | ---------------- | ----------- | --------------------------- | | State(狀態變量) | `storage` | `count`(in contract storage) | | Local(局部變量) | `memory`(reference types)<br>`stack`(basic types) | `localCount`(in function) | | Global(全局變量) | EVM dynamic | `msg.sender`,`block.number` | 2. Array ```solidity= //fixed-sized arrays <type>[<length>] <name>; <type>[] memory <name> = new <type>[](<length>); uint[9] array; uint[] memory array3 = new uint[](5); //dynamic-sized array uint[] array1; bytes array2; //dynamic byte array ``` - `.length` -> return array's length dynamic array : - `.push` -> add `0`element at the end of array - `.puxh(x)` -> add `x`element at the end of array - `.pop` -> remove the last element of array 3. Struct ```solidity= struct Student{ uint id; uint score; } //4 ways to assign value function method1() external{ Student storage _student = student; //copy Student _student.id = 11; _student.score = 100; } function method2() external{ student.id = 1; student.score = 80; } function method3() external { student = Student(3, 90); } function method4() external { student = Student({id: 4, score: 60}); } ``` 4. Map key -> Value ```solidity= mapping(<KeyType> => <ValueType>) public <name>; mapping(address => uint) public balances; <name>[<key>] = <Value>; balances[msg.sender] = 100; ``` ### 2024.09.25 1. constant/immutable | Characteristic | `constant` | `immutable` | | ------------------- | ------------------------------------------ | ----------------------------------------------------------------- | | Initialization time | declaration | constructor/declaration | | Modification time | Compile-time constant | Determined at deployment | | Storage location | Inlined directly at compile-time | storage | | Use cases | completely fixed values (e.g. fixed rates) | values determined by conditions at deployment time (e.g.deployer) | 2. Control flow same as C ```solidity= //if-else function ifElseTest(uint256 _number) public pure returns(bool){ if(_number == 0){ return(true); }else{ return(false); } } //for loop function forLoopTest() public pure returns(uint256){ uint sum = 0; for(uint i = 0; i < 10; i++){ sum += i; } return(sum); } //while function doWhileTest() public pure returns(uint256){ uint sum = 0; uint i = 0; do{ sum += i; i++; }while(i < 10); return(sum); } //Insertion Sort function insertionSort(uint[] memory a) public pure returns(uint[] memory) { for (uint i = 1;i < a.length;i++){ uint temp = a[i]; //uint j=i-1; uint j=i; //uint can while( (j >= 1) && (temp < a[j-1])){ (temp < a[j]) a[j] = a[j-1]; j--; } a[j] = temp; } return(a); } ``` ### 2024.09.27 1. constructor If variables is dynamic dicision **when deploy**,we can use `constructor` to assign (similar as `decorator`) ```solidity= address owner; constructor(address initialOwner) { owner = initialOwner; } ``` 2. modifier use to modify the behavior of function ```solidity= address public owner; bool public paused; constructor() { owner = msg.sender; paused = false; } modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _;//continue to run function } modifier whenNotPaused() { require(!paused, "Contract is paused"); _; } function setPause(bool _paused) public onlyOwner { paused = _paused; } function changeOwner(address newOwner) public onlyOwner whenNotPaused { owner = newOwner; } ``` 3. event When event be triggered,it will be recorded in log ```solidity= event Transfer(address indexed from, address indexed to, uint256 value); function transfer(address _to, uint256 _value) public { emit Transfer(msg.sender, _to, _value); //trigger event } ``` 4. override OverWrite the parent function ```solidity= contract Parent { function foo() public virtual { } } contract Child is Parent { function foo() public override { //... } } ``` ### 2024.09.29 1. Interface Define the interactions between contracts ```solidity= interface Token { function transfer(address recipient, uint256 amount) external returns (bool); } contract MyToken is Token { mapping(address => uint256) public balances; function transfer(address recipient, uint256 amount) external override returns (bool) { require(balances[msg.sender] >= amount, "Insufficient balance"); balances[msg.sender] -= amount; balances[recipient] += amount; return true; } } ``` 1.1 IERC721 - event-Transfer: ```solidity! event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); ``` when `tokenID` moved from `from` to another address `to` - event-ApprovalForAll: ```solidity! event ApprovalForAll(address indexed owner, address indexed operator, bool approved); ``` The token holder authorizes/de-authorizes an `operator` to manage all its tokens. - function-balanceOf ```solidity! function balanceOf(address owner) external view returns (uint256 balance); ``` return the number of tokens owned by `owner` - function-ownerOf ```solidity! function ownerOf(uint256 tokenId) external view returns (address owner); ``` return the address of owner of `tokenID` and more.... ### 2024.09.30 1. Error Handling - `require` Used to check if a condition is true If false,contract will be terminated ```solidity= function withdraw(uint amount) public { require(amount <= balance, "Insufficient balance"); balance -= amount; payable(msg.sender).transfer(amount); } ``` - `assert` Used to check if a condition **always** be true ```solidity= function decrement() public { assert(counter > 0); counter -= 1; } ``` - `error` Custom error ```solidity= error InsufficientBalance(uint requested, uint available); function withdraw(uint amount) public { if (amount > balance) revert InsufficientBalance({ requested: amount, available: balance }); balance -= amount; payable(msg.sender).transfer(amount); } ```