---
title: 'Solidity WTF 102 25 ~ 26 單元'
lang: zh-tw
---
Solidity WTF 102 25 ~ 26 單元
===
:::info
:date: 2024/10/07
:::
[TOC]
# 課程學習
## CREATE2
### 簡介
其實與合約中創建新合約相關,只是創建方式不同。
#### CREATE
先來說說`CREATE`是如何計算地址
> 通常是創建者地址 + 該地址發送交易的總數,如果是合約帳戶則是創建合約的總數,每創建一次都會 nonce + 1
```javascript=
新地址 = hash(创建者地址, nonce)
```
#### CREATE2
目的是為了讓合約地址獨立於未來的事件,也就是預測地址,他由以下四種方法去計算:
- 0XFF: 一個長數,避免和CREATE衝突。
- CreatorAddress: 調用CREATE2的當前合約地址。
- salt: 一個創建者指定的bytes32類型的值,主要目的用來影響創建出來的合約地址。
- initcode: 新合約的初始字節。
```javascript=
新地址 = hash("0xFF",创建者地址, salt, initcode)
```
### 如何使用
與CREATE類似都是new一個合約出來,但是傳入的參數並不同:
```javascript=
Contract x = new Contract{salt: _salt, value: _value}(params)
```
### 如何提前計算Address
用來預測的方法,其實都是這四個參數帶入後取唯一值,就是我創建的新合約的地址。
```javascript!
predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff), // 固定的前綴
address(this), // 部署該合約的創建者地址(工廠合約地址)
salt, // 用於區分不同合約部署的隨機值
keccak256(type(Pair).creationCode) // 合約的創建碼的哈希值
)))));
```
如果在創建新合約中有值帶入,那就會是
```javascript!
predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff), // 固定前綴,表明使用CREATE2
address(this), // 工廠合約地址
salt, // 隨機值 salt
keccak256(
abi.encodePacked(
type(Pair).creationCode, // 合約創建碼
abi.encode(address(this) // 構造函數參數
)))
)))));
```
:::success
這邊重點我認為應該是在怎麼去更改合約創建碼的內容,因為其餘都是複製貼上,並且清出了解與CREATE的差別。
:::
## 刪除合約
### 簡介
selfdestruct命令用來刪除合約,並將被刪除的該合約剩餘ETH轉到指定的地址。
> 如果想使用 SELFDESTRUCT 銷毀合約並釋放合約中的資源,那麼這必須是在同一筆交易內完成的,否則已經部署且在多筆交易中運行的合約不容易再通過 SELFDESTRUCT 來執行相同的功能。
:::info
早期被命名為suicide(自殺),後來改掉。
:::
:::warning
在V0.8.18版本中,selfdestruct關鍵字被標記為「不再建議使用」,目前還沒有替代方案,所以只是編譯階段的警告。[詳細看這裡 EIP-6049](https://eips.ethereum.org/EIPS/eip-6049)
:::
### 使用方式
`value`初始設置為10,並且有兩個函數`deleteContract() and getBalance()`,合約部屬後可以透過`msg.value`傳入`ETH`,並且這時呼叫`getBalance()`會返回傳入的ETH數量,`Value`仍然是`10`。當我們調用`deleteContract()`,會把合約中的`ETH`返回於`msg.sender`。
```javascript!
// _addr是接收合約中剩餘的ETH地址。不需有receive() or fallback()也能接收。
selfdestruct(_addr);
// 下列是範例
contract DeleteContract {
uint public value = 10;
constructor() payable {}
receive() external payable {}
function deleteContract() external {
// 调用selfdestruct销毁合约,并把剩余的ETH转给msg.sender
selfdestruct(payable(msg.sender));
}
function getBalance() external view returns(uint balance){
balance = address(this).balance;
}
}
```
:::warning
這邊有個重點,**在坎昆升級前,合約是會被自毀的,升級後,合約會依然存在,只是將合約包含的ETH轉移到指定地址中,而合約依然可以調用**。所以在調用`deleteContract()`後,`value`仍然是`10`。
:::