# KrypoCamp 第三週課前預習 Solidity ### Function Modifiers(函數修飾符) 透過宣告修飾符並掛載給已存在方法來調整方法行為 - 如函數一樣可傳入參數 - 宣告不可使用相同命名(不論參數類型) - "_" 的意思是原方法的內容 ```solidity= modifier onlyOwner() { // Modifier _; } modifier checkOwner(address _addr) { require(_addr == owner, "Address is not the owner."); _; } ``` ```solidity= // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract MyToken { address public owner; modifier onlyOwner() { require( msg.sender == owner, "Only owner can call this." ); _; } modifier checkOwner(address _addr) { require(_addr == owner, "Address is not the owner."); _; } function burn() public view onlyOwner { // ... } function mint() public view checkOwner( msg.sender ) { // ... } } ``` ### Events 智能合約中唯一能夠留下 Log 行為紀錄的方法 - 可用於追蹤。 - 可串接Log,用於訂閱事件 ```solidity= event HighestBidIncreased(address bidder, uint amount); ``` ```solidity= // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.21 <0.9.0; contract SimpleAuction { event HighestBidIncreased(address bidder, uint amount); // Event function bid() public payable { // ... emit HighestBidIncreased(msg.sender, msg.value); // Triggering event } } ``` ### Errors 遇到錯誤,回滾狀態(回到原本狀態),並且扣除/(不)返還手續費 - throw(不返還手續費)(現在不使用) - assert(不返還手續費) - require(返還未使用手續費 - 有條件檢查) - revert(返回未使用手續費 - 無條件檢查) ```solidity= // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; /// Not enough funds for transfer. Requested `requested`, /// but only `available` available. error NotEnoughFunds(); contract Token { mapping(address => uint) balances; function transferThrowError() public { // revert(); throw; } function transferAssertError() public { assert(false); } function transferRevertError() public { revert NotEnoughFunds(); } function requireRevertError() public { require(false, "revert error"); } } ``` ### Function Virtual, Override ```solidity= // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); } /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } contract MyToken is IERC20, IERC20Metadata { mapping(address => mapping(address => uint256)) private _allowances; constructor() {} /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = msg.sender; return true; } function name() public view virtual override returns (string memory) { return "We Are Gonna Make it."; } function symbol() public view virtual override returns (string memory) { return "WAGMI"; } function decimals() public view virtual override returns (uint8) { return 18; } } ``` ### Address Method `All three functions call, delegatecall and staticcall are very low-level functions and should only be used as a last resort as they break the type-safety of Solidity.` 以下幾個 address 方法都是屬於低階方法,不為可靠與預期,需要謹慎使用 - call - 呼叫指定合約函數,呼叫者為合約,環境為呼叫合約 - callcode - 呼叫指定合約函數,呼叫者為合約,環境為原合約 - delegatecall - 呼叫指定合約函數,呼叫者為原合約呼叫者,環境為原合約 - staticcall - 呼叫指定合約函數,只可讀 ```solidity= address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); ``` ### ABI - abi.encodeWithSelector(bytes4(keccak256(signature)) - abi.encodeWithSignature - abi.encode - abi.encodePacked ### Defi 智能合約導讀 #### Defi > 去中心化金融是一種建立於區塊鏈上的金融,它不依賴券商、交易所或銀行等金融機構提供金融工具,而是利用區塊鏈上的智慧型合約進行金融活動。DeFi平台允許人們向他人借出或借入資金,交易加密貨幣,並在類似儲蓄的帳戶中獲得利息。 #### 什麼是自動化做市商(AMM)? > 自動化做市商(AMM)是一種去中心化交易所(DEX)協議,以數學公式來為資產進行定價。資產不再像傳統交易所般使用訂單簿,而是由價格演算法來定價。 每種協議的公式皆不同。例如,Uniswap使用x * y = k ,其中x是流動池中一種代幣的數量,而y是另一種代幣的數量。在此公式中, k是一個固定常數,意味著流動池的總流動性永遠保持不變。其他AMM會按照其特定用例而使用不同的公式。但是,它們之間都有相似之處,就是通過演算法來確定價格。 #### 什麼是流動資金池? > 流動性供應者(LP)將資金注入流動性資金池中。您可以把流動池想像為是一大筆可讓交易者進行交易的資金。流動性供應者會在其流動池的交易中賺取費用,作為向協議提供流動性的回報。在Uniswap的情況,流動性供應者存入兩個價值相等的代幣,例如是把50% ETH及50% DAI存到ETH/DAI池。 UniswapExchange v1 - [完整 Solidity](https://github.com/PhABC/uniswap-solidity/blob/master/contracts/uniswap/UniswapExchange.sol) - [簡化 Solidity](https://gist.github.com/madeinfree/d1d0fd5c6bb3406174eb6394d407bb77) UniswapExchange v2 - [官方 Solidity 版](https://github.com/Uniswap/v2-core) #### 延伸讀物 [Solidity Tutorial](https://www.tutorialspoint.com/solidity/) [Solidity by Example](https://solidity-by-example.org/) [深入智能合約 ABI](https://medium.com/taipei-ethereum-meetup/ethereum-%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84%E9%96%8B%E7%99%BC%E7%AD%86%E8%A8%98-%E6%B7%B1%E5%85%A5%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84-abi-268ececb70ae)