Here's your function slightly modified by adding public
to numbers
so we can peek at the data:
contract C {
uint[] public numbers;
function initNumbers() {
numbers.push(1);
numbers.push(2);
}
function stateChanger(uint a) {
numbers.push(a);
}
}
Using the stripCrLf
script in How to load Solidity source file into geth, I've flattened the source code using the following command:
user@Kumquat:~$ echo "var cSource='`stripCrLf C.sol`'"
var cSource='contract C { uint[] public numbers; function initNumbers() { numbers.push(1); numbers.push(2); } function stateChanger(uint a) { numbers.push(a); } }'
I'm running a dev network using the following command (I have my password in passwordfile
):
user@Kumquat:~$ geth --datadir ~/devdata --dev --mine --minerthreads 1 --unlock 0 --password ~/passwordfile console
I paste the flattened code in the geth
command line:
> var cSource='contract C { uint[] public numbers; function initNumbers() { numbers.push(1); numbers.push(2); } function stateChanger(uint a) { numbers.push(a); } }'
undefined
And compile the code using the following command:
> var cCompiled = web3.eth.compile.solidity(cSource);
Version: 0.3.5-0/RelWithDebInfo-Linux/g++/Interpreter
path: /usr/bin/solc
undefined
Here is the Application Binary Interface:
> cCompiled.C.info.abiDefinition
[{
constant: false,
inputs: [],
name: "initNumbers",
outputs: [],
type: "function"
}, {
constant: false,
inputs: [{
name: "a",
type: "uint256"
}],
name: "stateChanger",
outputs: [],
type: "function"
}, {
constant: true,
inputs: [{
name: "",
type: "uint256"
}],
name: "numbers",
outputs: [{
name: "",
type: "uint256"
}],
type: "function"
}]
Deploy the contract on the blockchain:
> var cContract = web3.eth.contract(cCompiled.C.info.abiDefinition);
undefined
> var c = cContract.new({
from:web3.eth.accounts[0],
data: cCompiled.C.code, gas: 400000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
})
Contract mined! Address: 0x672807a8c0f72a52d759942e86cfe33264e73934
Call your initNumbers()
:
> c.initNumbers({from:eth.accounts[0], gas: 400000})
"0x3f21e1cdb636a2cf291cd9296282a4e9c4f4ed57c65a13fedc937a97203c3a75"
...
> c.numbers(0)
1
> c.numbers(1)
2
> c.numbers(2)
0
Calling stateChanger(...)
- Method 1
> c.stateChanger(3, {from:eth.accounts[0], gas: 400000})
"0x3ecf3aa6464f93d5b062ad01b76b5dbc4302c190baf70d157a4d7607d4c7c749"
...
> c.numbers(2)
3
> c.numbers(3)
0
Calling stateChanger(...)
- Method 2
> c.stateChanger.sendTransaction(4, {from: eth.accounts[0], gas: 400000})
"0xe1d9c57ca55dbdf446e55602570888ff5efce97a91ddc5c9575d10c7c9a1f0c8"
...
> c.numbers(3)
4
> c.numbers(4)
0
Calling stateChanger(...)
- Method 3
And following is how to use the raw data sendTransaction(...)
format.
Find the function signature. Note that the uint
parameter is actually a uint256
(see the ABI format above):
> web3.sha3('stateChanger(uint256)').substr(0, 10)
"0x65060775"
Here is 5 encoded in hex and padded to 32 bytes:
0x0000000000000000000000000000000000000000000000000000000000000005
Join the data together, removing the 0x
from the hex(5) string:
0x650607750000000000000000000000000000000000000000000000000000000000000005
Here's how to sendTransaction(...)
. The to:
parameter is the address of the mined contract:
> var result = web3.eth.sendTransaction({
from: eth.accounts[0],
to: "0x672807a8c0f72a52d759942e86cfe33264e73934",
data: "0x650607750000000000000000000000000000000000000000000000000000000000000005",
gas: 400000}
)
undefined
> result
"0x420d4256718b4326967677da2e460a1d361a62f3ceee386e1313d25b12c0f610"
...
> c.numbers(4)
5
> c.numbers(5)
0
Bonus 1 - estimateGas(...)
Since we have worked out the data to send with sendTransaction(...)
above.
Here is the gas used by the sendTransaction(...)
call above:
> eth.getTransactionReceipt(result).gasUsed
46888
You can use the same data format to estimate the gas using the estimateGas(...)
call:
var result = web3.eth.estimateGas({
from: eth.accounts[0],
to: "0x672807a8c0f72a52d759942e86cfe33264e73934",
data: "0x650607750000000000000000000000000000000000000000000000000000000000000005",
gas: 400000}
)
undefined
> result
46888
Bonus 2 - The Transaction Data
Set debug.verbosity(7)
and watch the transaction get removed from the transaction pool after it is executed:
> debug.verbosity(7)
...
I0730 00:13:43.918828 core/tx_pool.go:547] removed tx (
TX(07c3c717c87ce1e2b31ba144b6b751d66c90a8a69375478a5ef4e60a6f42996c)
Contract: false
From: a7857047907d53a2e494d5f311b4b586dc6a96d2
To: 672807a8c0f72a52d759942e86cfe33264e73934
Nonce: 35
GasPrice: 20000000000
GasLimit 400000
Value: 0
Data: 0x650607750000000000000000000000000000000000000000000000000000000000000004
V: 0x1c
R: 0x75ff67a969670a0f35ae415f2fa541446a71fa9b7d8ad6247ad12fd7ae3986a
S: 0x7150424ed1698792cdcf1253a79f2474e4df411610db97e36240bab50af6c80c
Hex: f889238504a817c80083061a8094672807a8c0f72a52d759942e86cfe33264e7393480a46506077500000000000000000000000000000000000000000000000000000000000000041ca0075ff67a969670a0f35ae415f2fa541446a71fa9b7d8ad6247ad12fd7ae3986aa07150424ed1698792cdcf1253a79f2474e4df411610db97e36240bab50af6c80c
) from pool: low tx nonce or out of funds
The different methods of calling (c.stateChanger(3, {from:eth.accounts[0], gas: 400000})
and c.stateChanger.sendTransaction(4, {from: eth.accounts[0], gas: 400000})
) are converted to the sendTransaction(...)
format.