Contract-Development

呼叫合約方法時如何解釋字元串序列化?

  • December 22, 2016

在 Ropsten 測試網上,我部署了這樣的合約:

// creation of contract object
var aContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"lastIdMessage","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"readYourLastMessage","outputs":[{"name":"message","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"idMessage","type":"uint256"}],"name":"readYourMessageById","outputs":[{"name":"message","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"idMessage","type":"uint256"}],"name":"readYourMessageMetadataById","outputs":[{"name":"_idMessage","type":"uint256"},{"name":"_idPrevious","type":"uint256"},{"name":"_timestamp","type":"uint256"},{"name":"_from","type":"address"},{"name":"_message","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"timestamp","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"messages","outputs":[{"name":"idMessage","type":"uint256"},{"name":"idPrevious","type":"uint256"},{"name":"timestamp","type":"uint256"},{"name":"from","type":"address"},{"name":"message","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"countMessage","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"whoAmI","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"message","type":"string"}],"name":"sendMessage","outputs":[],"payable":false,"type":"function"},{"payable":false,"type":"fallback"}]);

// initiate contract for an address
var sc = aContract.at('0x59dbff7e055b09f02d5508a7c42f09b4683b2934');

該合約有一個我試圖呼叫的方法,但首先我需要了解如何正確編碼字元串參數:

// invoke contract method sendMessage(address,string)
sc.sendMessage.sendTransaction("0xa7e3c7c227c72a60e5a2f9912448fb1c21078769", "Hi Juan, this is marketpay sending first blockchain ever message!", {from:"0xf28dafbfeb41bf32869c9d498da0d651d0206ed4", gas:1000000});
   "0xe1a5d54c5b2ed440d55405ab73516245e909a2e345c734438fc9878801365c56"
   https://testnet.etherscan.io/tx/0xe1a5d54c5b2ed440d55405ab73516245e909a2e345c734438fc9878801365c56

根據這個之前的交易,我可以探索字元串數據是如何被序列化的:

// hex header
0x

// 8 chars for method hash
de6f24bb

// 64 chars for first parameter, an account address
000000000000000000000000a7e3c7c227c72a60e5a2f9912448fb1c21078769

// 320 chars for encoding a string
000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000414869204a75616e2c2074686973206973206d61726b65747061792073656e64696e6720666972737420626c6f636b636861696e2065766572206d6573736167652100000000000000000000000000000000000000000000000000000000000000

好吧,問題是我怎樣才能從這個字元串中走出來:

"Hi Juan, this is marketpay sending first blockchain ever message!"

到這個十六進制值?:

000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000414869204a75616e2c2074686973206973206d61726b65747061792073656e64696e6720666972737420626c6f636b636861696e2065766572206d6573736167652100000000000000000000000000000000000000000000000000000000000000

我在哪裡可以找到解釋乙太坊字元串序列化的文件?謝謝!

你可以在Ethereum Contract ABI找到文件。

動態類型的使用部分:

對於靜態類型 uint256 和 bytes10,這些直接是我們想要傳遞的值,而對於動態類型 uint32$$ $$和字節,我們使用以字節為單位的偏移量到它們的數據區域的開始,從值編碼的開始測量(即不計算包含函式簽名雜湊的前四個字節)。

這是我到目前為止制定的細分:

// Hex header
0x

// 8 chars for method hash
de6f24bb

// Address
000000000000000000000000a7e3c7c227c72a60e5a2f9912448fb1c21078769

// 0x40 = 64. This is the offset from the beginning of Address
// directly above to the start of the next set of hex strings
// ending with 41 directly below
0000000000000000000000000000000000000000000000000000000000000040

// 0x41 = 65. This is the length of the dynamic string
0000000000000000000000000000000000000000000000000000000000000041

// And this is the string contents. As it is 65 characters, it will
// take up 32 characters + 32 characters + 1 character
// web3.toUtf8("0x4869204a75616e2c2074686973206973206d61726b65747061792073656e6469")
// returns "Hi Juan, this is marketpay sendi"
4869204a75616e2c2074686973206973206d61726b65747061792073656e6469

// web3.toUtf8("6e6720666972737420626c6f636b636861696e2065766572206d657373616765")
// returns "ng first blockchain ever message"
6e6720666972737420626c6f636b636861696e2065766572206d657373616765

// web3.toUtf8("2100000000000000000000000000000000000000000000000000000000000000")
// returns "!"
2100000000000000000000000000000000000000000000000000000000000000

也可以看看:

引用自:https://ethereum.stackexchange.com/questions/10818