question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

sendRawTransaction allows you to make transactions for free

See original GitHub issue

@oed commented on Mon Jul 10 2017

Expected Behavior

Sending a transaction using sendRawTransaction should not be allowed if the sender account doesn’t have any ether.

Current Behavior

Right now it is possible to send a raw transaction without any ether in the sender account. Looking at the txReciept the transaction says that it has consumed gas.

Possible Solution

There might be a check that is missing when sending raw transactions. Sending raw transactions with value from an empty account does not work.

Steps to Reproduce (for bugs)

The following code should be sufficient to reproduce the bug:

var Contract = require('truffle-contract')
var TestRPC = require('ethereumjs-testrpc');
var Web3 = require('web3')
var Transaction = require('ethereumjs-tx');
var Promise = require('bluebird')
var coder = require('web3/lib/solidity/coder');
var CryptoJS = require('crypto-js');

var testRegArtifact = { "contract_name": "TestRegistry", "abi": [ { "constant": true, "inputs": [ { "name": "", "type": "address" } ], "name": "registry", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [ { "name": "with", "type": "uint256" }, { "name": "many", "type": "address" }, { "name": "strange", "type": "string" }, { "name": "params", "type": "uint256" } ], "name": "reallyLongFunctionName", "outputs": [], "payable": false, "type": "function" }, { "constant": false, "inputs": [], "name": "testThrow", "outputs": [], "payable": false, "type": "function" }, { "constant": false, "inputs": [ { "name": "x", "type": "uint256" } ], "name": "register", "outputs": [], "payable": false, "type": "function" } ], "unlinked_binary": "0x606060405234610000575b61017b806100196000396000f300606060405263ffffffff60e060020a600035041663038defd781146100455780630da9a4241461007057806350bff6bf146100d4578063f207564e146100e3575b610000565b346100005761005e600160a060020a03600435166100f5565b60408051918252519081900360200190f35b3461000057604080516020600460443581810135601f81018490048402850184019095528484526100d29482359460248035600160a060020a031695606494929391909201918190840183828082843750949650509335935061010792505050565b005b34610000576100d2610040565b005b34610000576100d2600435610130565b005b60006020819052908152604090205481565b600160a060020a03831660009081526020819052604090208190555b50505050565b610000565b565b600160a060020a03331660009081526020819052604090208190555b505600a165627a7a72305820cb91dd6e3f04cdc9c738360fa22a89e466a845485c2c5df43ad25d11eff687120029", "networks": {}, "schema_version": "0.0.5", "updated_at": 1498489105320 }
var keypair = { "privateKey": "0x3686e245890c7f997766b73a21d8e59f6385e1208831af3862574790cbc3d158",
                "address": "0x7f2d6bb19b6a52698725f4a292e985c51cefc315" }

var provider = TestRPC.provider()
var web3 = new Web3(provider)
var TestRegistry = Contract(testRegArtifact)
TestRegistry.setProvider(provider)
web3.eth = Promise.promisifyAll(web3.eth)

var accounts = Object.keys(provider.manager.state.accounts)
var txParams = {from: accounts[0], gas: 2000000}
var testNum = 1234
var data = '0x' + encodeFunctionTxData('register', ['uint256'], [testNum])
var testReg

TestRegistry.new(txParams).then(instance => {
  testReg = instance
  return testReg.registry.call(keypair.address)
}).then(registeredNum => {
  console.log('Registered number before tx: ' + registeredNum.toNumber())
  return web3.eth.getBalanceAsync(keypair.address)
}).then(bal => {
  console.log('Balance before tx: ', bal.toNumber())
  return web3.eth.getTransactionCountAsync(keypair.address)
}).then(nonce => {
  var tx = new Transaction({
    to: testReg.address,
    value: 0,
    nonce: nonce,
    data: data,
    gasLimit: 2000000
  })
  tx.sign(Buffer.from(keypair.privateKey.slice(2), 'hex'))
  var signedRawTx = tx.serialize().toString('hex')

  return web3.eth.sendRawTransactionAsync(signedRawTx)
}).then(txHash => {
  return web3.eth.getTransactionReceiptAsync(txHash)
}).then(tx => {
  console.log('Gas used: ' + tx.gasUsed)
  return testReg.registry.call(keypair.address)
}).then(registeredNum => {
  console.log('Registered number after tx: ' + registeredNum.toNumber())
  return web3.eth.getBalanceAsync(keypair.address)
}).then(bal => {
  console.log('Balance after tx: ', bal.toNumber())
})

function encodeFunctionTxData(functionName, types, args) {
  var fullName = functionName + '(' + types.join() + ')';
  var signature = CryptoJS.SHA3(fullName, { outputLength: 256 }).toString(CryptoJS.enc.Hex).slice(0, 8);
  var dataHex = signature + coder.encodeParams(types, args);

  return dataHex;
}

Output

Registered number before tx: 0
Balance before tx:  0
Gas used: 41841
Registered number after tx: 1234
Balance after tx:  0

Your Environment

  • Version used: 4.0.1
  • Environment name and version: node v8.1.3
  • Operating System and version: Arch Linux

@Cryptonious commented on Thu Apr 05 2018

This also and currently still occurs with the Ganache UWP client (not just the CLI)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
kyriediculouscommented, Nov 29, 2018

@davidmurdoch

Hmm this code example makes the situation a bit more clear.

By “blocking” I thought actively blocking all transactions with no specified gasPrice. Which is what might have thrown me off in the other thread.

When no gasPrice is specified I believe the network mean is used. When no gasPrice is specified starting testRPC the default is 200 shannon.

So, in this specific case where the user has no balance the expected behaviour would be:

Case 1: Transaction has gasPrice set to 0 , node has 200 shannon –> Transaction should remain pending and wait for expiration or replacement

Case2: Transaction has gasPrice set > 0 or defaults to network mean –> Transaction should throw “Gas cost exceeds balance”

From what I can see in the source code, rawTx should behave the same as sendTx ? The txParams from queueRawTx are passed into queueTx where a new rawTx object is created based on the txParams (if set).

So in theory this should also happen with “regular” transactions.

0reactions
davidmurdochcommented, Apr 22, 2022

Closing this one for issue maintenance 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

sendRawTransaction allows you to make transactions for free
Sending a transaction using sendRawTransaction should not be allowed if the sender account doesn't have any ether.
Read more >
How to use sendrawtransaction properly [duplicate]
If you want to use sendRawTransaction you need pass the transaction signed and in raw bytes. The posts here and here will give...
Read more >
How to Send Transactions on Ethereum - Alchemy Docs
In this tutorial, we'll be using Alchemy to send our transactions to the Ethereum chain. You can create a free Alchemy account here....
Read more >
python - Difference between sendTransaction and ...
sendTransaction() only supports sending unsigned transactions. ... but enables you to broadcast transactions on hosted nodes.
Read more >
Create and send transactions - Hyperledger Besu
You can send signed transactions using the eth_sendRawTransaction JSON-RPC API method. Signed transactions can be simple value transfers, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found