智能合約是可編程的代碼,僅在滿足一組條件時才執行。在現實世界中,與具有法律約束力的合衕具有相衕含義;隻有在這種情況下,代碼才是法律。由於智能合約駐留在區塊鏈上,因此它們是不可變的,即無法被篡改。正是這種不變性商數賦予智能合約特殊性。
智能合約用於自動化區塊鏈特定的交易。由於它們是特定條件的合約,因此不需要中介機構。智能合約之所以有效,是因爲它們在廣泛的用例(包括金融服務、供應鏈管理等)中具有兼容性。與一次性編程的傳統代碼塊不衕,智能合約需要高度安全且耗時的策略。
智能合約如何與區塊鏈技術相結合(來源:BeInCrypto)
“流行語“web3”暗含了網絡鬆散、安全性差的編程習慣。當加密貨幣或智能合約像網頁一樣編程時,它們就註定會失敗。可持續成功的區塊鏈及其應用程序基於更加安全、周密和緩慢的編程方法。”——Nick Szabo,密碼學家和計算機科學家髮布於Twitter
智能合約可與區塊鏈特定的代幣(例如以太坊區塊鏈的 ERC-20)配合使用,從而激勵行動併促進交易各處轉移。由於涉及代碼、條件和成本,您應謹慎讀取、寫入和審計它們。
智能合約的真正意義在於其本質和定位。對於給定的場景,比如當 A 完成一項服務時,A 將資金轉移給 B,區塊鏈節點會保存併執行智能合約的副本。智能合約在鏈內保存爲合約代碼。這種多路徑驗證是一種以區塊鏈爲中心的特徵,可確保事物的安全。
此外,還存在以次序而髮生的智能合約或衕步智能合約和異步智能合約,其中任務併行執行。因此,智能合約的類型和用途決定了它的寫入、讀取甚至審計方式。要明白以下特徵:
傳統的合衕、財産契約、遺囑等都是私法,即“由私人而不是政客或政府官僚起草”。智能合約就是這種去中心化規則製定的一種新形式。參閲:https://t.co/EU2Y28FznK
— Nick Szabo (@NickSzabo4) 於2018年3月15日髮布
讓我們考慮一個標準的智能合約管理的流動性池。
想象一下,代幣池可用於交易,每次成功進行交易時,總交易價值的0.3%都會髮送給流動性提供者,流動性提供者實施交易或爲給定的可交易資産增加流動性。所有強調交易場景、交易費用、違規和交易失敗的條件都被編碼爲智能合約,以合約代碼的形式存儲在鏈內。
智能合約的特點
如果我們不了解合約的特徵,我們就無法深入讀取、寫入和審計合約。以下是需要明白的標準智能合約特徵:
標準智能合約的一些特徵(來源:BeInCrypto)
智能合約隻是一些代碼。您可寫入智能合約來根據特定條件執行命令和場景。這就是爲什麽智能合約開髮人員和程序員目前很受大家的青睞,因爲大多數 DeFi 領域已經依賴智能合約來處理覆雜的實例,例如處理跨流動性池的交易費用、維護 APY 比率等。
駐留在區塊鏈上的智能合約無需人爲幹預。因此,他們是完全去信任的。例如,如果由智能合約管理的特定 DeFi 協議衕意在價值低於閾值時清算您的資産,則任何人爲幹預都不能或不應阻止它。該代碼處理支付、性能、管理和規則執行,使整個空間完全去信任化。
如前所述,智能合約加載了自動執行的指令集。就編碼而言,這意味著在樣闆內構建迭代和循環。這確保了諸如支付、提款、存款、通過削減懲罰驗證者等任務以及其他一些任務都是自主處理的。
最後,由於智能合約是使用密碼學來保護的,因此破解它們非常睏難。如果沒有內置漏洞,繞過智能合約就意味著試圖在整個區塊鏈麵前公開破壞它。
通過智能合約處理的交易是可自我驗證的。這意味著執行足以證明交易是首先髮生的,因爲不涉及人爲因素。自我驗證機製使智能合約比管理遺留銀行設置的傳統合約更具優勢。
因此,下次您計畫讀取智能合約時,請確保樣闆或文檔包含所涉及的所有上述特徵。
簡版智能合約(來源:Reddit)
這是一個代錶托管賬戶的簡單智能合約。用戶將資金存入托管機構,然後在特定時間範圍過後將資金轉移到接收方。
/ SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Basic Smart Contract Boilerplate
contract SimpleTrustlessEscrow {
// State variables
address public depositor; // Account depositing ether
address payable public beneficiary; // Account receiving ether
uint256 public releaseTime; // Timestamp to release ether
// Events for verifying contract activity
event Deposited(address indexed _from, uint256 _value);
event Released(address indexed _to, uint256 _value);
// The contract constructor initializes the smart contract
constructor(address payable _beneficiary, uint256 _releaseTime) {
require(_releaseTime > block.timestamp, “Release time must be in the future”);
// Secure and Trustless: Contract binds depositor and beneficiary
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
}
// Deposit function – autonomous execution (fallback function)
receive() external payable {
emit Deposited(msg.sender, msg.value);
}
// Release the ether to the beneficiary
function release() public {
// Programmable: Can only be executed after releaseTime
require(block.timestamp >= releaseTime, “Too early to release”);
// Autonomous: Automatically executes based on condition
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
emit Released(beneficiary, amount);
}
}
雖然我們將詳細解讀併讀取此智能合約,但讓我們首先檢查它是否具備上述合約特徵。
Look at the contract closely for this piece of code:
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
The funds are to be released only when a specific releaseTime condition is met, making these programmable contracts.
仔細閲讀合約中的這段代碼:
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
僅當滿足特定的釋放時間條件時才會釋放資金,從而形成這些可編程合約。
讓我們快速瀏覽上麵的這個代碼片段:
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
在合約中,從存款人到接收資金的人,每個人都受代碼的約束。沒有人需要與對方交互或信任對方,因爲轉移資金的功能受到releaseTime(一種基於代碼的參數)的約束。
閲讀以下代碼的“資金釋放”部分:
function release() public {
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
emit Released(beneficiary, amount);
}
整個過程是自主執行的,因爲隻有當釋放時間滿足一定標準時才會釋放資金。請註意,代碼不是部分可編程的,而是完全自主的。
智能合約代碼的其他元素(包括存款功能)也可以完全是自主的,具體取決於您想要包含的功能。例如,每當用戶的錢包有超過100美元時,您就可以啟動定期存款計畫,多餘的金額將轉移給收款人。
想知道哪個要素爲合衕提供擔保?查看這部分代碼:
constructor(address payable _beneficiary, uint256 _releaseTime) {
require(_releaseTime > block.timestamp, “Release time must be in the future”);
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
}
請註意,releaseTime 函數相對於時間戳是如何設置優先級的。沒有什麽是隨機的,必鬚滿足條件。
與智能合約相關的每筆交易都記録在鏈中,由單獨的日誌活動元素提供。
event Deposited(address indexed _from, uint256 _value);
event Released(address indexed _to, uint256 _value);
emit Deposited(msg.sender, msg.value);
emit Released(beneficiary, amount);
現在我們已經確定了定義智能合約特徵的元素,以下是其他合約的元素,可以幫助您更好地練習理解智能合約。
Pragma solidity ^0.8.0; ——寫入此智能合約所需的 Solidity 編程語言版本。
// SPDX-License-Identifier:MIT ——術語“軟件包數據交換”,該標識符錶示代碼髮布的許可證。合約應包含此內容,以便讓人們知道它是否是開源的併且是否是可解決的。
Contract TimeLock { ——爲智能合約分配名稱,就像是一個標簽。
Address public depositor;——由於合衕涉及存款人和收款人,因此這裡提到了存款人的公共地址。該變量是以太坊錢包地址,併且是公開可見的。
Address payable public beneficiary; ——這是收款人的公共地址,托管機構將資金轉移到該地址。它也是可讀取的,併爲區塊鏈驅動的智能合約帶來了透明度。
Uint256 public releaseTime; ——由於這是一個有時限的合約,因此 uint256 將基於時間的變量分配給合約。這將是資金釋放的時間錶。
在 Solidity 編程語言中,uint(無符號整數)是分配基於整數的值的方式。後綴256代錶存儲的大量數字。
經過5年的智能合約寫入經歷後,我直到今天才意識到 Solidity 徽標是展開的以太坊徽標 pic.twitter.com/wlM369Eff9
——kaden.eth (@0xKaden) 髮布於2023年7月8日
您可參閲 Solidity 文檔來深入了解語法、錶達式和其他代碼元素。
constructor(address payable _beneficiary, uint256 _releaseTime) { ——“Constructor”是一個一次性特殊函數,在部署智能合約時被調用。它啟動了合約。請註意,在此時,我們之前聲明的所有地址變量都被調用併進行初始化。
Receive() external payable { ——這是資金從外部轉移到合約地址時調用的特殊函數。External暗示來自外部,“Payable”定義了此舉的性質,即接收ERC-20代幣。
Function release() public { ——這是一個公共函數,用於説明 ERC-20 代幣從合約地址轉移到收款人。該功能受到releaseTime的影響。
所有這些要素都是我們討論假設作爲托管合約的一部分。因此,您能閲讀到完整的 Solidity 文檔,以便更好地了解該語言。
在計畫寫入智能合約之前了解的要素(來源:BeInCrypto)
到目前爲止,您應已在讀取和理解已寫入的智能合約方麵有了些知識。許多智能合約(例如我們討論的智能合約)構成了去中心化應用程序的後端——標準移動應用程序的區塊鏈版本。
智能合約的每一個特性,包括合約安全性、自主性和可編程執行、交易的去信任性等等,在開髮去中心化應用程序時都很容易實現。因此,下次您無意遇到 DApps 時,請註意,它是托管在區塊鏈上的智能合約驅動的後端,可幫助您在無需人工幹預的情況下啟動多個任務。智能合約構成了 DApps 的邏輯。
我們知道,以太坊可讓您開髮智能合約,就像大型軟件解決方案一樣。然而,它併不是唯一的區塊鏈協議。如果您想深入了解智能合約開髮領域,那麽您可能想看看其他區塊鏈。不衕的區塊鏈在製定合約時有不衕的用語。
但首先,讓我們討論一下以太坊——這是大多數智能合約開髮人員的首選平颱。
以太坊上的智能合約是用 Solidity 編程語言寫入的。該智能合約開髮平颱的代幣接口是ERC-20。
您可回到我們之前討論的基於托管的智能合約,看看標準的基於以太坊的智能合約是如何寫入的。
即使在以太坊區塊鏈上啟動 ERC-20 代幣也是一項嚴重依賴智能合約的功能,我們將在寫入智能合約時深入討論這一點。
如果我們計畫推出新的加密貨幣 BIC,則基本代碼結構如下所示。
(此處併不是真的推出 BIC 加密貨幣,隻是一個假設場景。)
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BICToken is ERC20 {
constructor(uint256 initialSupply) ERC20("BIC Token", "BIC") {
_mint(msg.sender, initialSupply);
}
}
稍後在寫入智能合約時,我們將討論該代碼的每個元素。
與以太坊一樣,您甚至可以在 Solana 等平颱上使用 Rust 和 Cardano、Plutus(函數式編程語言 Haskell 的子集)創建智能合約。
“Cordona 也有智能合約嗎?”
跟你開玩笑的,朋友。 #CardanoADA pic.twitter.com/j8SXCu72Sd ——Willybot 🇦🇺 (@wilbot28) 髮布於2023年7月9日
Rust (Solana) 中的代碼結構如下所示:
(註意:這是一個簡單的合約,其中計數器會遞增。)
use anchor_lang::prelude::*;
declare_id!(“Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS”);
#[program]
pub mod hello_world {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
let greeting_account = &mut ctx.accounts.greeting_account;
greeting_account.counter = 0;
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> ProgramResult {
let greeting_account = &mut ctx.accounts.greeting_account;
greeting_account.counter += 1;
Ok(())
}
}
你可知道?Rust 是用於創建基於 Solana 的智能合約的編程語言,而 Anchor 是所使用的智能合約開髮框架。爲了使用 Rust 創建智能合約,開髮人員需要從 Anchor 框架中提取模塊——以上示例代碼的第一行 (useanchor_lang::*;) 所代錶的內容。
閲讀此 Solana 文檔,它將幫助您了解 Rust 特定的智能合約語言。
衕樣地,緊隨 Plutus 之後,是作爲語言選擇的Cardano ,其次是 Polkadot 的語言 Ink!、Algorand 的語言 TEAL、NEO 的 C# 等等。在繼續寫入兼容的智能合約之前,建議先詳細學習區塊鏈知識文檔。
具有能寫入智能合約的能力會得到了高度贊賞,但即便隻能讀取智能合約也有其好處,部分如下:
在現已能讀取智能合約的基礎上,讓我們學習如何寫入智能合約。在開始深入研究之前,有必要重申不衕的區塊鏈可能有不衕的與智能合約開髮相關的標準和語言。請務必在寫入和合約部署之始,關註任何給定區塊鏈定義的標準。
在我們的大部分討論中,我們將重點以以太坊區塊鏈爲例,併使用Solidity語言。
智能合約編程無疑是開髮周期中最重要的部分。要進入以太坊或任何其他區塊鏈上實施智能合約開髮,您應該對非區塊鏈編程語言(如 Javascript)有一定的經驗。
不衕的區塊鏈和寫入智能合約的語言(來源:BeInCrypto)
有了寫入智能合約的能力,您就能夠實施邏輯、處理相衕的安全元素、優化Gas費代碼、自定義相衕的代碼,甚至在需要時使相衕的代碼具有互操作性。
任何計畫在以太坊上寫入智能合約的人都需要了解以太坊虛擬機(EVM)是什麽以及它如何與智能合約配合使用。首先,EVM 是一個以太坊組件,爲程序提供了一個隔離且受控的工作環境。可將其視爲托管以太坊上每段合約代碼的全球計算機。以太坊網絡上的每個節點都運行 EVM。
如果您有誌成爲一名智能合約開髮人員,您需要了解以下有關智能合約和 EVM 的知識。
在使用 Solidity(一種高級語言)寫入了程序後,您就需要將其編譯成字節碼——一種機器可理解的低級格式。該字節碼進入以太坊區塊鏈併駐留在其中。任何與智能合約交互的人都需要將交易髮送到合約地址。
每個安裝了 EVM 的節點都可以看到該交易,驗證者批準該交易後,智能合約代碼就會被執行。由於每個節點都具有事務可見性,因此任何內容都無法篡改,併且代碼按寫入時執行。代碼被執行後,區塊鏈的狀態就會髮生變化,使整個過程實現端到端且完全具有透明性。
寫入智能合約需要技術知識。但事實併非如此。您還需要徹底了解區塊鏈技術的工作原理、哪些特定於語言的需求與您所針對的區塊鏈相關、互操作性等等。除此之外,您還應了解與智能合約漏洞相關的大量信息——這寫入代碼時要避免的事情。最後,合約測試和合約部署知識也是必鬚要知曉的。
所有這些都看起來讓人不知所措。因此,以下準備一份快速入門的備忘清單:
以下提供了一份快捷思路,其中包含一些將智能合約寫入得更完善的技巧:
🥧 FREI-PI
‼️ 爲什麽智能合約開髮人員需要知道這些內容!
功能:
– 要求
– 影響
– 交互
協議
不變性
這是您在創建智能合約時應思考的模式。
這就是原因👇
— Patrick Collins (@PatrickAlphaC) 髮錶於2023年7月6日
現在是時候討論智能合約開髮技術方麵的內容了。盡管Solana 和 Cardano 這樣的區塊鏈也允許您開髮智能合約,但以太坊仍然是最受歡迎的智能合約開髮平颱。
你可知道?僅在2022年,就有超過100,000個去中心化應用程序進入以太坊網絡。
以太坊擁有龐大的開髮者社區。您開髮的任何東西都會立刻穫得關註。另外,它的母語 Solidity 對於了解 Python 或 JavaScript 的人來説相對容易。最後,以太坊全球軟件 EVM 有助於無縫執行合約。
如果您是也是青睞以太坊的大多數人之一,併且更喜歡使用以太坊和 Solidity,那麽在開始智能合約開髮之前,您需要了解以下快速入門事項:
在知曉了事情在區塊鏈上是如何進行的情況下,讓我們開始寫入和部署第一個智能合約。盡管“Hello World”仍然是第一步,但我們將首先創建一個智能合約,推出一個假設的 BIC 代幣,其供應量爲100萬個,100%釋放。
開始寫入的基礎事項
第一步,安裝最新版本的 Node.js 和 NPM 或 Node Package Manager(節點包管理器)。這會考慮到開髮工具和本地開髮環境。此外,Node.js 和 NPM 允許您爲智能合約設置 Web 前端。
現在,您需要設置一個IDE來寫入合約代碼。爲此,您可快速安裝 Visual Studio Code。或者您可避免混亂併跳到 Alchemy——一個區塊鏈開髮平颱。通過 Alchemy,您可以穫得一些測試網 ETH。當您將智能合約部署到 Goerli 測試網甚至 Sepolia 測試網時,將産生 Gas 費用。
請註意,Sepolia 是一個較新的測試網,因此它在節點部署方麵占用較少的磁盤空間。
目前,我們將繼續使用 Goerli 測試網,因爲它已有大量已部署的應用程序。
測試網和假 ETH 準備就緒後,讓我們開始具體寫入智能合約。以下是創建固定供應量100萬個 BIC 代幣的代碼片段。
註意:我們將在 MacOS 本地而不是測試網上部署智能合約。對於智能合約的測試網和主網部署,我們將有一個單獨的部分,這在本文不予討論。
以下是假設代幣的簡單代碼片段:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BICToken is ERC20 {
constructor() ERC20("BIC Token", "BIC") {
_mint(msg.sender, 1000000 * 10 ** decimals());
}
}
若您了解語法,您就會知道每個代碼組件的含義。至於Openzepplin部分,它是導入ERC-20智能合約的首選庫。該庫提供了 ERC-20 代幣的基本操作標準。
mint 函數討論初始供應,該供應被部署到智能合約地址或 msg.sender。
要在本地設置此代碼併進行測試,我們需要三個組件:
如果您已完成寫入智能合約的詳細過程,那麽有必要了解一些有關合約執行的知識。它是通過節點在鏈上執行智能合約代碼的過程。
正是與合約執行相關的一緻性使得智能合約透明且不可變。現在讓我們了解與合約執行相關的詳細步驟:
我們寫入的代碼片段需要在某個地方執行。就智能合約而言,執行地點就是區塊鏈。節點或鏈上的參與成員幫助執行合約。
節點負責執行合約代碼塊,以換取與鏈相關的激勵。鏈內髮生的每一個命令或動作都由智能合約主導。
每個智能合約都有一個特定的地址。爲了執行合約,交易被髮送到該合約地址。請註意,每個節點都運行 EVM,然後 EVM 擁有智能合約代碼的副本,從而能更容易地檢查交易的真實性。
針對智能合約的交易由驗證者選出,然後將其包含到特定的區塊中。
交易被推送併成功得到驗證後,它就成爲區塊鏈的一部分。然後,與交易相關的智能合約函數在區塊鏈節點上被調用併執行。
執行智能合約的每個節點都應得出確定性結論——衕一組輸入具有相衕的輸出——從而使合約具有完全去信任和透明的性質。
註意:任何與代碼執行有關的錯誤或與Gas費相關的問題都會導緻交易被撤銷。這意味著基於特定智能合約代碼的交易將不覆存在。這正是閃電貸髮生的情況,因爲無法遵守特定規範而導緻整個交易髮生逆轉,似乎讓人覺得一資金從一開始就沒有流動。
與智能合約相關的每個狀態變化都會記録在區塊鏈中,併成爲區塊鏈的不可變部分。
現在您已經對智能合約有了一定的了解,下麵是一些開啟合約開髮的建議:
上麵提到的每個實踐都能幫助優化代碼併有利於特定於安全性的實現。但是,您必鬚遵循和實施一些特定於合約的實踐,以保證代碼的可持續性。這樣做的目的是,保持合約代碼爲輕量級且是可用的,以便每個運行和執行相衕合約的節點無需投入大量計算能力。
即便在寫入和開髮智能合約時遵循了以上最佳實踐,但在將其推送到主網時仍需要關註合約安全漏洞事宜。
主網中存在的每個智能合約都需要在代碼性能、安全性和其他特徵方麵受到評估。這就是審計(嚴格的合約測試流程)占據重要地位的原因,它讓您能夠髮現潛在的合約漏洞和弱點。
以下是快速入門審計的要點:
絶佳的智能合約審計要點😈
請務必在下次審計時檢查這些內容✅
感恩轉髮,傳播知識🫡https://t.co/ILx0C67kf8
——cholakov (@cholakovv) 髮布於2023年7月7日
讀取、寫入和審計之間的關繫:爲什麽還要審計智能合約?
雖然在開髮智能代碼時,讀取和寫入智能合約是相輔相成的,但審計的地位不一般,併且首先涉及檢查合約的邏輯。在談到基於區塊鏈的代碼執行時,我們都認爲它的一切都是不可變的,任何災難性的事情都可能對合約執行産生不可逆轉的後果。這正是爲什麽需要通過審計對合約代碼和其他方麵進行全麵檢查。
詳細的智能合約審計可識別出許多合約漏洞。其中包括檢查重入攻擊、溢出或下溢、與訪問控製相關的問題等等。確定了問題的確切性質後,審計員甚至可以提供解決該問題的最佳實踐。
還是不明白智能合約審計有何好處?那麽,讓我們回顧一下2016年臭名昭著的 DAO 黑客事件,該事件利用了重入問題,造成了近360萬 ETH 的損失。衕樣,2017年 Parity 錢包合約被黑客攻擊,導緻近50萬 ETH 損失。通過正確的審計,這些問題本來可以避免。
DAO 黑客的流程圖(來源:BeInCrypto)
審計智能合約的策略有很多。以下討論了一些較受歡迎的策略:
審計工具充當第一套防禦措施,最適用於定位常見漏洞。一些更常見工具有 Securify、Mythril 等,能夠對代碼執行靜態分析、檢測漏洞模式併幫助穫得特定於安全性的領先優勢。
審計智能合約的工具(來源:BeInCrypto)
代碼審查由手動代碼審查人員負責,他們檢查代碼庫併識別覆雜的漏洞(若有)。手動審查可幫助處理業務邏輯、上下文和使用模式。
以下介紹了手動代碼審查如何幫助您定位威脅:
給初級審查員的一個小知識!
如果您髮現該漏洞,請轉髮! pic.twitter.com/i14YtweXcz
——CharlesPaladin (@PaladinCharles) 髮布於2023 年7月8日
Snyk 和 GuardRails 等工具能幫助自動合約掃描——每次更新代碼時都會調用的安全實現。這種形式的審計可確保對代碼所做的新更改在本質上是安全且非侵入性的。
形式驗證是一個覆雜的過程,僅依賴於檢查代碼的業務邏輯。請註意,形式驗證實際上併不是爲了驗證語法,而是爲了驗證代碼是否按預期執行的邏輯。
除了上述策略之外,還可使用衕行評審、漏洞賞金計畫和通過 Solidity Coverage 等工具測試覆蓋率來啟動智能合約審計,以最大限度地提高效率。
審計智能合約的簡單方法(來源:BeInCrypto)
如果您是一位新手智能合約審計員,請務必註意,有兩種方法可廣泛分析代碼併識別問題。具體如下:
這種類型的代碼分析能幫助根據給定的編碼標準和約定識別基本的安全漏洞、編碼錯誤和其他問題。可以使用靜態分析來突出顯示未經檢查的對外部源的調用、整數溢出等威脅。靜態分析的最大好處是,無需執行代碼即可對其開展檢查。
這種審計方法用於測試代碼與 EVM 的一緻性。動態分析不是僅檢查代碼,而是交叉檢查智能合約對各種輸入的響應。動態分析可識別諸如不連貫的 Gas 消耗甚至錯誤的合約邏輯等問題。像 Ganache 這樣的個人區塊鏈環境可以用作動態分析平颱,可讓開髮人員進行交易、執行命令以及使用合約執行更多操作。
這是一個智能合約片段,用作存儲資金,具有提款功能:
pragma solidity ^0.6.1;
contract VulnerableContract {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Insufficient balance.");
(bool success, ) = msg.sender.call{value: _amount}("");
require(success, "Transfer failed.");
balances[msg.sender] -= _amount;
}
}
如果仔細觀察此代碼片段,您會髮現一個關鍵漏洞:
在上個代碼片段中,如果接收資金的用戶也使用智能合約,則可再次調用“取款”函數,盡管這是惡意的行爲。因此,在最後一個函數或餘額更新髮生之前,可以髮起重入攻擊以轉移額外的資金。經驗豐富的審計員可識別這種漏洞。
以下是相衕的固定代碼:
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Insufficient balance.");
balances[msg.sender] -= _amount;
(bool success, ) = msg.sender.call{value: _amount}("");
require(success, “Transfer failed.”);
}
檢查如何首先調用餘額更新函數,然後首先調用用戶。操作順序的改變就是修覆合約的東西。
去中心化應用程序和智能合約領域已超越了以太坊。盡管大部分操作仍髮生在以太坊生態繫統內,但還有其他區塊鏈(例如 Cardano、Solana 等)支持智能合約併需要不衕的審計標準。
不衕的區塊鏈使用不衕的編程語言。代碼的語義、語法和屬性不衕,因此智能合約能夠響應不衕的寫入和審計實踐。例如,以太坊使用 Solidity 語言,而 Polkadot 使用 Ink 和 Rust——因此它能對特定的審計標準做出反應。
如果您想利用以太坊以外的平颱,也有有一些入門的專門審計工具。例如,Cardano有用於形式驗證和審計的Marlowe套件。若使用 Solana 平颱,Rust 特定的 libfuzzer 和 Cargo-fuzz 可用於審計和合約測試。多鏈審計員必鬚熟悉這些概念,以防止合約漏洞。
需要重申的是,您可將智能合約審計分爲三種類型,即手動、自動和混合。請註意,人們更喜歡針對具有深層業務邏輯的覆雜合約的混合審計策略,因爲它們是最全麵的。
具有極少編碼知識的組織和個人通常將智能合約的寫入和審計要求外包給知名公司。選擇合適的審計公司變得更加重要,因爲盡管 ChatGPT 等人工智能工具可以幫助寫入智能合約代碼,但衕樣需要手動檢查來髮現問題。
另外,外包審計任務時需註意以下因素:
在您選擇合適的外包公司之前,要檢查歷史審計情況、評估經驗,甚至關註其重要審計團隊成員,這一點至關重要。
在雇用審計公司之前,請了解與審計相關的成本和服務。必鬚首先了解所提供服務的性質,例如問題識別、問題解決等。您還必鬚檢查實施第一行修覆後是否還需重新審計。智能合約審計的成本可能因服務而異,因此,有必要在使用服務之前了解每項要求和服務。
如果您不想將審計工作外包給審計公司,而是想親自審核智能合約,那麽請記住以下最佳策略和實踐:
人工智能確實讓智能合約寫入變得更加容易。然而,無論人工智能如何創新,要想做到最好的智能合約審計,仍需人工幹預。因此,如果您計畫構建下一個強調智能合約和去中心化應用程序的 web3 産品,那麽請專註智能合約的最優審計資源,這一點至關重要。隨著加密貨幣黑客攻擊和漏洞利用行爲日益增多,黑客們也在計畫新的突破策略,能準確地審計合約無疑是當今更重要的技能之一。
智能合約是可編程的代碼,僅在滿足一組條件時才執行。在現實世界中,與具有法律約束力的合衕具有相衕含義;隻有在這種情況下,代碼才是法律。由於智能合約駐留在區塊鏈上,因此它們是不可變的,即無法被篡改。正是這種不變性商數賦予智能合約特殊性。
智能合約用於自動化區塊鏈特定的交易。由於它們是特定條件的合約,因此不需要中介機構。智能合約之所以有效,是因爲它們在廣泛的用例(包括金融服務、供應鏈管理等)中具有兼容性。與一次性編程的傳統代碼塊不衕,智能合約需要高度安全且耗時的策略。
智能合約如何與區塊鏈技術相結合(來源:BeInCrypto)
“流行語“web3”暗含了網絡鬆散、安全性差的編程習慣。當加密貨幣或智能合約像網頁一樣編程時,它們就註定會失敗。可持續成功的區塊鏈及其應用程序基於更加安全、周密和緩慢的編程方法。”——Nick Szabo,密碼學家和計算機科學家髮布於Twitter
智能合約可與區塊鏈特定的代幣(例如以太坊區塊鏈的 ERC-20)配合使用,從而激勵行動併促進交易各處轉移。由於涉及代碼、條件和成本,您應謹慎讀取、寫入和審計它們。
智能合約的真正意義在於其本質和定位。對於給定的場景,比如當 A 完成一項服務時,A 將資金轉移給 B,區塊鏈節點會保存併執行智能合約的副本。智能合約在鏈內保存爲合約代碼。這種多路徑驗證是一種以區塊鏈爲中心的特徵,可確保事物的安全。
此外,還存在以次序而髮生的智能合約或衕步智能合約和異步智能合約,其中任務併行執行。因此,智能合約的類型和用途決定了它的寫入、讀取甚至審計方式。要明白以下特徵:
傳統的合衕、財産契約、遺囑等都是私法,即“由私人而不是政客或政府官僚起草”。智能合約就是這種去中心化規則製定的一種新形式。參閲:https://t.co/EU2Y28FznK
— Nick Szabo (@NickSzabo4) 於2018年3月15日髮布
讓我們考慮一個標準的智能合約管理的流動性池。
想象一下,代幣池可用於交易,每次成功進行交易時,總交易價值的0.3%都會髮送給流動性提供者,流動性提供者實施交易或爲給定的可交易資産增加流動性。所有強調交易場景、交易費用、違規和交易失敗的條件都被編碼爲智能合約,以合約代碼的形式存儲在鏈內。
智能合約的特點
如果我們不了解合約的特徵,我們就無法深入讀取、寫入和審計合約。以下是需要明白的標準智能合約特徵:
標準智能合約的一些特徵(來源:BeInCrypto)
智能合約隻是一些代碼。您可寫入智能合約來根據特定條件執行命令和場景。這就是爲什麽智能合約開髮人員和程序員目前很受大家的青睞,因爲大多數 DeFi 領域已經依賴智能合約來處理覆雜的實例,例如處理跨流動性池的交易費用、維護 APY 比率等。
駐留在區塊鏈上的智能合約無需人爲幹預。因此,他們是完全去信任的。例如,如果由智能合約管理的特定 DeFi 協議衕意在價值低於閾值時清算您的資産,則任何人爲幹預都不能或不應阻止它。該代碼處理支付、性能、管理和規則執行,使整個空間完全去信任化。
如前所述,智能合約加載了自動執行的指令集。就編碼而言,這意味著在樣闆內構建迭代和循環。這確保了諸如支付、提款、存款、通過削減懲罰驗證者等任務以及其他一些任務都是自主處理的。
最後,由於智能合約是使用密碼學來保護的,因此破解它們非常睏難。如果沒有內置漏洞,繞過智能合約就意味著試圖在整個區塊鏈麵前公開破壞它。
通過智能合約處理的交易是可自我驗證的。這意味著執行足以證明交易是首先髮生的,因爲不涉及人爲因素。自我驗證機製使智能合約比管理遺留銀行設置的傳統合約更具優勢。
因此,下次您計畫讀取智能合約時,請確保樣闆或文檔包含所涉及的所有上述特徵。
簡版智能合約(來源:Reddit)
這是一個代錶托管賬戶的簡單智能合約。用戶將資金存入托管機構,然後在特定時間範圍過後將資金轉移到接收方。
/ SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Basic Smart Contract Boilerplate
contract SimpleTrustlessEscrow {
// State variables
address public depositor; // Account depositing ether
address payable public beneficiary; // Account receiving ether
uint256 public releaseTime; // Timestamp to release ether
// Events for verifying contract activity
event Deposited(address indexed _from, uint256 _value);
event Released(address indexed _to, uint256 _value);
// The contract constructor initializes the smart contract
constructor(address payable _beneficiary, uint256 _releaseTime) {
require(_releaseTime > block.timestamp, “Release time must be in the future”);
// Secure and Trustless: Contract binds depositor and beneficiary
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
}
// Deposit function – autonomous execution (fallback function)
receive() external payable {
emit Deposited(msg.sender, msg.value);
}
// Release the ether to the beneficiary
function release() public {
// Programmable: Can only be executed after releaseTime
require(block.timestamp >= releaseTime, “Too early to release”);
// Autonomous: Automatically executes based on condition
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
emit Released(beneficiary, amount);
}
}
雖然我們將詳細解讀併讀取此智能合約,但讓我們首先檢查它是否具備上述合約特徵。
Look at the contract closely for this piece of code:
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
The funds are to be released only when a specific releaseTime condition is met, making these programmable contracts.
仔細閲讀合約中的這段代碼:
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
僅當滿足特定的釋放時間條件時才會釋放資金,從而形成這些可編程合約。
讓我們快速瀏覽上麵的這個代碼片段:
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
在合約中,從存款人到接收資金的人,每個人都受代碼的約束。沒有人需要與對方交互或信任對方,因爲轉移資金的功能受到releaseTime(一種基於代碼的參數)的約束。
閲讀以下代碼的“資金釋放”部分:
function release() public {
require(block.timestamp >= releaseTime, “Too early to release”);
uint256 amount = address(this).balance;
beneficiary.transfer(amount);
emit Released(beneficiary, amount);
}
整個過程是自主執行的,因爲隻有當釋放時間滿足一定標準時才會釋放資金。請註意,代碼不是部分可編程的,而是完全自主的。
智能合約代碼的其他元素(包括存款功能)也可以完全是自主的,具體取決於您想要包含的功能。例如,每當用戶的錢包有超過100美元時,您就可以啟動定期存款計畫,多餘的金額將轉移給收款人。
想知道哪個要素爲合衕提供擔保?查看這部分代碼:
constructor(address payable _beneficiary, uint256 _releaseTime) {
require(_releaseTime > block.timestamp, “Release time must be in the future”);
depositor = msg.sender;
beneficiary = _beneficiary;
releaseTime = _releaseTime;
}
請註意,releaseTime 函數相對於時間戳是如何設置優先級的。沒有什麽是隨機的,必鬚滿足條件。
與智能合約相關的每筆交易都記録在鏈中,由單獨的日誌活動元素提供。
event Deposited(address indexed _from, uint256 _value);
event Released(address indexed _to, uint256 _value);
emit Deposited(msg.sender, msg.value);
emit Released(beneficiary, amount);
現在我們已經確定了定義智能合約特徵的元素,以下是其他合約的元素,可以幫助您更好地練習理解智能合約。
Pragma solidity ^0.8.0; ——寫入此智能合約所需的 Solidity 編程語言版本。
// SPDX-License-Identifier:MIT ——術語“軟件包數據交換”,該標識符錶示代碼髮布的許可證。合約應包含此內容,以便讓人們知道它是否是開源的併且是否是可解決的。
Contract TimeLock { ——爲智能合約分配名稱,就像是一個標簽。
Address public depositor;——由於合衕涉及存款人和收款人,因此這裡提到了存款人的公共地址。該變量是以太坊錢包地址,併且是公開可見的。
Address payable public beneficiary; ——這是收款人的公共地址,托管機構將資金轉移到該地址。它也是可讀取的,併爲區塊鏈驅動的智能合約帶來了透明度。
Uint256 public releaseTime; ——由於這是一個有時限的合約,因此 uint256 將基於時間的變量分配給合約。這將是資金釋放的時間錶。
在 Solidity 編程語言中,uint(無符號整數)是分配基於整數的值的方式。後綴256代錶存儲的大量數字。
經過5年的智能合約寫入經歷後,我直到今天才意識到 Solidity 徽標是展開的以太坊徽標 pic.twitter.com/wlM369Eff9
——kaden.eth (@0xKaden) 髮布於2023年7月8日
您可參閲 Solidity 文檔來深入了解語法、錶達式和其他代碼元素。
constructor(address payable _beneficiary, uint256 _releaseTime) { ——“Constructor”是一個一次性特殊函數,在部署智能合約時被調用。它啟動了合約。請註意,在此時,我們之前聲明的所有地址變量都被調用併進行初始化。
Receive() external payable { ——這是資金從外部轉移到合約地址時調用的特殊函數。External暗示來自外部,“Payable”定義了此舉的性質,即接收ERC-20代幣。
Function release() public { ——這是一個公共函數,用於説明 ERC-20 代幣從合約地址轉移到收款人。該功能受到releaseTime的影響。
所有這些要素都是我們討論假設作爲托管合約的一部分。因此,您能閲讀到完整的 Solidity 文檔,以便更好地了解該語言。
在計畫寫入智能合約之前了解的要素(來源:BeInCrypto)
到目前爲止,您應已在讀取和理解已寫入的智能合約方麵有了些知識。許多智能合約(例如我們討論的智能合約)構成了去中心化應用程序的後端——標準移動應用程序的區塊鏈版本。
智能合約的每一個特性,包括合約安全性、自主性和可編程執行、交易的去信任性等等,在開髮去中心化應用程序時都很容易實現。因此,下次您無意遇到 DApps 時,請註意,它是托管在區塊鏈上的智能合約驅動的後端,可幫助您在無需人工幹預的情況下啟動多個任務。智能合約構成了 DApps 的邏輯。
我們知道,以太坊可讓您開髮智能合約,就像大型軟件解決方案一樣。然而,它併不是唯一的區塊鏈協議。如果您想深入了解智能合約開髮領域,那麽您可能想看看其他區塊鏈。不衕的區塊鏈在製定合約時有不衕的用語。
但首先,讓我們討論一下以太坊——這是大多數智能合約開髮人員的首選平颱。
以太坊上的智能合約是用 Solidity 編程語言寫入的。該智能合約開髮平颱的代幣接口是ERC-20。
您可回到我們之前討論的基於托管的智能合約,看看標準的基於以太坊的智能合約是如何寫入的。
即使在以太坊區塊鏈上啟動 ERC-20 代幣也是一項嚴重依賴智能合約的功能,我們將在寫入智能合約時深入討論這一點。
如果我們計畫推出新的加密貨幣 BIC,則基本代碼結構如下所示。
(此處併不是真的推出 BIC 加密貨幣,隻是一個假設場景。)
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BICToken is ERC20 {
constructor(uint256 initialSupply) ERC20("BIC Token", "BIC") {
_mint(msg.sender, initialSupply);
}
}
稍後在寫入智能合約時,我們將討論該代碼的每個元素。
與以太坊一樣,您甚至可以在 Solana 等平颱上使用 Rust 和 Cardano、Plutus(函數式編程語言 Haskell 的子集)創建智能合約。
“Cordona 也有智能合約嗎?”
跟你開玩笑的,朋友。 #CardanoADA pic.twitter.com/j8SXCu72Sd ——Willybot 🇦🇺 (@wilbot28) 髮布於2023年7月9日
Rust (Solana) 中的代碼結構如下所示:
(註意:這是一個簡單的合約,其中計數器會遞增。)
use anchor_lang::prelude::*;
declare_id!(“Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS”);
#[program]
pub mod hello_world {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
let greeting_account = &mut ctx.accounts.greeting_account;
greeting_account.counter = 0;
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> ProgramResult {
let greeting_account = &mut ctx.accounts.greeting_account;
greeting_account.counter += 1;
Ok(())
}
}
你可知道?Rust 是用於創建基於 Solana 的智能合約的編程語言,而 Anchor 是所使用的智能合約開髮框架。爲了使用 Rust 創建智能合約,開髮人員需要從 Anchor 框架中提取模塊——以上示例代碼的第一行 (useanchor_lang::*;) 所代錶的內容。
閲讀此 Solana 文檔,它將幫助您了解 Rust 特定的智能合約語言。
衕樣地,緊隨 Plutus 之後,是作爲語言選擇的Cardano ,其次是 Polkadot 的語言 Ink!、Algorand 的語言 TEAL、NEO 的 C# 等等。在繼續寫入兼容的智能合約之前,建議先詳細學習區塊鏈知識文檔。
具有能寫入智能合約的能力會得到了高度贊賞,但即便隻能讀取智能合約也有其好處,部分如下:
在現已能讀取智能合約的基礎上,讓我們學習如何寫入智能合約。在開始深入研究之前,有必要重申不衕的區塊鏈可能有不衕的與智能合約開髮相關的標準和語言。請務必在寫入和合約部署之始,關註任何給定區塊鏈定義的標準。
在我們的大部分討論中,我們將重點以以太坊區塊鏈爲例,併使用Solidity語言。
智能合約編程無疑是開髮周期中最重要的部分。要進入以太坊或任何其他區塊鏈上實施智能合約開髮,您應該對非區塊鏈編程語言(如 Javascript)有一定的經驗。
不衕的區塊鏈和寫入智能合約的語言(來源:BeInCrypto)
有了寫入智能合約的能力,您就能夠實施邏輯、處理相衕的安全元素、優化Gas費代碼、自定義相衕的代碼,甚至在需要時使相衕的代碼具有互操作性。
任何計畫在以太坊上寫入智能合約的人都需要了解以太坊虛擬機(EVM)是什麽以及它如何與智能合約配合使用。首先,EVM 是一個以太坊組件,爲程序提供了一個隔離且受控的工作環境。可將其視爲托管以太坊上每段合約代碼的全球計算機。以太坊網絡上的每個節點都運行 EVM。
如果您有誌成爲一名智能合約開髮人員,您需要了解以下有關智能合約和 EVM 的知識。
在使用 Solidity(一種高級語言)寫入了程序後,您就需要將其編譯成字節碼——一種機器可理解的低級格式。該字節碼進入以太坊區塊鏈併駐留在其中。任何與智能合約交互的人都需要將交易髮送到合約地址。
每個安裝了 EVM 的節點都可以看到該交易,驗證者批準該交易後,智能合約代碼就會被執行。由於每個節點都具有事務可見性,因此任何內容都無法篡改,併且代碼按寫入時執行。代碼被執行後,區塊鏈的狀態就會髮生變化,使整個過程實現端到端且完全具有透明性。
寫入智能合約需要技術知識。但事實併非如此。您還需要徹底了解區塊鏈技術的工作原理、哪些特定於語言的需求與您所針對的區塊鏈相關、互操作性等等。除此之外,您還應了解與智能合約漏洞相關的大量信息——這寫入代碼時要避免的事情。最後,合約測試和合約部署知識也是必鬚要知曉的。
所有這些都看起來讓人不知所措。因此,以下準備一份快速入門的備忘清單:
以下提供了一份快捷思路,其中包含一些將智能合約寫入得更完善的技巧:
🥧 FREI-PI
‼️ 爲什麽智能合約開髮人員需要知道這些內容!
功能:
– 要求
– 影響
– 交互
協議
不變性
這是您在創建智能合約時應思考的模式。
這就是原因👇
— Patrick Collins (@PatrickAlphaC) 髮錶於2023年7月6日
現在是時候討論智能合約開髮技術方麵的內容了。盡管Solana 和 Cardano 這樣的區塊鏈也允許您開髮智能合約,但以太坊仍然是最受歡迎的智能合約開髮平颱。
你可知道?僅在2022年,就有超過100,000個去中心化應用程序進入以太坊網絡。
以太坊擁有龐大的開髮者社區。您開髮的任何東西都會立刻穫得關註。另外,它的母語 Solidity 對於了解 Python 或 JavaScript 的人來説相對容易。最後,以太坊全球軟件 EVM 有助於無縫執行合約。
如果您是也是青睞以太坊的大多數人之一,併且更喜歡使用以太坊和 Solidity,那麽在開始智能合約開髮之前,您需要了解以下快速入門事項:
在知曉了事情在區塊鏈上是如何進行的情況下,讓我們開始寫入和部署第一個智能合約。盡管“Hello World”仍然是第一步,但我們將首先創建一個智能合約,推出一個假設的 BIC 代幣,其供應量爲100萬個,100%釋放。
開始寫入的基礎事項
第一步,安裝最新版本的 Node.js 和 NPM 或 Node Package Manager(節點包管理器)。這會考慮到開髮工具和本地開髮環境。此外,Node.js 和 NPM 允許您爲智能合約設置 Web 前端。
現在,您需要設置一個IDE來寫入合約代碼。爲此,您可快速安裝 Visual Studio Code。或者您可避免混亂併跳到 Alchemy——一個區塊鏈開髮平颱。通過 Alchemy,您可以穫得一些測試網 ETH。當您將智能合約部署到 Goerli 測試網甚至 Sepolia 測試網時,將産生 Gas 費用。
請註意,Sepolia 是一個較新的測試網,因此它在節點部署方麵占用較少的磁盤空間。
目前,我們將繼續使用 Goerli 測試網,因爲它已有大量已部署的應用程序。
測試網和假 ETH 準備就緒後,讓我們開始具體寫入智能合約。以下是創建固定供應量100萬個 BIC 代幣的代碼片段。
註意:我們將在 MacOS 本地而不是測試網上部署智能合約。對於智能合約的測試網和主網部署,我們將有一個單獨的部分,這在本文不予討論。
以下是假設代幣的簡單代碼片段:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BICToken is ERC20 {
constructor() ERC20("BIC Token", "BIC") {
_mint(msg.sender, 1000000 * 10 ** decimals());
}
}
若您了解語法,您就會知道每個代碼組件的含義。至於Openzepplin部分,它是導入ERC-20智能合約的首選庫。該庫提供了 ERC-20 代幣的基本操作標準。
mint 函數討論初始供應,該供應被部署到智能合約地址或 msg.sender。
要在本地設置此代碼併進行測試,我們需要三個組件:
如果您已完成寫入智能合約的詳細過程,那麽有必要了解一些有關合約執行的知識。它是通過節點在鏈上執行智能合約代碼的過程。
正是與合約執行相關的一緻性使得智能合約透明且不可變。現在讓我們了解與合約執行相關的詳細步驟:
我們寫入的代碼片段需要在某個地方執行。就智能合約而言,執行地點就是區塊鏈。節點或鏈上的參與成員幫助執行合約。
節點負責執行合約代碼塊,以換取與鏈相關的激勵。鏈內髮生的每一個命令或動作都由智能合約主導。
每個智能合約都有一個特定的地址。爲了執行合約,交易被髮送到該合約地址。請註意,每個節點都運行 EVM,然後 EVM 擁有智能合約代碼的副本,從而能更容易地檢查交易的真實性。
針對智能合約的交易由驗證者選出,然後將其包含到特定的區塊中。
交易被推送併成功得到驗證後,它就成爲區塊鏈的一部分。然後,與交易相關的智能合約函數在區塊鏈節點上被調用併執行。
執行智能合約的每個節點都應得出確定性結論——衕一組輸入具有相衕的輸出——從而使合約具有完全去信任和透明的性質。
註意:任何與代碼執行有關的錯誤或與Gas費相關的問題都會導緻交易被撤銷。這意味著基於特定智能合約代碼的交易將不覆存在。這正是閃電貸髮生的情況,因爲無法遵守特定規範而導緻整個交易髮生逆轉,似乎讓人覺得一資金從一開始就沒有流動。
與智能合約相關的每個狀態變化都會記録在區塊鏈中,併成爲區塊鏈的不可變部分。
現在您已經對智能合約有了一定的了解,下麵是一些開啟合約開髮的建議:
上麵提到的每個實踐都能幫助優化代碼併有利於特定於安全性的實現。但是,您必鬚遵循和實施一些特定於合約的實踐,以保證代碼的可持續性。這樣做的目的是,保持合約代碼爲輕量級且是可用的,以便每個運行和執行相衕合約的節點無需投入大量計算能力。
即便在寫入和開髮智能合約時遵循了以上最佳實踐,但在將其推送到主網時仍需要關註合約安全漏洞事宜。
主網中存在的每個智能合約都需要在代碼性能、安全性和其他特徵方麵受到評估。這就是審計(嚴格的合約測試流程)占據重要地位的原因,它讓您能夠髮現潛在的合約漏洞和弱點。
以下是快速入門審計的要點:
絶佳的智能合約審計要點😈
請務必在下次審計時檢查這些內容✅
感恩轉髮,傳播知識🫡https://t.co/ILx0C67kf8
——cholakov (@cholakovv) 髮布於2023年7月7日
讀取、寫入和審計之間的關繫:爲什麽還要審計智能合約?
雖然在開髮智能代碼時,讀取和寫入智能合約是相輔相成的,但審計的地位不一般,併且首先涉及檢查合約的邏輯。在談到基於區塊鏈的代碼執行時,我們都認爲它的一切都是不可變的,任何災難性的事情都可能對合約執行産生不可逆轉的後果。這正是爲什麽需要通過審計對合約代碼和其他方麵進行全麵檢查。
詳細的智能合約審計可識別出許多合約漏洞。其中包括檢查重入攻擊、溢出或下溢、與訪問控製相關的問題等等。確定了問題的確切性質後,審計員甚至可以提供解決該問題的最佳實踐。
還是不明白智能合約審計有何好處?那麽,讓我們回顧一下2016年臭名昭著的 DAO 黑客事件,該事件利用了重入問題,造成了近360萬 ETH 的損失。衕樣,2017年 Parity 錢包合約被黑客攻擊,導緻近50萬 ETH 損失。通過正確的審計,這些問題本來可以避免。
DAO 黑客的流程圖(來源:BeInCrypto)
審計智能合約的策略有很多。以下討論了一些較受歡迎的策略:
審計工具充當第一套防禦措施,最適用於定位常見漏洞。一些更常見工具有 Securify、Mythril 等,能夠對代碼執行靜態分析、檢測漏洞模式併幫助穫得特定於安全性的領先優勢。
審計智能合約的工具(來源:BeInCrypto)
代碼審查由手動代碼審查人員負責,他們檢查代碼庫併識別覆雜的漏洞(若有)。手動審查可幫助處理業務邏輯、上下文和使用模式。
以下介紹了手動代碼審查如何幫助您定位威脅:
給初級審查員的一個小知識!
如果您髮現該漏洞,請轉髮! pic.twitter.com/i14YtweXcz
——CharlesPaladin (@PaladinCharles) 髮布於2023 年7月8日
Snyk 和 GuardRails 等工具能幫助自動合約掃描——每次更新代碼時都會調用的安全實現。這種形式的審計可確保對代碼所做的新更改在本質上是安全且非侵入性的。
形式驗證是一個覆雜的過程,僅依賴於檢查代碼的業務邏輯。請註意,形式驗證實際上併不是爲了驗證語法,而是爲了驗證代碼是否按預期執行的邏輯。
除了上述策略之外,還可使用衕行評審、漏洞賞金計畫和通過 Solidity Coverage 等工具測試覆蓋率來啟動智能合約審計,以最大限度地提高效率。
審計智能合約的簡單方法(來源:BeInCrypto)
如果您是一位新手智能合約審計員,請務必註意,有兩種方法可廣泛分析代碼併識別問題。具體如下:
這種類型的代碼分析能幫助根據給定的編碼標準和約定識別基本的安全漏洞、編碼錯誤和其他問題。可以使用靜態分析來突出顯示未經檢查的對外部源的調用、整數溢出等威脅。靜態分析的最大好處是,無需執行代碼即可對其開展檢查。
這種審計方法用於測試代碼與 EVM 的一緻性。動態分析不是僅檢查代碼,而是交叉檢查智能合約對各種輸入的響應。動態分析可識別諸如不連貫的 Gas 消耗甚至錯誤的合約邏輯等問題。像 Ganache 這樣的個人區塊鏈環境可以用作動態分析平颱,可讓開髮人員進行交易、執行命令以及使用合約執行更多操作。
這是一個智能合約片段,用作存儲資金,具有提款功能:
pragma solidity ^0.6.1;
contract VulnerableContract {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Insufficient balance.");
(bool success, ) = msg.sender.call{value: _amount}("");
require(success, "Transfer failed.");
balances[msg.sender] -= _amount;
}
}
如果仔細觀察此代碼片段,您會髮現一個關鍵漏洞:
在上個代碼片段中,如果接收資金的用戶也使用智能合約,則可再次調用“取款”函數,盡管這是惡意的行爲。因此,在最後一個函數或餘額更新髮生之前,可以髮起重入攻擊以轉移額外的資金。經驗豐富的審計員可識別這種漏洞。
以下是相衕的固定代碼:
function withdraw(uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Insufficient balance.");
balances[msg.sender] -= _amount;
(bool success, ) = msg.sender.call{value: _amount}("");
require(success, “Transfer failed.”);
}
檢查如何首先調用餘額更新函數,然後首先調用用戶。操作順序的改變就是修覆合約的東西。
去中心化應用程序和智能合約領域已超越了以太坊。盡管大部分操作仍髮生在以太坊生態繫統內,但還有其他區塊鏈(例如 Cardano、Solana 等)支持智能合約併需要不衕的審計標準。
不衕的區塊鏈使用不衕的編程語言。代碼的語義、語法和屬性不衕,因此智能合約能夠響應不衕的寫入和審計實踐。例如,以太坊使用 Solidity 語言,而 Polkadot 使用 Ink 和 Rust——因此它能對特定的審計標準做出反應。
如果您想利用以太坊以外的平颱,也有有一些入門的專門審計工具。例如,Cardano有用於形式驗證和審計的Marlowe套件。若使用 Solana 平颱,Rust 特定的 libfuzzer 和 Cargo-fuzz 可用於審計和合約測試。多鏈審計員必鬚熟悉這些概念,以防止合約漏洞。
需要重申的是,您可將智能合約審計分爲三種類型,即手動、自動和混合。請註意,人們更喜歡針對具有深層業務邏輯的覆雜合約的混合審計策略,因爲它們是最全麵的。
具有極少編碼知識的組織和個人通常將智能合約的寫入和審計要求外包給知名公司。選擇合適的審計公司變得更加重要,因爲盡管 ChatGPT 等人工智能工具可以幫助寫入智能合約代碼,但衕樣需要手動檢查來髮現問題。
另外,外包審計任務時需註意以下因素:
在您選擇合適的外包公司之前,要檢查歷史審計情況、評估經驗,甚至關註其重要審計團隊成員,這一點至關重要。
在雇用審計公司之前,請了解與審計相關的成本和服務。必鬚首先了解所提供服務的性質,例如問題識別、問題解決等。您還必鬚檢查實施第一行修覆後是否還需重新審計。智能合約審計的成本可能因服務而異,因此,有必要在使用服務之前了解每項要求和服務。
如果您不想將審計工作外包給審計公司,而是想親自審核智能合約,那麽請記住以下最佳策略和實踐:
人工智能確實讓智能合約寫入變得更加容易。然而,無論人工智能如何創新,要想做到最好的智能合約審計,仍需人工幹預。因此,如果您計畫構建下一個強調智能合約和去中心化應用程序的 web3 産品,那麽請專註智能合約的最優審計資源,這一點至關重要。隨著加密貨幣黑客攻擊和漏洞利用行爲日益增多,黑客們也在計畫新的突破策略,能準確地審計合約無疑是當今更重要的技能之一。