# 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)