許多正在學習如何編寫智能合約的程序員將學習Solidity語言。有豐富的在線教程和書籍資源,將教我們關於Solidity的內容。當與Truffle框架相結合時,Solidity形成了開發智能合約的“殺手”組合。幾乎所有存在於以太坊區塊鏈上的智能合約都是用Solidity編程語言編寫的。

在本文中,我們將探討如何用Vyper編程語言編寫智能合約。

主題

介紹設置環境使用Vyper創建智能合約將智能合約部署到Ganache與智能合約交互與其他智能合約交互以編程方式編譯代碼

介紹

Vyper是什麼?

Vyper是一種面向合約的python編程語言,以以太坊虛擬機(EVM)為目標。 Vyper有非常簡單/可理解的語法:Vyper的原則之一是使開發人員幾乎不可能編寫具有誤導性的程序。

為什麼要用Vyper ?

安全性:在Vyper中構建安全的智能合約應該是可能的。語言和編譯器的簡單性:語言和編譯器實現應該力求簡單。可審核性:Vyper代碼應該最大限度地讓人可讀。此外,編寫具有誤導性的代碼應該是最困難的。讀者的可讀性比作者的可讀性更重要,對於沒有使用Vyper經驗的讀者(以及一般沒有編程經驗的讀者)來說,簡單性尤其重要。

因此,Vyper提供了以下特性:

邊界和溢出檢查:對數組訪問和算術。支持有符號整數和十進制定點數可判定性:可以計算任何Vyper函數調用的gas消耗的精確上限。強類型小而易懂的編譯器代碼對純函數的有限支持:任何標記為常量的東西都不允許改變狀態。

設置環境

Vyper需要Python 3.6軟件。所以,如果我們沒有安裝Python 3.6軟件,我們必須安裝它,然後按照下面的步驟進行:

$ python3 -m pip install --user virtualenv $ pip install vyper $ virtualenv -p python3.6 vyper-venv $ source vyper-venv/bin/activate (vyper-venv) $ pip install vyper (vyper-venv) $ vyper - -version

使用Vyper創建智能合約

現在讓我們用Vyper創建一個智能合約。首先,我們將創建一個擴展名為.vy的文件,並將其命名為hello.vy,如下:

name: public(String[24])@externaldef __init__(): self.name = "Satoshi Nakamoto" @externaldef change_name(new_name: String[24]): self.name = new_name @externaldef say_hello() -> String[32 ]: return concat("Hello, ", self.name)

下面是編譯vyper文件的方法:

(vyper-venv) $ vyper hello.vy

由此,我們將得到以下輸出:

這是智能合約的字節碼。要部署智能合約,就需要字節碼,但要訪問智能合約,需要abi。如何得到abi呢?可以通過以下命令來實現:

(vyper-venv) $ vyper -f json hello.vy

由此,我們將獲得以下輸出:

如果我們想在一個編譯過程中同時得到abi和字節碼,可以在編譯過程中合併這兩個標誌,如下所示:

(vyper-venv) $ vyper -f json,bytecode hello.vy

這將給我們以下輸出:

將智能合約部署到Ganache

那麼如何將這個智能合約部署到以太坊區塊鏈中呢?有幾種方法可以做到這一點,但讓我們用一種熟悉的方法來使用Truffle:

創建一個目錄,並使用truffle init初始化它,如下所示:

$ mkdir hello_project $ cd hello_project $ truffle init

設置truffle-config.js如下所示:

module.exports = { networks: { "development": { network_id: "*", host: "127.0.0.1", port: 8545 // port at Ganache running }, } };

創建一個構建目錄,如下所示:

$ mkdir -p build/contracts $ cd build/contracts

然後創建一個Hello.json文件,如下所示:

{“abi”: ”bytecode”: }

然後用編譯過程的abi或json輸出填充abi字段,用編譯過程的字節碼輸出填充字節碼字段。需要用雙引號將字節碼值括起來。不要忘記在abi字段和字節碼字段之間放一個逗號。這會給我們一些類似於下面的東西:

{ "abi": [ { "stateMutability": "nonpayable", "type": "constructor", "inputs": [], "outputs": [] }, { "stateMutability": "nonpayable", "type" : "function", "name": "change_name", "inputs": [ { "name": "new_name", "type": "string" } ], "outputs": [], "gas": 74063 } , { "stateMutability": "nonpayable", "type": "function", "name": "say_hello", "inputs": [], "outputs": [ { "name": "", "type": "string" } ], "gas": 14923 }, { "stateMutability": "view", "type": "function", "name": "name", "inputs": [], "outputs": [ { "name": "", "type": "string" } ], "gas": 10538 } ], "bytecode": ""

然後我們可以通過在migrations/2_deploy_hello.js中創建一個新文件來創建一個遷移文件來部署這個智能合約,如下所示:

var Hello = artifacts.require("Hello");module.exports = function(deployer){ deployer.deploy(Hello); };

一切準備就緒後,啟動Ganache!

然後,在hello_project目錄中,我們可以運行遷移過程,如下所示:

$ truffle migrate

我們會看到類似如下的內容:

我們用Vyper編寫的智能合約已經部署到Ganache。我們的智能合約地址如下:

0x4ab3935df0e224771663984f3617f1a78bea4e8d

與智能合約交互

正如我們之前所做的,我們可以使用Truffle控制台與我們的智能合約進行交互,如下所示:

$ truffle console

我們的智能合約總是被命名為Contract。我們可以使用以下語句訪問智能合約:

truffle(development)> Contract.at("0x4AB3935Df0E224771663984f3617F1a78beA4E8D")

我們會得到一個很長的輸出,我們可以看到abi,字節碼,等等,如下面的截圖所示:

讓我們用下面的語句來看看智能合約的name變量的值:

truffle(development)> Contract.at(“0x4AB3935Df0E224771663984f3617F1a78beA4E8D”).then(function(instance){return instance.name.call(); }); "Satoshi Nakamoto"

讓我們將名稱更改如下:

truffle(development)> Contract.at(“0x4AB3935Df0E224771663984f3617F1a78beA4E8D”).then(function(instance) { return instance.change_name(“Vitalik Buterin”), { from: “0xb28Fc17791bf66719FBFCc65846B01Fe2726e9E2” } });

from字段中的值來自Ganache中的一個帳戶。我們只需查看Ganache 窗口並選擇自己喜歡的任何帳戶。

輸出:

{from: " 0xb28Fc17791bf66719FBFCc65846B01Fe2726e9E2 "}

改名了嗎?讓我們找出答案。執行如下命令:

truffle(development)> Contract.at(“0x4AB3935Df0E224771663984f3617F1a78beA4E8D”).then(function(instance){return instance.name.call(); });'Vitalik Buterin'

與其他智能合約交互

我們的智能合約可以與區塊鏈上的其他智能合約交互。

地址數據類型不僅適用於普通賬戶,也適用於智能合約賬戶。所以,一個智能合約可以通過捐贈智能合約將以太坊捐獻給我們的受贈人!

重啟我們的Ganache。還記得hello.vy文件嗎?我們想使用自定義名稱部署我們的Hello 智能合約。

我們的遷移文件migrations/2_deploy_hello.js仍然相同,如下代碼所示:

var Hello = artifacts.require("Hello"); module.exports = function(deployer){ deployer.deploy(Hello); };

再次編譯hello.vy文件以獲取接口和字節碼。打開我們的合約JSON 文件,

build/contracts/Hello.json文件。刪除所有內容並替換為以下代碼:

{ "contractName": "Hello", "abi": , "bytecode": " "}

我們必須為智能合約指定一個名稱,因為這一次,我們將部署兩個智能合約。如果我們不給我們的智能合約一個名稱,它將有一個默認名稱,Contract。如果我們只想部署一個智能合約,這不是問題。

然後,對於我們的donation.vy,對其進行編輯,並添加以下代碼行:

struct DonaturDetail: sum: uint256 name: String[100] time: uint256interface Hello(): def say_hello() -> Bytes[32]:viewdonatur_details: public(HashMap[(address, DonaturDetail)])donaturs: public(address[10 ])donatee: public(address)index: int128@externaldef __init__(): self.donatee = msg.sender@payable@externaldef donate(name: String[100]): assert msg.value >= as_wei_value(1, "ether ") assert self.index < 10 self.donatur_details[msg.sender] = DonaturDetail({ sum: msg.value, name: name, time: block.timestamp }) self.donaturs[self.index] = msg.sender self .index += 1@externaldef withdraw_donation(): assert msg.sender == self.donatee send(self.donatee, self.balance)@externaldef donation_smart_contract_call_hello_smart_contract_method(smart_contract_address: address) -> Bytes[32]: return Hello(smart_contract_address) .say_hello()

使用下面的代碼,為我們的Donation智能合約創建另一個遷移文件migrations/3_deploy_donation.js:

var Donation = artifacts.require("Donation"); module.exports = function(deployer) { deployer.deploy(Donation); };

編譯donation.vy並獲取智能合約的接口和字節碼。然後,使用以下代碼,為我們的捐贈智能合約創建另一個合約JSON 文件build/contracts/Donation.json:

{ "contractName": "Donation", "abi": , "bytecode": " "}

運行遷移。我們可能需要使用——reset,如下所示:

$ truffle migrate --reset

我們將得到以下輸出:

注意Donation智能合約“0x25aFF89B8a72aB4Ba6F4C831f5B1375f9BCe76A9”和Hello智能合約“0x772138489eD34095FBA6a0Af70d3C9115813CFcA”的地址。可能會有所不同。

按如下方式運行Truffle 控制台:

$ truffle console

現在我們的智能合約不再孤單,如下代碼所示:

function(instance) {return instance.donation_smart_contract_call_hello_smart_contract_method.call(" 0x772138489eD34095FBA6a0Af70d3C9115813CFcA ");});

輸出:

“0x48656c6c6f2c205361746f736869204e616b616d6f746f”

以編程方式編譯代碼

我們可以創建一個腳本來編譯Vyper代碼,而不是使用命令行實用程序。確保位於包含Hello.vy和的同一目錄中donation.vy。創建一個名為的腳本compiler.vy,如下:

import vyperimport os, json# You need a Vyper file, the name that you want to give to your smart contract, and the output JSON file. The following code will do this task:filename = "hello.vy"contract_name = "Hello" contract_json_file = open("Hello.json", "w")# Use the following lines of code to get the content of the Vyper file:with open(filename, "r") as f: content = f.read()# Then you create a dictionary object where the key is a path to your Vyper file and the value is the content of the Vyper file, as follows:current_directory = os.curdirsmart_contract = {}smart_contract[current_directory] = content# To compile the Vyper code , all you need to do is use the compile_codes method from the vyper module, as follows:format = ["abi", "bytecode"]compiled_code = vyper.compile_codes(smart_contract, format, "dict")smart_contract_json = { "contractName" : contract_name, "abi": compiled_code[current_directory]["abi"], "bytecode": compiled_code[current_directory]["bytecode"]}# The last code is used to write the result to an output JSON file:json.dump (smart_contract_json, contract_json_file)contract_json_file.close()

如果我們使用以下命令執行這個腳本,我們將獲得一個Hello.json可與Truffle 一起使用的文件,如下代碼所示:

(vyper-venv) $ python compiler.vy

總結

在本文中,我們了解瞭如何使用Vyper編程語言編寫智能合約。首先,我們安裝了Vyper編譯器。然後我們開發了一個智能合約。

通過這樣做,我們了解了Vyper編程語言的大部分特性,包括函數裝飾器、初始化函數和函數權限修飾符。

還有一些數據類型,如地址、整數、時間戳、映射、數組和字節數組(字符串)。我們學習瞭如何將Vyper源代碼編譯為智能合約,然後使用Truffle工具將其部署到Ganache中。我們也通過Truffle控制台與智能合約進行交互。

Source:https://medium.com/better-programming/implementing-smart-contracts-using-vyper-a-python-approach-95f9299e64d8