Solidity
有沒有一種簡單的方法來獲得契約的完整狀態?
我正在開發一個包含許多各種狀態變數的非常複雜的合約。(映射、數組、uint、字元串、字節等)。
對於測試,在給定時刻獲取具有契約完整狀態的 JSON(或類似的)將非常有用。
我想知道是否有一種簡單的方法可以從 geth 或 web3 獲得這種狀態。
就像是:
var currentState = web3.eth.getFullState([Contract address]);
如果這種方法適用於任何類型的任何契約,那就太好了。
此程式碼可以使用。它將呼叫合約的所有常量方法並列印它們的結果。如果您將合約的所有數據成員公開(當然在開發階段),編譯器將為您生成 getter 方法,這將是常量函式。此程式碼不會列印映射和數組,因為它們的 getter 需要鍵或索引。**合約中所有沒有參數的常量函式都將被執行。**但這似乎不是問題——他們無法改變任何事情。
function getContractState(abi_object, contract_instance) { "use strict"; for (let i=0; i<abi_object.length;i++) { if (abi_object[i].constant==true && abi_object[i].inputs.length==0&& abi_object[i].payable==false && abi_object[i].type=="function") { console.log(abi_object[i].name+"="+contract_instance[abi_object[i].name].call()); } } }
契約範例:
contract StateTest { uint public u; bool public b; int public i; string public s; byte public by; bytes public bs; address public a; function StateTest() { u=1; b=true; i=-1; s="abc"; by = 0x13; bs=new bytes(2); bs[0]=0x11; bs[1]=0xff; a = msg.sender; } }
輸出:
a=0xa90fa13d754131a31cde816fa8ce7ad222d4a246 b=true bs=0x11ff by=0x13 s=abc u=1 i=-1
從這裡複製粘貼答案:獲取智能合約的完整狀態
我在 Github 上創建了一個儲存庫,其中顯示瞭如何使用 nodejs https://github.com/medvedev1088/ethereum-merkle-patricia-trie-example讀取塊和任何合約儲存中的所有 Patricia trie 條目
var Trie = require('merkle-patricia-tree'); var rlp = require('rlp'); var levelup = require('levelup'); var leveldown = require('leveldown'); var db = levelup(leveldown('/your_home_dir/Library/Ethereum/rinkeby/geth/chaindata')); var keccak256 = require('js-sha3').keccak256; // the block state root, rinkeby, block number 1775804 // the block state root can be obtained by invoking web3.eth.getBlock(<blockNumber>) in `stateRoot` field var root = '0xe4a6ff741ec2e0d0cd274a745756028df27312161bdb4557b6da434349f716a9'; var trie = new Trie(db, root); trie.checkRoot(root, function (err, val) { console.log('Root exists:', val); }); var address = '398A7A69f3c59181A1ffe34bed11DCb5DF863A8a'; var addressHash = keccak256(new Buffer(address, 'hex')); trie.get('0x' + addressHash, function (err, val) { var decodedVal = rlp.decode(val); console.log(decodedVal); if (!decodedVal || decodedVal.length < 4) { console.log('The value for the address must be an array of 4 elements'); return; } // 3rd element in the array is storage root, 1st - nonce, 2nd - balance, 4th - codeHash var storageRoot = decodedVal[2]; console.log('storageRoot', storageRoot); trie.root = storageRoot; trie.checkRoot(storageRoot, function (err, val) { console.log('Storage root exists:', val); }); // Read storage slot with index 0 var slotZeroHash = keccak256(new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')); trie.get('0x' + slotZeroHash, function (err, val) { var decodedVal = rlp.decode(val); console.log('Value at slot 0: ', decodedVal); }); // Read all entries from contract storage var stream = trie.createReadStream(); stream.on('data', function (data) { console.log('key:' + data.key.toString('hex')); // values are rlp encoded var decodedVal = rlp.decode(data.value); console.log(decodedVal); }); stream.on('end', function (val) { console.log('done reading!'); }); });
範例輸出:
Root exists: true Account data: 398A7A69f3c59181A1ffe34bed11DCb5DF863A8a [ <Buffer 01>, <Buffer >, <Buffer 24 21 83 63 90 de b4 32 ce 0e ac fe 5f 49 be 88 99 17 bf 8a fa 07 72 24 1c 30 9e 61 e0 4a 0d 42>, <Buffer 61 60 55 49 c9 7c 3e 7a d6 68 63 3b 72 b2 60 d3 00 5e ab be f3 22 a2 d6 33 2a 49 76 80 89 77 7a> ] Storage root: <Buffer 24 21 83 63 90 de b4 32 ce 0e ac fe 5f 49 be 88 99 17 bf 8a fa 07 72 24 1c 30 9e 61 e0 4a 0d 42> Storage root exists: true Value at slot 0 - key: 290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 <Buffer 40 9f 9c d8 52 a3 ba e9 52 5d 2a aa> key:0205d9ce8b4a26409d40486b0ac7b8dc356714e840016b19cc5c0f2c8adbcd74 <Buffer 36 35 c9 ad c5 de a0 00 00> key:0249d346d51fad5ef0b6fae89b4907e63c831f4f8af088d602baef47cda4eab7 <Buffer 0a 07 64 07 d3 f7 44 00 00>
有趣的是,這些數據幾乎沒有用,因為您不知道槽索引(您只能看到它們的雜湊值)並且不知道值的數據類型。至少您知道合約佔用了多少儲存空間。