Last active
March 2, 2016 06:24
-
-
Save barkthins/c2e527af82056542cd7d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var Promise = require('bluebird'); | |
var fs = require('fs'); | |
var test = require('blue-tape'); | |
require('../web3E.js'); | |
var Web3 = require('web3'); | |
var web3 = new Web3(); | |
var solc = require('solc'); | |
// we shouldn't have to do this after web3E has done it, but can't | |
// get that working properly... | |
Promise.promisifyAll(web3.eth); | |
test("What happens when a contract sends ether it does not have", function(tid) { | |
web3.setupDefault(); | |
var myContract; | |
var source = fs.readFileSync("tape/send.sol", 'utf8'); | |
var compiled = solc.compile(source,1); | |
var code = compiled.contracts.sendit.bytecode; | |
var abi = JSON.parse(compiled.contracts.sendit.interface); | |
web3.eth.deployContract(code, abi) | |
.then(function(contract) { | |
myContract = contract; | |
Promise.promisifyAll(myContract); | |
Promise.promisifyAll(myContract.incrData); | |
// the contract sends ether it doesn't have. This results in | |
// the send failing but other side effects still happen. | |
// i.e. no throw in solidity. Note the contract takes the 5000 Wei that was sent, | |
// meaning this function would send ether every other time. | |
sent = 5000; | |
// this is not a good place to specify gas. Should be on the ABI function, not sprinkled into code. | |
return myContract.incrData.sendTransactionAsync({value:sent, gas:600000}) | |
}).then(function(result) { | |
// timeout should never be in application code, it's deployment and ABI function dependent. | |
// XXX if we run out of gas the tests below may be invalid and give false positive or false negative | |
return web3.eth.awaitConsensus(result).timeout(30000,"ethereum didn't mine it") | |
}).then(function() { | |
// XXX what happens if this times out because of node problem? Should throw from library | |
return myContract.dataAsync() | |
}).then(function(res) { | |
tid.equal(res.toString(10), '1', "Side effect of incrementing occured"); | |
return myContract.resultAsync() | |
}).then(function(res) { | |
tid.equal(res, false, "Got a failure to send the ether"); | |
return myContract.sendersBalanceAsync() | |
}).then(function(res) { | |
return web3.eth.getBalanceAsync(myContract.address) | |
}).then(function(bal) { | |
tid.equal(bal.toNumber(), sent, "Ether balance is what we sent in the incrData call"); | |
tid.end(); | |
}); | |
}); |
here's the solidity contract I'm testing:
contract sendit {
uint256 public data;
bool public result;
uint256 public sendersBalance;
function test() {
}
// if you send 5000 Wei to this function it will
// successfully send ether every other transaction
function incrData() {
data += 1;
// this should fail if this contract doesn't have enough ether
// however there's no throw. data is still incremented,
// and ether is still added to this contract instance's balance
// if it was sent in this transaction
result = msg.sender.send(10000);
sendersBalance = msg.sender.balance;
}
}
BTW this is the type of test contract and test code I write every time I encounter something non-obvious, to help the next noob and remind me when I forget.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that awaitConsensus is a function I wrote the performs the whole txhash->txreceipt event wait routine, instead of having that all over my application code. You can see the above code is straight to the point of what I'm trying to test with the solidity contract.
Requirements that need to be added to this code (but preferably not IN this code, but separately):