Ethereum Crowdsale Discussion

Hmm, sorry about that. I thought superblocks would support that. Hopefully I will have updated the lecture today or tomorrow with new code. Until then you can either rename the constructors to the old notion of function instead of constructor().

You can also try the latest superblocks version over at lab.superblocks.com.

I have replaced it now. Check it out here: https://github.com/filipmartinsson/Issue-your-own-ERC20-token/blob/master/contracts/erc20_tutorial.sol

When I find the time I will upgrade the entire section to the newest soildity version.

That seems to have worked, thank you!

1 Like

Hi Filip!

Could you please update the crowdsale and token contract so that they will compile using solidity ^0.5.1 and remix?

I’ve spent a lot of time trying to get those running but there are so many syntax changes in 0.5.1 so that it is really frustrating… Would really appreciate it if you could update it.

Thanks a lot!
Lars

All of the Ethereum parts will be updated next months. It will be up to date with the newest solidity version available at the time. In the meantime I would recommend you to use openzeppelins solidity contracts for tokens. In the Ethereum Game Programming course I show you how Openzeppelin works.

@filip function totalSupply() public view returns (uint) {
return _totalSupply - balances[address(0)];
}
Why are we using balances[address(0)]? What does this mean?

@filip function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
return true;
}
In the above function, ApproveAndCallFallback is a contract. We give sender as an argument. I guess it is to instantiate the contract. What does giving sender as the argument do exactly? And what is the “data” variable whose datatype is “bytes”?

  1. balances() for address 0 would be tokens that we have “burned”. Tokens that are no longer in supply and should therefor be subtracted from the original totalSupply.

  2. The ApproveAndCallFallback is a function, not a contract. And it doesn’t take sender as the argument, it takes a spender. It’s quite a complex function that we are not using, but I will try to explain it.

The function does 2 things. It first approves the spender to transfer some amount of tokens, setting the allowed mapping for the spender. This means that we allow the spender address to be allowed to use our tokens (owner by msg.sender).

The second thing it does is that is calls the fallback function of the spender address. This is were data comes in, data would be the input for the fallback function, which can vary depending on the fallback function.

You can read more about it here: https://ethereum.stackexchange.com/questions/43158/anyone-knows-what-does-this-contract-code-mean

@filip It is still not clear. ApproveAndCallFallback is a contract. Please check. “approveAndcall” is a function. I clearly understand that when the function approveAndcall is called, msg.sender approves some address to spend tokens on his behalf. And then we call ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);What does this do? we are sending the spender address to the contract ApproveAndCallFallBack and then calling its function receiveApproval.

I’m sorry, my bad. You are correct, I mixed them up.

So this line:

ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);

It will initiate a contract instance from the interface ApproveAndCallFallBack. And to answer your original question. We provide the spender address in order to initate the contract instance, yes.

If we have an interface and we want to create a contract instance out of that code, we need the address of where that contract is. That is the spender address in this case. Then it will call the receiveApproval function of that contract. Which you could read more about in the link that I gave you.

Sorry for the confusion. I didn’t read through your question carefully enough.

