$ geth console --testnet 2>>geth.log
--testnet
flag connects us to the Ropsten test network. To connect to Rinkeby, use the --rinkeby
flag --rinkeby
. Additionally, we redirect messages from the standard stream (stderr) of geth to the geth.log file, otherwise they will be interfered with in the console. > eth.getBalance(eth.coinbase)
22159430784000000000
> web3.fromWei( eth.getBalance(eth.coinbase) ) 22.159430784
> var address = "0x65cA73D13a2cc1dB6B92fd04eb4EBE4cEB70c5eC";
> var abi = [ { "constant": false, "inputs": [ { "name": "newString", "type": "string" } ], "name": "setString", "outputs": [], "payable": false, "type": "function" }, { "constant": true, "inputs": [], "name": "getString", "outputs": [ { "name": "", "type": "string", "value": "Hello World!" } ], "payable": false, "type": "function" } ];
> var contract = web3.eth.contract(abi);
> var stringHolder = contract.at(address)
undefined
- do not pay attention. Instead of the address and the interface, substitute your own values, and if you are on the same test network (Ropsten) as we are while creating our example, you can use our contract. Call the contract functions: > stringHolder.getString() "Hello World!" > stringHolder.setString("Hello my baby, hello my honey!"); Error: invalid address at web3.js:3879:15 at web3.js:3705:20 at web3.js:4948:28 at map (<native code>) at web3.js:4947:12 at web3.js:4973:18 at web3.js:4998:23 at web3.js:4061:16 at apply (<native code>) at web3.js:4147:16
getString
method worked correctly, and setString
caused an error. In this case, this error occurs due to the fact that transactions must be carried out from any account that can pay off the air. Unlock the account with the following command (you will need to enter the password from the private key) and run setString
again with an additional option, specifying from which account to perform the transaction: > web3.personal.unlockAccount(eth.coinbase); Unlock account 0x< > Passphrase: true > stringHolder.setString("Hello my baby, hello my honey!", {from: eth.coinbase}); "0x5f9c3a61c79df36776713f7373b902feea802cf6d3903195f8070ff2d376c669"
> web3.eth.getTransaction("0x5f9c3a61c79df36776713f7373b902feea802cf6d3903195f8070ff2d376c669");
getString
and see that the string has changed: > stringHolder.getString(); "Hello my baby, hello my honey!"
The broadcast is needed for any operations to change data, they are paid for the so-called gas - an abstract unit of measure, which serves to assess the work required to complete the transaction. It is necessary for the independence of this assessment from the current market value of the air. When sending a transaction, you can specify how much air you pay for each unit of gas and the maximum amount of gas you are willing to pay. The more you allocate - the more priority your transaction is for potential miners. After all, in essence, the payment for gas is the payment for the work of miners to complete your transaction and include it in the next block. Therefore, when mining, in addition to a fixed fee for the block found - at the time of writing it is 5 airs - the miner also receives payment for transactions, as a rule it is a few hundredths of aired. The amount of gas per transaction depends on the computational complexity of operations on data.
pragma solidity ^0.4.10; contract UselessWorker { int public successfullyExecutedIterations = 0; function doWork(int _iterations) { successfullyExecutedIterations = _iterations; for (int i = 0; i < _iterations; i++) { keccak256(i); } } }
doWork
function, which takes the number of iterations int _iterations
as a parameter, and then counts the keccak256
hash from the loop counter. So we can give a different amount of work and see how the amount of required gas depends on it. The only variable stored in the contract — successfullyExecutedIterations
— is used to save the number of cycles performed during the last run. It is needed to demonstrate what happens in case of excess gas flow. $ solc --bin --abi UselessWorker.sol
--bin
and --abi
we tell the compiler to generate the binary code and interface. A command is given a response similar to the following: ======= UselessWorker.sol:UselessWorker ======= Binary: Contract JSON ABI [{"constant":true,"inputs":[],"name":"successfullyExecutedIterations","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_iterations","type":"int256"}],"name":"doWork","outputs":[],"payable":false,"type":"function"}]
$ geth console --testnet 2>>geth.log
> var bin = ""; > var abi = [{"constant":true,"inputs":[],"name":"successfullyExecutedIterations","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_iterations","type":"int256"}],"name":"doWork","outputs":[],"payable":false,"type":"function"}];
> var contract = web3.eth.contract(abi);
> web3.personal.unlockAccount(eth.coinbase);
> var uselessWorker = contract.new( {from: eth.coinbase, data: bin, gas: 1000000}, function(e, contract) { if (e) { console.log(e); } else { if (contract.address) { console.log ("mined " + contract.address); } } });
mined 0xaad3bf6443621f24099ee4f51a22c8d7e9f63548
> uselessWorker.successfullyExecutedIterations(); 0
public
field.estimateGas()
method on the contract method of interest, and the parameters of the method of interest are passed as parameters in estimateGas
. In our case, you can call this: > uselessWorker.doWork.estimateGas(1); 41801 > uselessWorker.doWork.estimateGas(2); 41914 > uselessWorker.doWork.estimateGas(3); 42027
> web3.fromWei( eth.gasPrice ); 1e-7
> web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(1) ); "0.0041801"
> web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(10000) ); "0.1171752"
> web3.fromWei( eth.gasPrice * uselessWorker.doWork.estimateGas(1000000) ); "0.4704624"
> web3.fromWei( eth.gasPrice ); 2.8e-7
> var fixedGasPrice = 100000000000;
> web3.fromWei( fixedGasPrice * uselessWorker.doWork.estimateGas(100000, {gas: 100000000}) ); "1.1341816"
> web3.fromWei( fixedGasPrice * uselessWorker.doWork.estimateGas(100000, {gas: 1000}) ); "0.0001"
estimateGas
function may not always provide reliable data, because its execution is based on the current state of the blockchain, which may be different during the execution of this transaction, which will result in a different gas flow. > initialBalance = eth.getBalance(eth.coinbase); 5006820644000000000
> uselessWorker.doWork.estimateGas( 10 ); 42818
fixedGasPrice
price for this operation, but we will set the maximum amount of gas to 42000 (this is probably not enough, since it is less than the predicted value). Therefore, our payment, taking into account the consumption of all the gas provided, should be in wei: > predictedCost = 42000 * fixedGasPrice; 4200000000000000
> web3.fromWei(predictedCost); "0.0042"
> web3.personal.unlockAccount(eth.coinbase); > transaction = uselessWorker.doWork( 10, { from: eth.coinbase, gas: 42000, gasPrice: fixedGasPrice } ); "0xc0590a2cf39c3e4339253ecf11d124177b75502cea368adcf30d1b7d6933ef5a"
> result = web3.eth.getTransactionReceipt(transaction);
{ blockHash: "0x91b63b43856e62fd26ad7f401bfe556cc100e8adf4b5ac510261e91adb9953a3", blockNumber: 1375978, contractAddress: null, cumulativeGasUsed: 740323, from: "0x334731990b420d7fe77347545c45a689becfca08", gasUsed: 42000, logs: [], logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x07dc7178ac2abaa2460cd94d5eb7bf6d7ed9ed09e3e74a4b53321b5c210932c0", to: "0xaad3bf6443621f24099ee4f51a22c8d7e9f63548", transactionHash: "0xc0590a2cf39c3e4339253ecf11d124177b75502cea368adcf30d1b7d6933ef5a", transactionIndex: 1 }
nil
, then the transaction has not yet been added to the block, you must wait and repeat the command.gasUsed
gas gasUsed
turned out to be 42,000, as expected. Check if our balance has changed: > web3.fromWei( initialBalance - eth.getBalance(eth.coinbase) ); "0.0042"
> uselessWorker.successfullyExecutedIterations(); 0
> initialBalance = eth.getBalance(eth.coinbase); 5002620644000000000
> 43000 * fixedGasPrice; 4300000000000000
> web3.personal.unlockAccount(eth.coinbase); > transaction = uselessWorker.doWork( 10, { from: eth.coinbase, gas: 43000, gasPrice: fixedGasPrice } );
> result = web3.eth.getTransactionReceipt(transaction);
{ blockHash: "0xe9793206faf5e923042488d4312d542db2c5189d25a0014d894179fce222705d", blockNumber: 1376028, contractAddress: null, cumulativeGasUsed: 131780, from: "0x334731990b420d7fe77347545c45a689becfca08", gasUsed: 42817, logs: [], logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x51fd139db608c2fa833e5de205497368362853b8e778787e85180e1cde206151", to: "0xaad3bf6443621f24099ee4f51a22c8d7e9f63548", transactionHash: "0xd69e46cbb9c139cc2c56ae4860b2e73e4581a97fc016c2848dc6bd399e9b5196", transactionIndex: 2 }
> web3.fromWei( initialBalance - eth.getBalance(eth.coinbase) ); "0.0042817"
> uselessWorker.successfullyExecutedIterations(); 10
Source: https://habr.com/ru/post/336770/
All Articles