I want to send a message on a transaction. Here is my codes:
_data = web3.toHex('xxxx');
instance.function_name(param1, param2, param3, param4, {value: web3.toWei(_price, 'ether'), from: web3.eth.accounts[0], data:_data}).then(...);
The transaction is processed successfully, But the input data message is not the _data value in the etherscan.io
can anybody help me? Thank you.
The data field in the transaction object is used when deploying a contract or when using the general sendTransaction or sendRawTransaction methods. If you are using a contract instance, the data field is ignored.
From the Solidity docs:
Object - (optional) The (previous) last parameter can be a transaction object, see web3.eth.sendTransaction parameter 1 for more. Note: data and to properties will not be taken into account.
If you want to send the data manually, use sendTransaction.
The information shown in Etherscan is the decoded data from the signed transaction describing the function call made. It is not free form user data (if that's what you're trying to insert). The first 32 bits of the data are the function signature and each 256 bit block afterwards are the parameters.
See this source for more in-depth information.
Related
According to the docs for web3.eth.sendTransaction and the docs for eth_sendTransaction:
The transaction object can contain an optional data parameter which should be a String that consists of:
either an ABI byte string containing the data of the function call on a contract, or in the case of a contract-creation transaction the initialisation code.
I want to assign a string to data and have the string be stored along with the record of the transaction on the blockchain, so that I can retrieve that string when I retrieve the record of that transaction later.
const [testAccount] = await window.ethereum.request({ method: "eth_requestAccounts" })
const web3 = new Web3(window.ethereum)
if (!testAccount) {
return
}
let transactionHash = await web3.eth.sendTransaction({
from: testAccount,
to: testAccount,
value: web3.utils.toWei('0.0003'),
data: web3.utils.utf8ToHex(JSON.stringify({ a: 1, b: 2 }))
})
let transaction = await web3.eth.getTransaction(transactionHash)
let data = JSON.parse(web3.utils.hexToUtf8(transaction.data))
console.log(data.a) // should log 1
When I execute sendTransaction (using Metamask, while connected to the Ropsten network), I get the following error:
Error: Error: TxGasUtil - Trying to call a function on a non-contract address
{
"originalError": {
"errorKey": "transactionErrorNoContract",
"getCodeResponse": "0x"
}
}
Apparently, you cannot assign any string to data and expect the string to be incorporated in the record of the transaction on the blockchain, out-of-the-box, simply by assigning a value to it. Is this correct?
Question: Do I need to write a custom smart-contract in order to achieve this ?
This is a feature/limitation specific to MetaMask. Possibly to protect their users who want to interact with a smart contract but are connected to a different network where the contract is not deployed.
However, it is technically possible to send a valid transaction with non-empty data field to a non-contract address. You just need to use a different node provider to broadcast the transaction. Unfortunately the node provider in MetaMask is hardcoded so it's not possible using this wallet.
Example: This transaction on the Ropsten testnet to the 0xdac1... address that has the USDT token contract deployed on the mainnet, but is a non-contract address on the testnet. It is a valid transaction, successfully bought gas from the sender address to cover the transaction fees, mined in a block, just didn't execute any smart contract code (as there is no smart contract on the recipient address).
Do I need to write a custom smart-contract in order to achieve this ?
You can also write a smart contract function in Solidity that receives data as a function argument, but does nothing on this. Thus, GoEthereum node stores this data as calldata of the transaction and it can be later retrieved.
I am pretty sure some cross-chain bridges operate in this manner. Transactions only write data as the part of calldata (cheaper than Solidity storage) and then other clients read it from there.
I have ERC-20 token smart-contract which methods I call using sendSignedTransaction from web3.js. After I know transaction is succesfully mined I need to check contract method execution result. How do I do it if all I have is transaction hash?
Example: method transferFrom(from, to, tokens) returns true or false depending on whether transferring was successful. So if I try to transfer 100 tokens from empty wallet, contract method will return false.
Upd: Okay, as I understood there is no way of determining method outcome using txHash after transaction is mined and confirmed. Then which ways exists to handle this case? How can I make sure that tokens were transferred?
You can emit an event inside your contract code ( actually in ERC20 standard there is always a transfer event present ) and then inside web3js, read all the events till latest block using this line of code:
Events = Contract.eventName({}, {fromBlock: 0, toBlock: 'latest'});
Newbie.
There is a go-ethereum method:
eth.estimateGas({from:'firstAccount', to:'secondAccount'})
that works well,
but same method with contract address like:
eth.estimateGas({from:'firstAccount', to:'contractAddr'})
fails with error
gas required exceeds allowance or always failing transaction
I have looked into go-ethereum source code and it has the line, that contains proposal to use contract address as second parameter:
https://github.com/ethereum/go-ethereum/blob/master/accounts/abi/bind/base.go#L221
The question is: is there any possibily to use eth.estimateGas with contract address as second parameter and how to avoid above error?
Thank you.
You're not specifying what you're executing in the contract, so there's nothing to estimate. When you estimateGas for a transfer to an EOA account, there is no contract code to execute, so there is no message data to be sent as part of the transaction object. If you're estimating gas on a contract call, you need to include the data for the contract.
For example, if you want to estimate gas to setValue(2) method in this contract
pragma solidity ^0.4.19;
contract SimpleContract {
uint256 _value;
function setValue(uint256 value) public {
_value = value;
}
}
your call would be
var data = '552410770000000000000000000000000000000000000000000000000000000000000002';
eth.estimateGas({from: fromAccount, to: contractAddress, data});
The value for data comes from encoding the function signature and the parameter value(s). You can use a simple tool (like https://abi.hashex.org) to generate this. You just enter the function name along with the parameter argument types and their values, and it will generate the message data for you. You can also do this using web3js.
EDIT - I neglected to consider contracts with fallback functions. Executing estimateGas on a contract without passing in message data provide the estimate for contracts that have a fallback function. If the contract does not have a fallback function, the call will fail.
Can anyone explain to me what address(0) is in Solidity? I found the following in the docs but it doesn't really make sense to me:
If the target account is the zero-account (the account with the address 0), the transaction creates a new contract. As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the “nonce”). The payload of such a contract creation transaction is taken to be EVM bytecode and executed. The output of this execution is permanently stored as the code of the contract. This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that returns that code.
http://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html?highlight=address(0)#index-8
Within an Ethereum transaction, the zero-account is just a special case used to indicate that a new contract is being deployed. It is literally '0x0' set to the to field in the raw transaction.
Every Ethereum transaction, whether it's a transfer between two external accounts, a request to execute contract code, or a request to deploy a new contract, are encoded in the same way. A raw transaction object will look something like this:
transaction = {
nonce: '0x0',
gasLimit: '0x6acfc0', // 7000000
gasPrice: '0x4a817c800', // 20000000000
to: '0x0',
value: '0x0',
data: '0xfffff'
};
If to is set to something other than '0x0', this request will result in transferring ether to the address (if value is non-zero), and execute the function encoded in the data field. Remember, the address can either be a contract or an external account.
When the to address is the zero-address, a new contract will be created by executing the code in data (this is what is meant by "code that returns the code"). The address of the newly created contract is technically known beforehand as it's based on the address of the sender and it's current nonce. That address becomes the official address of the contract after mining.
For a pretty good read on Ethereum transactions, check out this blog post.
Note: There is also the actual Solidity code statement address(0) which is the initial value of a variable of type address. The documentation you posted, however, is referring to specifically when the to account address in a transaction is set to '0x0'.
It's not actually true that a contract creation transaction has a "to" field set to the zero address (meaning 0x00...000). This is an easy mistake to make (and I've made it too) as it is described that way in many resources.
The passage you cite from the Solidity docs were updated to state this:
If the target account is not set (the transaction does not have a
recipient or the recipient is set to null), the transaction creates a
new contract. As already mentioned, the address of that contract is
not the zero address but an address derived from the sender and its
number of transactions sent (the “nonce”).
So you can see they realized at some point that the recipient field should be empty. I've actually looked at serialized creation transactions and found 0x80 there instead of an RLP-ed zero address.
In fact, 0x80 is the RLP encoding of an empty byte array, which is what the Yellow Paper states is the recipient for a contract creation:
The address hash $T_t$ is slightly different: it is either a 20-byte
address hash or, in the case of being a contract-creation transaction
(and thus formally equal to ∅), it is the RLP empty byte sequence and
thus the member of $B_0$
As I said, this is a common source of confusion. In that vein, this GitHub PR rolling back a mistakenly "fixed" test is amusing. It has the comment:
RLP encoding of 0 is encoding of empty byte array, so 0x80 is correct.
0x00 is encoding of byte array of length 1 containing one byte 0, not
encoding of integer 0.
With web3js, how do you figure out that there was 40000 tokens transfer from the transaction's hash?
There's a very good blog post on Medium using the exact method you're interested in.
(Stealing from the post):
Retrieve the input data from web3.eth.getTransaction() This will return the hex data for the function and parameters sent in the transaction. It will look something like 0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff.
The first 32 bits (0xa9059cbb) is the sha3 encoded text of the function signature.
Every 256 bit block after that is an argument passed in.
After parsing out the block corresponding to the number of tokens in the parameter list, use web3.utils to convert to decimal.
I will try to show an example how you do this:
lets take this Tx:
0xa543a3a7b6498bc9aec6989d99228be07855cdd23cfbf491489e8d4088b4a94c
This is Tx to a contract that send some amount of token to address
The received data from web3.eth.getTransaction() input:
0xa9059cbb00000000000000000000000092e707288dc221d864cf4a8c710c143e97225d7d000000000000000000000000000000000000000000000059f37b9220158a8000
Now the first 34 bits represent text of the function signature (0xa9059cbb)
The next 256 bit block represent the address we want send the token to:
00000000000000000000000092e707288dc221d864cf4a8c710c143e97225d7d
The second block represent the amount (in hex) of tokens that were sent to the address:
000000000000000000000000000000000000000000000059f37b9220158a8000
We will convert the hex to decimal with any conversion function or with this web site:
https://www.rapidtables.com/convert/number/hex-to-decimal.html
we will see that after the conversion we get 1659305000000000000000
it the number of token that sent to the address.
I hope it help
Ethereum smart contract transaction input data decoder
Uses ethereumjs-abi for decoding.
https://github.com/miguelmota/ethereum-input-data-decoder
just use web3.eth.getTransaction(transaction_address)
let transaction= await web3.eth.getTransaction("0X....")
console.log(JSOM.stringlify(transaction))
just not forget to define your provider and your web3 object before.