@filip. thanks for the reply. I get the following concept.
Please correct me if I am wrong. Interfaces are basically like templates so that everyone can use it to create contract instance just using these templates and then finally give an address because a contract needs an address.
e.g-contract’x’has an address “0x1"on the blockchain. Now someone uses the interface’x’ and gives an address"0x2” to instantiate the contract so that a new contract with same functionality is created at address"0x2".
As far as the exchanges are concerned(from the explaination in the link: https://ethereum.stackexchange.com/questions/43158/anyone-knows-what-does-this-contract-code-mean), what happens is that the exchange already has some tokens in its account. Suppose 1000 tokens. Now when exchange receives money from a client, exchange calls the function approveAndCall(client,200tokens,data) from the token contract, gives the client the permission to transfer 200 tokens from exchange’s account. Now instead of waiting for the client to approve it creates a contract instance in the name of client by ApproveandCallFallBack(client).receiveApproval().This receiveApproval automatically approves on the behalf of client and thus transfers 200 tokens to the client’s address.
Is this correct?

@filip How to interact with the events emitted. I want a seller to get a notification when a buyer makes the payment using the event omitted.

Interfaces are basically like templates so that everyone can use it to create contract instance just using these templates and then finally give an address because a contract needs an address.

Yes, that’s basically correct. It’s like a specification of the structure of a contract.

Now when exchange receives money from a client, exchange calls the function approveAndCall(client,200tokens,data) from the token contract, gives the client the permission to transfer 200 tokens from exchange’s account. Now instead of waiting for the client to approve it creates a contract instance in the name of client by ApproveandCallFallBack(client).receiveApproval().This receiveApproval automatically approves on the behalf of client and thus transfers 200 tokens to the client’s address.

No I don’t think your description is correct. The step by step provided in the page I linked is accurate.

  • they call approveAndCall in the token contract which verifies the transfer is possible.
  • the token contract calls them (or their surrogate contract) back via receiveApproval .
  • the receiveApproval function does the funds transfer (or other action) as required.
  • the token contract gets control back and performs the token transfer.
  • if any one thing fails, it all fails together and no cleanup is required.

You can do it in your frontend code using web3.js. I think I show this in one of the courses, but not 100% sure.

web3.eth.subscribe('logs', options [, callback]);

https://web3js.readthedocs.io/en/v1.2.0/web3-eth-subscribe.html#subscribe-logs

@filip If I have an event named Inform(address indexed buyer, address indexed seller). Now in the app.js I define a variable as var subscription=web3.eth.subscribe(‘logs’,{address: CONTRACT ADDRESS,
topics:[null,‘SELLER ADDRESS’]},function(error, result){
if (!error)
console.log(result);
})
What does the ‘topics’ array do? Does the above code mean that every event on the contract address that has seller address as the second argument and is emitted in the contract will be console.logged?

@filip In the init function in app.js I created a variable named subscription = web3.eth.subscribe. with the required args but at the time of document.ready console shows an error that web3.eth.subscribe is not a function.

Hey @filip,

I have tried create dapp for ico of the coin, but it is not working.

I created both contracts, then I deployed them (I don’t know if properly, because there were again these questions about arguments in the constructor “Contract did not get deployed. Wrong arguments to constructor?”, but I got the addresses of them from etherscan) and in the end the “View” says “Missing contract javascript file, have you deployed all contracts?”. I have checked the settings for external account to be sure it is connected to Rinkeby, everything is set properly and I don’t know how to deal with it.

BTW Remix proccesses them without any groans.

Beside that I would like to ask if I can do sth like that in the app.js:

instance.totalAmountRaised(function (error, result){
}

or I can only use getters in that case?

I’m leaving code of these files:
GitHub Code

You can find more information about topics here: https://ethereum.stackexchange.com/questions/12950/what-are-event-topics

Make sure that you google your questions before you ask me. It saves me a lot of time that I can put into the academy :slight_smile:

Regarding your code, if you are using superblocks then the web3.js version is quite old and outdated. The old function, the one you need to use, is filter.watch. It’s very similar to subscribe, you can check it out here: https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethfilter

Sorry for linking you a function that is not available in superblocks. But I would recommend you to step out of superblocks if you want to continue to develop more advanced dapps. Truffle is really a better tool for that. More complex, but way better. The next solidity dapp course I’m making, will be with Truffle.

Well, I’m not sure I understand you 100%. If you got the error message “Contract did not get deployed”, then that is why it’s not working. You need to deploy them successfully.

Are you deploying locally? If so, you can’t use Etherscan since it’s on either Mainnet or Testnet.

The error message you are getting probably means that you haven’t set the constructor arguments properly. First of all, check how many constructor arguments you have. For the coin contract, you have zero. Then go into your contract configuration in Superblocks. Contracts -> Name of Contract -> Configure and set the nr of arguments to zero in that case.

Then do the same for your ICO contract. Except that this contract has 5 arguments, which you need to setup.

image

As to your second question. I assume that you asked about how you do a setter call?

We do that in the course when we call the update function in the HelloWorld dapp.

instance.update.sendTransaction(newMessage, {from: "0xa9e73bb65b54c445081dae9d67f08ccbcce8bcb7", gas: 30000000}, function(error, result){
                if(error){
                    //handle error
                }
                else{
                    //Do something
                }
            });

I hope that helps. Good luck :slight_smile:

1 Like

Yeah, you are right I didn’t think about increasing amount of arguments in the ICO contract, I also had some problems because I forgot to change the name of the constructor.

  1. Do you have idea how can I implement function to check how many tokens are left to buy?

I have tried this code, but it doesn’t return anything. I think it needs return statement, but the compailer is giving the error:

TypeError: Different number of arguments in return statement than in returns declaration.
return token.balanceOf(address(this));

interface DubCoin {
    function transfer (address receiver, uint amount);

    function balanceOf (address ico);
}

function getLeftTokens() public view returns(uint balance) {
        token.balanceOf(address(this));
    }

Code in app.js

function getLeft() {
        instance.getLeftTokens(function (error, result) { 
            if(error){
              alert(error);
            }
            else{
              $("#tokens").html(result.toString());
            }
        });
    }
  1. I would like to ask you about deploying contracts beyond the browser. I mean I have installed truffle (your video about truffle on youtube really helped), but I can’t find solution to deploy the contract on the rinkeby testnet. I read that I need hdwalletprovider, but I can’t install it through npm. I’m not sure if I understand it correctly, that Truffle has moved all modules to a monorepo at trufflesuite/truffle, it means that the hdwalletprovider is now inside the truffle which I have already installed, but I can’t find info how to use it, to execute sth like that:
module.exports = {
  rinkeby: {
       provider: function() {
           return new HDWalletProvider(mnemonic, "rinkeby.infura.io/v3/InfuraAPI");
       },
       network_id: '1',
   },
};

BTW I feel that programming on windows is a little bit harder compared to mac if it is related to npm, because I couldn’t e.g. execute your method from the video HalloWorld.at(‘address’).getName.call() - powershell throws an error.

  1. I have problem with withdraw ETH back from contract.
function safeWithdrawal() public {
        if(!fundingGoalReached){
            uint amount = balanceOfShare[msg.sender];
            balanceOfShare[msg.sender] = 0;
            // if(amount > 0){
                msg.sender.transfer(amount);
                if(!msg.sender.send(amount)){
                    balanceOfShare[msg.sender] = amount;
                // }
            }
        } else if(fundingGoalReached && msg.sender == beneficiary){
            if(!beneficiary.send(totalAmountRaised)){
                fundingGoalReached = false;
            }
            
        }
    }

Code in the app.js

function withdraw(){
      instance.safeWithdrawal.sendTransaction({from: accounts[0], gas:100000, value:0}, function (error, result){
        if (error){
          alert(error)
        } else {
          $("#result").html("Withdraw proccesed.");
        }
      });
    }

The problem is that I don’t get my sent ETH back to the Metamask account and I can’t find solution.