這篇文章主要講解了“Solidity故障怎么排查”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Solidity故障怎么排查”吧!
成都創(chuàng)新互聯(lián)公司服務(wù)項目包括鹽都網(wǎng)站建設(shè)、鹽都網(wǎng)站制作、鹽都網(wǎng)頁制作以及鹽都網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,鹽都網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到鹽都省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
1、推薦編輯器
目前嘗試 Solidity 編程的最好的方式是使用 Remix(https://remix.ethereum.org/) (需要時間加載,請耐心等待)。Remix 是一個基于 Web 的 IDE,它可以讓你編寫 Solidity 智能合約,然后部署并運行該智能合約。
2、Visual Studio Extension
Microsoft Visual Studio 的 Solidity 插件,包含 Solidity 編譯器。
3、Visual Studio Code extension
Microsoft Visual Studio Code 插件,包含語法高亮和 Solidity 編譯器。
function mint(address receiver, uint amount)
1、在REMIX輸入時,地址一定要有""表示,否則amount就取不到值。
例如是mint("0xca35b7d915458ef540ade6068dfe2f44e8fa733c",101)
2、程序中,如果注釋包含中文,單步調(diào)試的位置不準(zhǔn)確。
<address>.balance (uint256):該地址有多少以太坊余額(wei為單位)
<address>.transfer(uint256 amount):發(fā)送特定數(shù)量(wei為單位)的以太坊到對應(yīng)地址,當(dāng)出現(xiàn)錯誤時會扔出異常,但不會因異常而停止。固定需要耗費2300個gas。
<address>.send(uint256 amount) returns (bool):發(fā)送特定數(shù)量(wei為單位)的以太坊到對應(yīng)地址,當(dāng)出現(xiàn)錯誤時會返回flase。固定需要耗費2300個gas。
【警告】send() 執(zhí)行有一些風(fēng)險:如果調(diào)用棧的深度超過1024或gas耗光,交易都會失敗。因此,為了保證安全,必須檢查send的返回值,如果交易失敗,會回退以太幣。如果用transfer會更好。
<address>.call(...) returns (bool):CALL的低級調(diào)用函數(shù),當(dāng)失敗時返回false。執(zhí)行需要消耗不固定的gas。
【說明】不鼓勵使用call函數(shù),后期將會被移除。調(diào)用該函數(shù)可能造成安全攻擊,詳見后期安全相關(guān)文章。
<address>.callcode(...) returns (bool):CALLCODE的低級調(diào)用函數(shù),當(dāng)失敗時返回false。執(zhí)行需要消耗不固定的gas。
不建議使用,后續(xù)版本會刪除。
<address>.delegatecall(...) returns (bool):DELEGATECALL的低級調(diào)用函數(shù),當(dāng)失敗時返回false。執(zhí)行需要消耗不固定的gas。
【說明】為了和非ABI協(xié)議的合約進行交互,可以使用call() 函數(shù), 它用來向另一個合約發(fā)送原始數(shù)據(jù),支持任何類型任意數(shù)量的參數(shù),每個參數(shù)會按規(guī)則(ABI協(xié)議)打包成32字節(jié)并一一拼接到一起。一個例外是:如果第一個參數(shù)恰好4個字節(jié),在這種情況下,會被認(rèn)為根據(jù)ABI協(xié)議定義的函數(shù)器指定的函數(shù)簽名而直接使用。如果僅想發(fā)送消息體,需要避免第一個參數(shù)是4個字節(jié)。如下面的例子:
function callfunc(address addr) returns (bool){ bytes4 methodId = bytes4(keccak256("setScore(uint256)")); return addr.call(methodId, 100); }
測試地址和地址調(diào)用代碼舉例
pragma solidity ^0.4.18; contract AddrTest{ /*event函數(shù)知識把參數(shù)信息打印在REMIX等編譯器的LOG位置區(qū),不需要函數(shù)定義。*/ event logdata(bytes data); event LogContractAddress(address exAccount, address contractAddress); uint score = 0; /*回調(diào)函數(shù),沒有函數(shù)名。任何調(diào)用不存在的函數(shù),這時被調(diào)用的合約的fallback函數(shù)會執(zhí)行。 payable:如果一個函數(shù)需要進行貨幣操作,必須要帶上payable關(guān)鍵字*/ function() payable { logdata(msg.data); } /*智能合約構(gòu)建函數(shù)*/ function AddrTest(){ LogContractAddress(msg.sender,this); } function getBalance() returns (uint) { return this.balance; } function setScore(uint s) public { score = s; } function getScore() returns ( uint){ return score; } } contract CallTest{ /*該函數(shù)有函數(shù)申明沒有實際函數(shù)內(nèi)容,在remix的value區(qū)域設(shè)置以太坊的個數(shù),調(diào)用該函數(shù)會把外部賬戶(ACCOUNT)中的 以太坊轉(zhuǎn)移到智能合約賬戶中*/ function deposit() payable { } event logSendEvent(address to, uint value); event LogContractAddress(address exAccount, address contractAddress); /*轉(zhuǎn)以太坊給目標(biāo)地址*/ function transferEther(address towho) payable { towho.transfer(10);/*單位為wei*/ logSendEvent(towho, 10); } /*不指定調(diào)用函數(shù),則調(diào)用無函數(shù)名的回調(diào)函數(shù)*/ function callNoFunc(address addr) returns (bool){ return addr.call("tinyxiong", 1234); } /*制定調(diào)用函數(shù)的方法*/ function callfunc(address addr) returns (bool){ bytes4 methodId = bytes4(keccak256("setScore(uint256)")); return addr.call(methodId, 100); } /*返回當(dāng)前合約的以太坊余額*/ function getBalance() returns (uint) { return this.balance;//0 } /*銷毀智能合約,把以太坊余額返回給當(dāng)前外部賬戶*/ function ContractSuide() { LogContractAddress(this,msg.sender); suicide(msg.sender); } }
this (current contract’s type):表示當(dāng)前合約,可以顯式的轉(zhuǎn)換為Address
selfdestruct(address recipient):destroy the current contract, sending its funds to the given Address
銷毀當(dāng)前合約,發(fā)送當(dāng)前以太坊余額到給定的地址 suicide(address recipient):
selfdestruct的別名函數(shù)
**block.blockhash(uint blockNumber) returns (bytes32): **
給定區(qū)塊的哈希—僅對最近的 256 個區(qū)塊有效而不包括當(dāng)前區(qū)塊
**block.coinbase (address): **
挖出當(dāng)前區(qū)塊的礦工地址
**block.difficulty (uint): **
當(dāng)前區(qū)塊難度
block.gaslimit (uint):
當(dāng)前區(qū)塊 gas 限額
**block.number (uint): **
當(dāng)前區(qū)塊號
block.timestamp (uint):
自 unix epoch 起始當(dāng)前區(qū)塊以秒計的時間戳
**msg.data (bytes): **
完整的 calldata
**msg.gas (uint): **
剩余 gas
msg.sender (address):
消息發(fā)送者(當(dāng)前調(diào)用)
**msg.sig (bytes4): **
calldata 的前 4 字節(jié)(也就是函數(shù)標(biāo)識符)
msg.value (uint):
隨消息發(fā)送的 wei 的數(shù)量
**now (uint): **
目前區(qū)塊時間戳(block.timestamp)
**tx.gasprice (uint): **
交易的 gas 價格
**tx.origin (address): **
交易發(fā)起者(完全的調(diào)用鏈)
注解對于每一個外部函數(shù)調(diào)用,包括 msg.sender 和 msg.value 在內(nèi)所有 msg 成員的值都會變化。這里包括對庫函數(shù)的調(diào)用。
注解不要依賴 block.timestamp、 now 和 block.blockhash 產(chǎn)生隨機數(shù),除非你知道自己在做什么。
時間戳和區(qū)塊哈希在一定程度上都可能受到挖礦礦工影響。例如,挖礦社區(qū)中的惡意礦工可以用某個給定的哈希來運行賭場合約的 payout 函數(shù),而如果他們沒收到錢,還可以用一個不同的哈希重新嘗試。 當(dāng)前區(qū)塊的時間戳必須嚴(yán)格大于最后一個區(qū)塊的時間戳,但這里唯一能確保的只是它會是在權(quán)威鏈上的兩個連續(xù)區(qū)塊的時間戳之間的數(shù)值。
注解基于可擴展因素,區(qū)塊哈希不是對所有區(qū)塊都有效。你僅僅可以訪問最近 256 個區(qū)塊的哈希,其余的哈希均為零。
assert(bool condition):如果條件不滿足就拋出—用于內(nèi)部錯誤。
require(bool condition):如果條件不滿足就拋掉—用于輸入或者外部組件引起的錯誤。
revert():終止運行并恢復(fù)狀態(tài)變動。
addmod(uint x, uint y, uint k) returns (uint):計算 (x + y) % k,加法會在任意精度下執(zhí)行,并且加法的結(jié)果即使超過 2**256 也不會被截取。從 0.5.0 版本的編譯器開始會加入對 k != 0 的校驗(assert)。
mulmod(uint x, uint y, uint k) returns (uint):計算 (x * y) % k,乘法會在任意精度下執(zhí)行,并且乘法的結(jié)果即使超過 2**256 也不會被截取。從 0.5.0 版本的編譯器開始會加入對 k != 0 的校驗(assert)。
keccak256(...) returns (bytes32):計算 (tightly packed) arguments 的 Ethereum-SHA-3 (Keccak-256)哈希。
sha256(...) returns (bytes32):計算 (tightly packed) arguments 的 SHA-256 哈希。
sha3(...) returns (bytes32):等價于 keccak256。
ripemd160(...) returns (bytes20):計算 (tightly packed) arguments 的 RIPEMD-160 哈希。
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) :利用橢圓曲線簽名恢復(fù)與公鑰相關(guān)的地址,錯誤返回零值。(example usage:https://ethereum.stackexchange.com/q/1777/222)
上文中的“tightly packed”是指不會對參數(shù)值進行 padding 處理(就是說所有參數(shù)值的字節(jié)碼是連續(xù)存放的,譯者注),這意味著下邊這些調(diào)用都是等價的:
keccak256("ab", "c") keccak256("abc") keccak256(0x616263) keccak256(6382179) keccak256(97, 98, 99)
如果需要 padding,可以使用顯式類型轉(zhuǎn)換:keccak256("\x00\x12") 和 keccak256(uint16(0x12)) 是一樣的。
請注意,常量值會使用存儲它們所需要的最少字節(jié)數(shù)進行打包。例如:keccak256(0) == keccak256(uint8(0)),keccak256(0x12345678) == keccak256(uint32(0x12345678))。
在一個私鏈上,你很有可能碰到由于 sha256、ripemd160 或者 ecrecover 引起的 Out-of-Gas。這個原因就是他們被當(dāng)做所謂的預(yù)編譯合約而執(zhí)行,并且在第一次收到消息后這些合約才真正存在(盡管合約代碼是硬代碼)。發(fā)送到不存在的合約的消息非常昂貴,所以實際的執(zhí)行會導(dǎo)致 Out-of-Gas 錯誤。在你的合約中實際使用它們之前,給每個合約發(fā)送一點兒以太幣,比如 1 Wei。這在官方網(wǎng)絡(luò)或測試網(wǎng)絡(luò)上不是問題。
1、智能合約執(zhí)行失敗
告警描述: " Warning! Error encountered during contract execution [Out of gas] "
發(fā)生場景:執(zhí)行官網(wǎng)眾籌智能合約代碼,在給智能合約打代幣前,往智能合約地址賬戶打ETH,交易失敗,提示如下:
點擊查看信息鏈接:https://ropsten.etherscan.io/tx/0x8b4da573b36dbf7361c95a0156dfe060553874fbb4d401f989c7a4a6d539ebfa
代碼及原因分析:下面是執(zhí)行的回調(diào)函數(shù),其中“tokenReward.transfer(msg.sender, amount / price);”的意思就是把智能合約的代幣打給發(fā)送者賬號。這個賬號還沒有代幣,所以肯定會執(zhí)行失敗。
function () payable { require(!crowdsaleClosed); uint amount = msg.value; balanceOf[msg.sender] += amount; amountRaised += amount; tokenReward.transfer(msg.sender, amount / price); FundTransfer(msg.sender, amount, true); }
解決方法:先往智能合約賬號打代幣,然后打ETH,就不會執(zhí)行失敗了。
2、 REMIX+MetaMASK的場景下,調(diào)用智能合約函數(shù),提示不可知地址
告警描述:
REMIX輸出框輸出以下告警內(nèi)容: transact to Crowdsale.checkGoalReached errored: Unknown address - unable to sign transaction for this address: "0x3d7dfb80e71096f2c4ee63c42c4d849f2cbbe363"
發(fā)生場景:更換了Meta賬號后,調(diào)用之前賬號創(chuàng)建的智能合約的函數(shù)
原因分析:Remix輸出框提示未知地址:
告警描述
查看MetaMask的當(dāng)前賬號,發(fā)現(xiàn)是Account 1的賬號,所以無法執(zhí)行合約。
MetaMask的當(dāng)前賬號
解決方法:
更換MetaMask為Account8(地址為0x3D7DfB80E71096F2c4Ee63C42C4D849F2CBBE363)的賬號即可正常運行。
3、GETH安裝時出現(xiàn)異常
告警描述:GETH安裝時出現(xiàn)以下告警:
E: Failed to fetch http://101.110.118.22/ppa.launchpad.net/ethereum/ethereum/ubuntu/pool/main/e/ethereum/ethereum_1.8.10+build13740+artful_i386.deb Could not connect to 101.110.118.22:80 (101.110.118.22), connection timed out
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
發(fā)生場景:
GETH安裝,執(zhí)行以下命令出現(xiàn)。
sudo apt-get install ethereum
原因分析:
解決方法:
<1> 參考網(wǎng)上解決方案 sudo vim /etc/resolv.conf ,添加:
nameserver 8.8.8.8
然后執(zhí)行:
sudo /etc/init.d/networking restart
還是不行。
<2> 從綠地金融中心搬到家里,做相同的操作,就可以安裝成功了。 應(yīng)該是綠地金融中心的路由器做了某些配置,導(dǎo)致下載不成功。
4、問題描述模板
告警描述: 發(fā)生場景: 原因分析: 解決方法:
1).modifer函數(shù)是干什么的?
2).如何打幣回支付賬號?
3).智能合約的定時器和系統(tǒng)函數(shù)是什么?
4).當(dāng)創(chuàng)建一個智能合約時,msg.sender和this的區(qū)別?
答復(fù):msg.sender是指外部賬戶的地址,this是指當(dāng)前創(chuàng)建的智能合約的地址。
contract AddrTest{ event LogContractAddress(address exAccount, address contractAddress); function AddrTest(){ LogContractAddress(msg.sender,this); } }
在remix運行,可以證明這個推測
LOG說明
感謝各位的閱讀,以上就是“Solidity故障怎么排查”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Solidity故障怎么排查這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
本文名稱:Solidity故障怎么排查
網(wǎng)頁URL:http://m.newbst.com/article46/jedieg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機、網(wǎng)站制作、品牌網(wǎng)站設(shè)計、品牌網(wǎng)站建設(shè)、網(wǎng)站營銷、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)