Ethereum, tokens & smart contracts.

Notes on getting started Part 8. Crowdfunding and ICOs

Previous notes in case you are just joining us:
Part 1. Setting up.
Part 2. Web3.js/node.
Part 3. Solidity.
Part 4. Smart Contracts.
Part 5. Smarter Contracts.
Part 6. Tokens & Inheritance.
Part 7. ERC20 Token Standard.

Background:

One of the biggest ( if not the biggest ) appeal of the ethereum ecosystem is that of crowdfunding via tokens, the idea is that you create,compile and deploy a token like the ones we have been making, you attach a price or amount in ether which you receive to fund your project, we will be looking into the details in a bit. Further, since these tokens run on the EVM and are in essence a smart contract, they can be imbued with new behavior and characteristics.

An ICO or Initial Coin Offering (in case you were wondering) is usually a token sale backing a project which might or might not have some additional functionality,this functionality is usually explained in a white paper.

A big note about ICOs: Like any new and/or promising technology there are good and bad things attached to it.
Funding any project is usually not a pleasant or smooth event, so the idea of crowdfunding via token sales is an appealing experiment ( no more asking banks, vc's, rich relatives, etc,etc ),at the same time the relative ease and low cost by which you can make a token has resulted in thousands of ICOs, so there is now the added cost of sorting through them as an investor or user. 
Which ones are good and which ones are bad is a matter of due diligence and personal choice,each one of us needs to decide if we feel comfortable giving money to a project that might or might not work as intended with the available information.
Further complicating things there are legal matters depending on which country you live, in some countries ICOs are banned, in others they could be considered stocks if they pay dividends and then fall under that regulatory umbrella and in others they are allowed or overlooked for now.
In short, know beforehand what you are getting into as well as the risks & legal ramifications.

Ok, enough preamble,let’s go to the code.

Getting Paid in contracts.

So what would happen if we try to send Ether to a token or contract ? let’s see what happens (using parity for the visuals, but you can also use node.js/web3)…

The transaction along with the ether does not go through, yet we end up spending gas, here’s the Tx in etherscan:

Tx:0x506f24ca70e9dea24d778b1f1944ae0c1d759fa186d7871f02b15d2cb9f18e76

The reason is that we don’t have any method in our contract for receiving ethereum, a contract execution error happens and the VM execution continues until all of the gas limit is exhausted. So let’s make a simple contract that can receive ethereum…

// File blackHole.sol 
pragma solidity ^0.4.15;
contract blackHole {
function () public payable {}
}

There are 2 important things happening here:

1. function ()public {} is a fallback function : it will execute when no other function matches a call.

2. The payable keyword allows a function to receive ether, it is a modifier which we reviewed in the previous notes, and can be applied to other functions.

Let’s now deploy and try again:

txHash:0x7c447903a0e5a3b8c1c689063fc7ae67227b6ad733c41c69e4c8bb6ac1a961cf
Successfully deployed Contract with address: 0x52126db390716a8caf93160f4a0ee76c7649687a

After adding the contract to parity, no more warnings are displayed and we can now send Ether, the transaction goes ahead and the token itself will now show an ether balance, everything is great except for one crucial detail:

Super Important Note/ crucial detail: We can send ether into a contract, but how would we get it out again and exchange it for goods in ETH or exchange it for fiat currency ? 
We can't, it is possible, but not with this contract, hence the contract name, we have created a black hole for Ether, those 0.80 ETH will never ever again be able to be transfered from the Black Hole contract into any address and we have effectively burned some ether in the parlance of our times.
While this is only test ether with no monetary value ( just sentimental ) if you send real ether to a contract and it has a payable fallback function you have just trown money into a black hole. 

Let’s now figure out how to get our ether out.

// File tipJar.sol
pragma solidity ^0.4.15;
contract tipJar {
address private owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function tipJar() internal{
owner = msg.sender;
}
function () public payable {}
function collect(uint256 amount) onlyOwner public{
msg.sender.transfer(amount);
}
}
// Compile - Deploy:
Deploying contract...
txHash:0x64c1780f7ec0b8ec2d708ed690ff9b458c771e74cb215abaf2bd23f454142187
Successfully deployed Contract with address: 0x4f91122c95896acd33b61db5b0ba9e53dc018b77
And after Tipping the Tip Jar:

So now let’s try getting some ETH out of our Tip Jar Contract by using the collect function:

Success !, we can now retrieve our precious ether from a contract that also accepts ether from any address, let’s check the code:

Getting ether out of the tip jar:
The new behavior (transfering ether from the contract) is taken care by the transfer function which is part of solidity:
Members of Address: balance and transfer. (notice if you read the docs how it's not the only way to transfer).
function collect(uint256 amount) onlyOwner public{
msg.sender.transfer(amount);
}
The argument for transfer is denominated in wei (uint256 amount), so if we want to transfer 0.20 ether out, we need to convert it into 200000000000000000 wei.

The other new thing in this function is the use of a modifier (onlyOwner), which we explained last notes, here it checks that the only address allowed to collect from the Tip Jar is the owner.
A note about costs: 0.00002965 gas was paid for the Tip Jar Token when we collected our 0.20 ETH, what this means is that the account initiating the transfer is responsible for the transaction costs.

So now that we have a way of getting Ether in and out of a contract, we need to incorporate this into an ERC20 Token and we will almost be there, I say almost because adding extra functionality is a complex subject we will cover in future notes.

You give me Ether I give you Blips:

Let’s design a new token: Our new token will have an unlimited supply, will be able to receive Ether and give back tokens, and of course the owner will be able to retrieve the Ether, it will also be an ERC20 Token, our contract will mint these tokens which I am calling blips.

// File Mint.sol
pragma solidity ^0.4.0;
contract Mint {
string public constant symbol = "BLIPS";
string public constant name = "Blips Token";
uint8 public constant decimals = 18;
uint256 public totalSupply = 0;
address public owner;
uint256 public rate = 100000000000000;
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
function Mint() public{
owner = msg.sender;
}
function () public payable {
create(msg.sender);
}
function create(address beneficiary)public payable{
uint256 amount = msg.value;
if(amount > 0){
balances[beneficiary] += amount/rate;
totalSupply += amount/rate;
}
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function collect(uint256 amount) onlyOwner public{
msg.sender.transfer(amount);
}
function transfer(address _to, uint256 _amount) public returns (bool success) {
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
Transfer(msg.sender, _to, _amount);
return true;
} else {
return false;
}
}
function transferFrom(
address _from,
address _to,
uint256 _amount
) public returns (bool success) {
if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[_from] -= _amount;
allowed[_from][msg.sender] -= _amount;
balances[_to] += _amount;
Transfer(_from, _to, _amount);
return true;
} else {
return false;
}
}
function approve(address _spender, uint256 _amount) public returns (bool success) {
allowed[msg.sender][_spender] = _amount;
Approval(msg.sender, _spender, _amount);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
// Compiling Deploying:
Deploying contract...
Deploying contract...
txHash:0x0eab8e3e37d539bd7859939e312a5529fbab8013c49eb33500cb1451c860f0a7
Successfully deployed Contract with address: 0xcceef52df5ff1b80e63e3f211021bd0bae5323d6
Note: I've been gradually adding more gas to the transactions until they pass since estimates are not 100% correct at this time, having such an open supply also generates considerably more gas costs (630,669 vs an estimate of 615,669) while this might seem a lot,if you were to convert that into fiat in the real network it would be about $1.28 at current prices, not bad for recreating a central bank.

Let’s add it first to parity:

As designed, it has an initial supply of 0 blips and has no Ether, let’s correct that by sending some ether and see what happens:

let’s send more ether from a different account ( sending from A2,0.12 Ether):

A1 and A2 now have exchanged some ether for Blips and the BLIPS token contract has an ether balance, the total supply has also increased to reflect that. Before collecting the ether, let’s review the new code we added to the erc20.

The new behavior revolves around a few new variables and 2 functions ( the rest is identical to the erc20 from previous notes):
// Variables:
uint256 public totalSupply = 0;
uint256 public rate = 100000000000000;
function () public payable {
create(msg.sender);
}
function create(address beneficiary)public payable{
uint256 amount = msg.value;
if(amount > 0){
balances[beneficiary] += amount/rate;
totalSupply += amount/rate;

}
}
  • The first difference is that we start with an initialSupply of 0 (zero), since we will be creating blips as folks deposit ether.
  • Creation of new blips starts when ether is received, our fallback function receives it and calls the create function passing the msg.sender as an argument(the msg is apparently also available as a global)
  • The create function (which needs to be payable), first gets the ether amount (msg.value) and then checks to see if it’s bigger than zero, then it alocates a balance to the beneficiary ( this is where blips are created ) and increases the totalSupply.
Note: calculating the exchange rate is complicated by the fact that operations are made in wei, 1 ether =  1,000,000,000,000,000,000 wei or 1 ether = 1 Quintillion wei !
When designing this blips token, I wanted to give out 10,000 blips for each ether,so 10,000 blips = 1 Ether.
The amount we are receiving is denominated in wei, so 10,000 blips =
1,000,000,000,000,000,000 wei and 1 blip is thus 100,000,000,000,000 wei which explains our rate variable:
int256 public rate =  100000000000000;
And our final conversion when creating:
totalSupply += amount/rate;
Why not use decimals ? in a word solidity doesn't support them today, but it might in the future, so we need to deal with this situations with fixed point math like we just did.

Getting paid.

So we issued our blips tokens in exchange for something and we received some ether, now all we need to do is retrieve said ether and exchange it for fiat or products.

To do so, we will use the collect function we covered in the tip jar example, it is identical:

function collect(uint256 amount) onlyOwner public{
msg.sender.transfer(amount);
}

The only thing that changes is that as the owner of the token you need to add it as custom contract or interact with it via web3 to have access to the collect function. We will try the first option, note all the extra information we get:

And now we have access to the collect function:

The owner account is the only one allowed to collect like in our tip jar example, trying to collect from another account would result in an error ( it will throw an exception, no collection will happen and some gas will be lost ).

Is that it ? Well, we’ve come a long way since we started and you are welcome to leave here and start developing smart contracts, if you want to stay with me though, we will tie smart contracts with Dapps and look into more complex contracts in the next few notes, for now you know the drill, let’s recap:

  • Notes Part 1 : Setting up : Getting a wallet/client , connecting to a test Ethereum blockchain and getting some test ether.
  • Notes Part 2: web3.js/node : Interacting with the blockchain through web3.js and node for more convenience and ease of development.
  • Notes Part 3: Solidity : Installing solidity (Ethereums contract writing language ) , Creating a very basic contract, compiling it, deploying it to the blockchain ( the test one) and interacting with it.
  • Notes Part 4: Smart Contracts: We modified our simple contract so we could store and retrieve information (making it smart), in the process we also covered how to watch the blockchain and contracts and finally we took a look at gas and how to estimate it.
  • Notes Part 5: Smarter Contracts: In order to allow contracts more complex behavior (make them smarter) , we need to delve a bit deeper into contract creation via constructors and a few more complex types which we will use in making a token contract.
  • Notes Part 6: Tokens & Inheritance: We made our first Token and interacted with it by transfering some of it from one account to another, we also briefly covered inheritance which is used in more complex contracts.
  • Notes Part 7: ERC20 Token Standard: We made and deployed an erc20 token which can be considered the parting standard for working sub currencies. We examined the code and talked about transfers in between tokens.
  • Notes Part 8: Crowdfunding and ICOs: (This post) We explored the subject of crowdfunding via smart contracts in the form of ICOs and the exchange of ether for tokens, we made contracts that can receive ether, collect ether and can be used for exchanging ether and creating an unlimited supply of tokens.
Get the Book ! 🙏 😊
If you are looking for an introduction to Ethereum, Solidity and Smart Contracts these notes were edited and revised into a convenient book!
Available in ebook and paperback:
https://www.amazon.com/dp/B078CQ8L7V

Cheers !

Keno

About the Author :

Born Eugenio Noyola Leon (Keno) I am a Designer,Web Developer/programmer, Artist and Inventor, currently living in Mexico City, you can find me at www.k3no.com