Last article from blockchain, the concept of Ethereum, to decentralized applications, then to the language, framework, and finally listed some open source projects, I believe you have been introduced to Ethereum development. If you haven’t seen it, you can click on the link first.
Next we create and issue our own tokens step by step. Tokens in the Ethereum ecosystem can represent anything that can be traded, such as coins, gold, tokens, and game items. All tokens in Ethereum follow basic rules and protocols, so our tokens are compatible with Ethereum wallets and other clients and smart contracts that follow the same rules.
Tokens contracts
Standard token contracts can be quite complex, so let’s start with a simple stress test.
Pragma solidity ^ 0.4.16; interface tokenRecipient {function receiveApproval(
address _from,
uint256 _value,
address _token,
bytes _extraData) public;
}
contract TokenERC20 { // Public variables of the token
string public name;
string public symbol;
// 18 decimals is the strongly suggested default, avoid changing it
uint8 public decimals = 18;
uint256 public totalSupply;
// This creates an array with all balances
mapping (address => uint256) public balanceOf;
// This generates a public event on the blockchain that will notify clients
mapping (address => mapping (address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
// This notifies clients about the amount burnt
event Burn(address indexed from, uint256 value);
/**
* Constructor function
*
* Initializes contract with initial supply tokens to the creator of the contract
*/
function TokenERC20(
uint256 initialSupply,
string tokenName,
string tokenSymbol
) public {
// Update total supply with the decimal amount
totalSupply = initialSupply * 10 ** uint256(decimals);
balanceOf[msg.sender] = totalSupply;
name = tokenName;
symbol = tokenSymbol;
}
/**
* Internal transfer, only can be called by this contract
*/
function_transfer(address _from, address _to, uint _value) internal { // Prevent transfer to 0x0 address. Use burn() instead require(_to ! = 0x0); // Checkif the sender has enough
require(balanceOf[_from] >= _value);
// Check for overflows
require(balanceOf[_to] + _value > balanceOf[_to]);
// Save this for an assertion in the future
uint previousBalances = balanceOf[_from] + balanceOf[_to];
// Subtract from the sender
balanceOf[_from] -= _value;
// Add the same to the recipient
balanceOf[_to] += _value;
Transfer(_from, _to, _value);
// Asserts are used to use static analysis to find bugs in your code. They should never fail
assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}
/**
* Transfer tokens
*
* Send `_value` tokens to `_to` from your account
*
* @param _to The address of the recipient
* @param _value the amount to send
*/
function transfer(address _to, uint256 _value) public {
_transfer(msg.sender, _to, _value);
}
/**
* Transfer tokens from other address
*
* Send `_value` tokens to `_to` on behalf of `_from`
*
* @param _from The address of the sender
* @param _to The address of the recipient
* @param _value the amount to send
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]); // Check allowance
allowance[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
/**
* Set allowance forother address * * Allows `_spender` to spend no more than `_value` tokens on your behalf * * @param _spender The address authorized to spend * @param _value the max amount they can spend */function approve(address _spender, uint256 _value) public
returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
/**
* Set allowance for other address and notify
*
* Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it
*
* @param _spender The address authorized to spend
* @param _value the max amount they can spend
* @param _extraData some extra information to send to the approved contract
*/
function approveAndCall(address _spender, uint256 _value, bytes _extraData)
public returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
/**
* Destroy tokens
*
* Remove `_value` tokens from the system irreversibly
*
* @param _value the amount of money to burn
*/
function burn(uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
balanceOf[msg.sender] -= _value; // Subtract from the sender
totalSupply -= _value; // Updates totalSupply
Burn(msg.sender, _value);
return true;
}
/**
* Destroy tokens from other account
*
* Remove `_value` tokens from the system irreversibly on behalf of `_from`.
*
* @param _from the address of the sender
* @param _value the amount of money to burn
*/
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(balanceOf[_from] >= _value); // Check if the targeted balance is enough
require(_value <= allowance[_from][msg.sender]); // Check allowance
balanceOf[_from] -= _value; // Subtract from the targeted balance
allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance totalSupply -= _value; // Update totalSupply Burn(_from, _value); return true; }}Copy the code
Still scared, ha ha ~ I was scared too at first.
Let’s try something more basic:
contract MyToken {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(uint256 initialSupply) {
balanceOf[msg.sender] = initialSupply;
// Give the creator all initial tokens
}
/* Send coins */
function transfer(address _to, uint256 _value) {
require(balanceOf[msg.sender] >= _value);
// Check if the sender has enough
require(balanceOf[_to] + _value >= balanceOf[_to]);
// Check for overflows
balanceOf[msg.sender] -= _value;
// Subtract from the sender
balanceOf[_to] += _value;
// Add the same to the recipient
}
}
Copy the code
The contract is fairly simple, with a state variable used to store the balances of all accounts and a transfer function ().
Next we write the MyToken code step by step. Go to the Ethereum website to download the Ethereum Wallet, install the wallet, and select Rinkeby Testnet. After entering the wallet, first select wallet, add Account below, and then enter the password to add it directly.
Click the Contract TAB to go to the Contract screen, and then click Deploy New Contract to Deploy the New contract.
Enter the following code in the Solidity Contract Source Code edit box:
contract MyToken {
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
}
Copy the code
Here we declare a variable balanceOf of type mapping, which can be understood as a Java HashMap. The public keyword, which indicates that a variable can be accessed by all nodes on the blockchain. Solidity automatically generates getter methods for variables of type public.
This contract is not useful at the moment, because we haven’t generated any tokens, so if a contract tries to get the amount of our tokens, the result is 0. We create some tokens at contract deployment time and add the following code at the end of the code:
function MyToken() {
balanceOf[msg.sender] = 21000000;
}
Copy the code
The function, with the same name as the contract, acts as a C constructor and is executed only when the contract is first deployed. After deploying the contract, the contract creator msG. sender will have 21 million tokens. Here we have written the value in code. A better way is to provide an argument to the constructor and let the contract author fill it in, as follows:
function MyToken(uint256 initialSupply) public {
balanceOf[msg.sender] = initialSupply;
}
Copy the code
Look to the right of the wallet and select MyToken from the drop-down list. You will see an edit box that lets you enter the constructor parameters.
Next add the transfer function for our tokens.
/* Send coins */
function transfer(address _to, uint256 _value) { /* Add and subtract new balances */
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
}
Copy the code
When the function is called, the caller msg.sender directly subtracts the corresponding number of tokens, and the receiver gets the corresponding number of tokens. There are two questions:
-
If the caller tries to send more tokens than his or her balance, our contract will be negative;
-
If the _value value is too large, the recipient’s balance may also overflow.
To avoid these two situations, we can use previous experience to determine whether a return or throw throws an exception if the condition is not met. Either way, we can release a new version and update it later. Contracts, however, cannot be changed or taken offline once deployed. And the throw wastes the caller’s gas. With these two considerations in mind, all data should be checked before contract deployment to ensure that exceptions do not occur. Solidity provides the require() method and we modify the code as follows:
function transfer(address _to, uint256 _value) {
/* Check if sender has balance and for overflows */
require(balanceOf[msg.sender] >= _value && balanceOf[_to] + _value >= balanceOf[_to]);
balanceOf[_to] += _value;
}
Copy the code
Now the transfer function is available. However, our token is missing a name and symbol, declaring the corresponding state variable directly in the code:
string public name;
string public symbol;
uint8 public decimals;
Copy the code
Assign values to variables in the constructor so that we have the flexibility to name our tokens at deployment time.
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(uint256 initialSupply, string tokenName, string tokenSymbol, uint8 decimalUnits) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
name = tokenName; // Set the name for display purposes
symbol = tokenSymbol; // Set the symbol for display purposes
decimals = decimalUnits; // Amount of decimals for display purposes
}
Copy the code
In order for the wallet and other clients to be notified of the token, we finally add Events to the token. Events are a handy tool to use the EVM logging built-in functionality, which in turn invokes Javascript’s listening event callbacks in the DAPP interface. The event statement:
event Transfer(address indexed from, address indexed to, uint256 value);
Copy the code
Call events in the Transfer () function:
/* Notify anyone listening that this transfer took place */
Transfer(msg.sender, _to, _value);
Copy the code
At this point, MyToken development is complete.
Deployment of tokens,
Fill in the parameters required by the constructor, and your wallet interface should look something like this:
Pull to the bottom and set the amount of Ether you are willing to spend for token deployment. You can either leave the default or set it a little bit more, because the remaining ether will be returned to us, and less ether will take more time to complete deployment.
Click the Deploy.
Enter the password to submit the deployment. Once deployed, you can play with your tokens, such as forwarding them to your friends. Click the SEND TAB next to the WALLET TAB, input your friend’s WALLET address, token number, select your own token (default is Ether), and click SEND.
But right now your friend’s wallet can’t see the tokens you sent him, because ethereum wallets only track the currencies it knows, and we need to manually add our newly created tokens to the wallet.
First go to the contract interface you just created to copy the contract address, click Watch Token, and paste the contract address, name, symbol and other fields in the pop-up dialog box should be automatically filled.
Click ok so our wallet will be notified of any changes to our tokens.
The last
Deployment of contracts requires the etheric pesetas Rinkeby test network Ethernet coin available free at https://faucet.rinkeby.io/. If you can’t use the Internet scientifically, you can try it on remix.
Follow my wechat official account:
Friend me: