【BlockChain】 呼叫智慧合約的方法
前言
本文主要講呼叫已部署的智慧合約的幾種方法,以 ofollow,noindex">Capture The Ether 網站為例,呼叫測試鏈為Ropsten。
使用remix-ide
remix-ide 是 Browser-Only Solidity IDE and Runtime Environment
。能夠幫助我們除錯合約程式碼。在本地搭建好後可以直接使用瀏覽器開啟訪問。
這裡以CTE裡的一道題為 例子 。
程式碼如下:
pragma solidity ^0.4.21; contract CallMeChallenge { bool public isComplete = false; function callme() public { isComplete = true; } }
目的是呼叫ropsten裡的callme。
點選開始後會得到一個合約地址:
我們把程式碼放到remix-ide裡,並進行編譯
在 Run
標籤欄裡,填好所需的資訊,如環境,合約地址,最後能看到在ropsten裡部署好的合約:
點選 callme
,在console裡會輸出log資訊,並給出是否成功。
此時,回到題目,點選檢查。即可通過這關。
使用remix-ide只能滿足簡單的互動要求,如果互動頻繁,則可以選擇更為靈活的程式碼實現。
web3py
web3py是web3.js在python上的實現,可以使用pip安裝:
pip install web3
一個使用web3py簡單互動的程式碼如下:
# -*- coding:utf-8 -*- from web3 import Web3, HTTPProvider from web3.contract import ConciseContract from web3.eth import Eth false = False true = True config = { "abi": [ { "constant": false, "inputs": [], "name": "callme", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "isComplete", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" } ], "address": "0x1933fEa88E2295e7b7A5523A86CE69742794DaA8" # 合約地址 } INFURA_API_KEY="your_key" ROPSTEN_URL = "https://ropsten.infura.io/%s" %INFURA_API_KEY web3 = Web3(HTTPProvider(ROPSTEN_URL)) contract_instance = web3.eth.contract(address=config['address'], abi=config['abi']) MY_ADDR = "0x901B1bDE..."# 你的地址 PRIV_KEY = "0x1dc7..."# 你的私鑰 def SendTxn(txn): signed_txn = web3.eth.account.signTransaction(txn, private_key=PRIV_KEY) res = web3.eth.sendRawTransaction(signed_txn.rawTransaction).hex() txn_receipt = web3.eth.waitForTransactionReceipt(res) # print(res) return txn_receipt txn = contract_instance.functions.callme().buildTransaction( { 'chainId': 3,#ropsten, 1 for main 'nonce': web3.eth.getTransactionCount(MY_ADDR), 'gas': 7600000, 'value':Web3.toWei(0,'ether'), 'gasPrice': web3.eth.gasPrice, } ) print(SendTxn(txn))
要例項化一個合約,需要 abi
和 合約地址
兩個引數,abi可以在remix-ide裡獲取到。
另外,使用web3的過程中我們需要連線到以太坊節點,如 HTTPProvider
。如果自己本地沒有搭建好節點,那麼可以使用第三方提供的節點,如 infura 。註冊好後可以得到一個app key,使用該key就能連入infura提供的節點。
例項化contract以後我們可以使用 contract_instance.functions.callme()
的方法呼叫合約內的函式。因為我們需要實際改變ropsten鏈的值,所以我們需要建立一個交易,完成對ropsten的通訊,所以還需呼叫 buildTransaction
方法。最後把簽完名的交易塊傳送到ropsten鏈上。
web3.js
web3.js是官方提供的庫。其呼叫程式碼如下:
let Web3 = require("web3"); let Tx = require('ethereumjs-tx'); // 合約地址 let contractAddress = "0x799Caa8d82d70296f1eA4992B76553ABD72da9B1"; // 建立web3物件 let web3 = new Web3(); // 連線到 ropsten 測試節點 let INFURA_API_KEY="************" let ROPSTEN_URL = "https://ropsten.infura.io/" + INFURA_API_KEY web3.setProvider(new Web3.providers.HttpProvider(ROPSTEN_URL)) let fromAddress = "0x901B1bDE..."; let count = web3.eth.getTransactionCount(fromAddress); let gasPrice = web3.eth.gasPrice; let gasLimit = 90000; let rawTransaction = { "from": fromAddress, "nonce": web3.toHex(count), "gasPrice": web3.toHex(gasPrice), "gasLimit": web3.toHex(gasLimit), "to": contractAddress, "value": "0x0", "data": "0xa3c8e393", }; // 讀取私鑰,這裡不包含‘0x’兩個字元 let privKey = new Buffer.from('1dc72....', 'hex'); let tx = new Tx(rawTransaction); // 用私鑰簽名交易資訊 tx.sign(privKey); let serializedTx = tx.serialize(); // 傳送交易 web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) { if (!err) console.log(hash); else console.log(err); });
如上,這裡我們要重點關注 rawTransaction
裡的 data
段。
它是所調函式的函式宣告做keccak256(即sha3)的雜湊,並取前4個位元組組成。如果需要傳遞引數,則把需要傳遞的引數轉換成16進位制,並在前面填滿 32位元組
(64位)。然後跟函式簽名拼接而成。
相關的說明我們可以參考:
https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#examples
https://github.com/linjie-1/guigulive-operation/wiki/Ethereum%E7%9A%84%E5%90%88%E7%BA%A6ABI%E6%8B%93%E5%B1%95#abi%E7%9A%84%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8