---
title: "Solidity 中的 selfdestruct 是什麼？"
description: "是什麼、運作原理，以及如何開始使用"
---

# Solidity 中的 selfdestruct 是什麼？

**更新**：在 Shanghai Ethereum 升級中，Selfdestruct 已依照 [EIP-6049](https://eips.ethereum.org/EIPS/eip-6049) 的規範被棄用。本文內容已過時，僅反映此功能過去的運作方式。

_Selfdestruct_ 是 [Solidity](https://www.alchemy.com/overviews/solidity) 中的一個關鍵字，用於開發者想要終止合約時使用。根據 2021 年一篇研究論文〈Why Do Smart Contracts Self-Destruct? Investigating the Selfdestruct Function on Ethereum〉，約有 800 個合約使用了 _selfdestruct_ 關鍵字，使其成為[學習 Solidity](https://www.alchemy.com/overviews/learn-solidity) 時的重要概念。

本文將定義 _selfdestruct_ 是什麼、說明其用途，並提供在 [Solidity](https://www.alchemy.com/dapps/solidity) 智能合約中實作 _selfdestruct_ 的範例。

## **什麼是 selfdestruct？**

Selfdestruct 是一個用於終止合約、從 Ethereum 區塊鏈上移除位元組碼，並將合約中的資金傳送到指定地址的關鍵字。

_Selfdestruct_ 起源於 2016 年，當時 Ethereum 區塊鏈與去中心化組織（[DAO](https://www.alchemy.com/dapps/top/daos)）都還處於發展初期。其中一個最早的 DAO 遭駭客攻擊，損失了 360 萬 ETH。由於 Solidity 合約具有不可變性，這次攻擊持續了數天。當時尚不存在銷毀合約的方法，早期的 DAO 開發者只能分岔整條區塊鏈，以防止進一步的漏洞利用。

因此，_selfdestruct_ 被創造出來，作為安全威脅發生時的緊急出口。雖然它最初被稱為「suicide function」，但從 **Solidity v0.5.0** 起改名為 _selfdestruct_。

### 開發者為什麼要使用 selfdestruct 函式？

開發者使用 selfdestruct 函式，主要是為了提升智能合約程式碼的安全性、清理不再使用的合約，以及快速轉移 Ethereum 資產。

當開發者需要升級智能合約時，_selfdestruct_ 就很有幫助。舉例來說，[ERC-20 框架](https://www.alchemy.com/overviews/erc20-solidity)是 Ethereum 上所有同質化代幣的標準實作方式，目的是為了互通性。任何未依循 ERC-20 標準的代幣，都會難以與其他合約互動。

在這種情況下，開發者會改用新合約，而不是升級現有合約。因此，他們可以使用 _selfdestruct_ 函式從現有合約中取出資金，並建立一個具備所需功能的新合約。

開發者也會使用 _selfdestruct_ 函式來防範潛在的安全威脅。根據同一份[2021 年 selfdestruct 智能合約報告](https://arxiv.org/pdf/2005.07908.pdf#:~:text=On%20the%20one%20hand%2C%20using,an%20attack%20vector%20for%20attackers)，當開發者在合約中發現安全漏洞時，_selfdestruct_ 函式能協助他們立即終止有缺陷的合約，並以安全的合約取代它。

### 使用 selfdestruct 有哪些缺點？

selfdestruct 函式的缺點在於：無法回收 ERC-20 代幣，且合約自我銷毀後無法將代幣重新導向。

一般來說，_selfdestruct_ 函式被呼叫時，往往是因為開發者未能及時通知合約即將終止。即使團隊有發出通知，訊息也可能來不及擴散。結果就是，有些人可能會以為合約仍在運作，而將資金傳送到已銷毀的合約，這種情況下資金就會遺失。

使用 _selfdestruct_ 的第二個缺點是，它只能轉移 Ether（ETH），而無法轉移其他 ERC-20 代幣，例如山寨幣，或依循 ERC-721 代幣標準的 NFT。一旦呼叫 _selfdestruct_，這些資產就永遠無法回收。

#### 為什麼有些人認為 selfdestruct 函式很危險？

selfdestruct 函式讓惡意開發者更容易進行 rug pull。

這個函式讓開發者能夠呼叫 _selfdestruct_，並將資金導向自己的個人錢包。因此，部分協議使用者與開發者對於使用 _selfdestruct_ 函式抱持著複雜的態度。

## selfdestruct 是如何運作的？

selfdestruct 的運作方式是：從鏈上抹除合約的位元組碼、將所有資金傳送到指定地址，然後將部分 gas 費用退還給開發者。

一個合約由兩個部分組成：狀態（state）與函式（functions）。這些部分定義了合約的行為以及[可呼叫的函式](https://www.alchemy.com/overviews/solidity-functions)。移除位元組碼意味著合約不再具備任何定義它的組成部分，使得該合約無法被呼叫。

_selfdestruct_ 函式有一個必要參數，用來指定呼叫者希望合約資金在銷毀後歸屬的地址。

### **什麼是 negative gas，為什麼它很重要？**

Negative gas 指的是交易手續費中的一部分，當開發者使用 selfdestruct 函式時，Ethereum 鏈會退還這部分費用。

Ethereum 透過將移除鏈上資料所節省下來的 gas 回饋給呼叫者，來鼓勵使用 _selfdestruct_ 函式。當合約呼叫 _selfdestruct_ 函式時，該交易所使用的總 gas 有一半會退還給呼叫者。

### selfdestruct 會移除合約在 Ethereum 區塊鏈上的歷史紀錄嗎？

不會，selfdestruct 函式不會移除合約在 Ethereum 鏈上的歷史紀錄——它只會移除合約的位元組碼。

Ethereum 是一條區塊鏈，也是一個公開帳本，由一個互相連接的節點網路持續保存區塊鏈狀態的副本。因此，呼叫 _selfdestruct_ 函式之前所發生的所有資料與交易，都會永久記錄在鏈上，無法被更改。

### 呼叫 selfdestruct 函式後，資金會永久遺失嗎？

**有些會，有些不會：現有的 ETH 會被傳送到呼叫者所指定的另一個地址，而 ERC-20 代幣則會遺失。**

此外，如果有人在合約已 selfdestruct（即已終止）之後，仍向該合約傳送資金，這些資金將不會被重新導向，並會遺失。

## selfdestruct 函式範例

這個程式的目的，是允許鑄造 NFT，直到合約中累積達到一定數量的 ETH 為止。一旦達到此數量，程式會將所有 Ether 作為獎勵傳送給最後一位鑄造者的錢包。每個人可以用 1 Ether 鑄造多個 NFT，但每次只能鑄造一個。**此合約並非用於正式環境，僅作為範例用途。**

這個鑄造合約的主要問題在於，它使用「_this.balance_」來驗證合約是否有足夠資金以觸發結束條件。因此，攻擊者可以輕易地傳送一筆金額，讓合約超過指定上限，接著使用 _selfdestruct_ 關鍵字，將資金導向自己宣告的建構子（constructor）。

因此，在使用 _selfdestruct_ 時，開發者必須謹慎選擇用來滿足特定條件的變數。應避免使用任何指向合約地址或合約內資金的參照，因為這些都可能被人為操縱。

## **如何使用 selfdestruct 函式**

初始化 selfdestruct 函式很簡單：你只需要在函式中使用 selfdestruct 關鍵字，並指定一個 payable 地址，該地址會在呼叫 selfdestruct 函式後接收合約資金。

以下是 Solidity 課程中常見的 _selfdestruct_ 函式範例：

以下說明這段程式碼在做什麼：

- 這個函式的名稱是 *destroy*
- 參數將地址指定為 *apocalypse*
- 當 destroy 函式被呼叫時，地址會透過 apocalypse 變數指定
- [函式的可見性宣告為 public](https://www.alchemy.com/overviews/solidity-function-visibility)，讓其他合約也能存取它。
- 接著我們使用 _selfdestruct_ 關鍵字，並在將 apocalypse 變數宣告為 payable 之後傳入。

由於此函式是 public 的，這代表著潛在的安全漏洞。為了應對這一點，你可以考慮加入 _onlyOwner_ 修飾符，或使用 [require 陳述式](https://www.alchemy.com/overviews/solidity-require)，來確認只有擁有者能呼叫 destroy 函式。

### 透過 Alchemy 的 Solidity 開發者課程學習 Solidity 與 selfdestruct 函式

_Selfdestruct_ 作為一種安全機制，可在遭遇安全漏洞、開發者想要升級合約，或需要移除舊合約時終止合約。雖然 _selfdestruct_ 的使用在 Solidity 開發者社群中仍存在爭議，但這個函式的出現，確實協助防範了許多潛在的駭客攻擊。

想深入了解像 _selfdestruct_ 這樣的重要函式，並[成為更優秀的 Solidity 開發者](https://www.alchemy.com/overviews/how-to-become-a-solidity-developer)，可以報名 Alchemy University 的[免費七週 Ethereum Bootcamp](https://university.alchemy.com/?a=d1bd288312)。如果開發者對開發本身還很陌生，Alchemy 的 **三週 JavaScript 速成課程** 是開始 Ethereum bootcamp 前很好的先修課程。
