3

On Ropsten testnet I have deployed a contract like this:

// 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');

This contract has a method I am trying to invoke but first I need to undertand how to encode properly the string parameter:

// 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

According to this previous transaction I can explore how string data was serialized:

// 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

Well, the question is how can I go from this string:

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

to this hex value ? :

000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000414869204a75616e2c2074686973206973206d61726b65747061792073656e64696e6720666972737420626c6f636b636861696e2065766572206d6573736167652100000000000000000000000000000000000000000000000000000000000000

Where can I find a doc explaining string serialization on Ethereum? Thx!

4

You can find the documentation at Ethereum Contract ABI .

From the Use of Dynamic Types section:

For the static types uint256 and bytes10, these are directly the values we want to pass, whereas for the dynamic types uint32[] and bytes, we use the offset in bytes to the start of their data area, measured from the start of the value encoding (i.e. not counting the first four bytes containing the hash of the function signature).

Here is the breakdown I've worked out so far:

// 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

See also:

  • 1
    According to the docs, address is equivalent to uint160. Has that something to do with 0x40 = 64, the offset from the beginning of Address? – Juan Ignacio Pérez Sacristán Dec 21 '16 at 9:39
  • Yup. It's the offset from the beginning of Address to look in the second field. – The Officious BokkyPooBah Dec 21 '16 at 10:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.