I have the following fallback function:

uint public success;
function() public payable {
  success = 111;

I'm testing it with Truffle using this code:

beforeEach(async () => {
    this.icoInstance = await ico.deployed();
    await this.icoInstance.sendTransaction({ 
       value: 33, 
       from: investor, 
       gas: 300000 
it('should have been called', async () => {
    var success  = await this.icoInstance.success.call();
    console.log("success: " + success.toString()); 

Yet the console output says success: 0, meaning the function hasn't been called.

  1. Wha am I doing wrong?
  2. How do I test the case when a user sends some ETH to my contract?
  3. I've heard that the fallback function doesn't have enough gas to even set a variable, so how do I can do something whenever the contract receives money? My purpose is to save the sender's address to an array or a mapping.

UPDATE: it seems like the problem is with how my contract is instantiated. The code fails when I use this.icoInstance = await ico.deployed(), but succeeds when I change it to this.icoInstance = await ico.new(this.tokenInstance.address, {from: owner}). Another strange issue is that even if I initialize the success variable, it still says success: 0.

The deployment code is supposed to deploy two contracts:

module.exports = function(deployer, network, accounts) {
    .then(function () {
      deployer.deploy(CrowdSale, NppToken.address); 

The second contract is the one that has problems.


Wha am I doing wrong?

I'm not entirely sure as I experimented with the code above and it always works for me. However, note that before each test run, your deploy script is run once and it is the contract created with this script that is referenced with ico.deployed(). So when you use this.icoInstance = await ico.deployed() it reuses the contract that is deployed at the start of the test run for each test. Where as using this.icoInstance = await ico.new(this.tokenInstance.address, {from: owner}) will create a new contract for each test.

Check other tests in your test file aren't modifying the state in ways you're not expecting.

EDIT: Another thought, try deleting the 'build' folder. This will be regenerated when the contracts are recompiled, eg when you run test or compile. I don't think Truffle recompiles contracts if it thinks they haven't changed and sometimes it can be mistaken in thinking they haven't changed when they have.

How do I test the case when a user sends some ETH to my contract?

You can get the balance of an address/contract with web3.eth.getBalance(this.icoInstance.address). Note this doesn't currently return a callback so no need for await.

I've heard that the fallback function doesn't have enough gas to even set a variable...

The fallback function is limited to 2300 gas when it is called from another contract using send() or transfer(). It is not limited when calling from outside a contract, like you're doing here.

  • So when a user sends some ether with MetaMask or some other wallet, will there be enough gas to set a variable/do other stuff? How can I verify it in my test? I'm currently setting gas to 300000, but the user won't set it when they send the payment. – ulu Jan 19 '18 at 20:22
  • 1
    In MetaMask and most popular wallets, the user has the option to specify the gas limit. For me, in MetaMask the gas limit seems to default to 31500 which probably isn't enough to execute complex fallback functions. You'll have to determine how much gas your fallback function costs beforehand and request your users increase the gas limit in their transactions to at least that value. If they don't the transaction will fail costing them the transaction cost but returning any ether they attempted to send. – willjgriff Jan 19 '18 at 20:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.