create account

(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14) by igormuba

View this thread on: hive.blogpeakd.comecency.com
· @igormuba ·
$35.40
(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)
#### Repository
https://github.com/igormuba/EthereumSolidityClasses/tree/master/class14

#### What Will I Learn?
- What is fungibility
- How to make unique tokens
- Unique tokens transaction

#### Requirements

- Internet connection
- Code editor
- Browser

#### Difficulty

- Intermediate

#### Tutorial Contents

An Ethereum development pattern that is getting more common is the ERC721. The ERC721 compliant contracts allow you to build unique non-fungible tokens.

We won't cover the ERC721 standard yet, but I will show you how you can create unique tokens with just a few lines of Solidity code, this way you can understand how uniqueness an non-fungibility works before you really get started on fitting your contract on the ERC721 pattern.

# Our token
The token we will build in not fungible. A fungible token is a token that can be mixed with other and is no different from other tokens. A not fungible token is a token that is unique and you can identify it.

An example of non-fungible currency is gold. If you steal gold from a bank, sure, it comes with some kind of print or marks to show from what bank it came from, but once you melt it you can sell as if you found it. A non-fungible currency, on the other hand, can be the paper dollar. Each dollar has a unique ID, though every dollar has the same value, if you steal from a bank and you want to deposit the stolen dollar, theoretically they can track you by the id of the bill!! Differently, from gold, you can't melt dollars!

So our token will have an "id" and an indicator of who owns it.

We will also implement a very simple and rudimentary internal market on the contract, which will allow you to set the price of a token, sell, and withdraw into your wallet.

# Unique token structure
The code below creates the structure for the tokens we will mint. As you can see each token is unique.

```
pragma solidity ^0.5.0; //solidity version

contract uniqueToken{ //contract declaration
    struct ourToken{ //token structure
        uint id; //unique ID
        string name; //token name
        uint value; //token value (price, we will see it shortly)
        address owner; //owner of the token
    }
}
```

Here is what each variable of the structure stands for and how we will work with it
`id` each token will have a unique ID that will automatically be assigned to it upon creation
`name` the name we give to the token, this variable, differently from the id, is not unique and will be passed into it as an argument upon creation of the token
`value` when creating the token we will be able to set a price to it, so if someone wants to buy it from the contract the person will be able to  buy it at the price we have set, the price will be set upon token creation but we will create a function to change its value later
`owner` wallet that owns the token

# Token id

Before the struct code(or right after) declare a private variable, that will hold the value of the current ID, this will allow us to, later, assign a unique ID to each token

```
pragma solidity ^0.5.0;

contract uniqueToken{
    uint private currentId=0; //current ID that will automatically be assigned to the token
    struct ourToken{
        uint id;
        string name;
        uint value;
        address owner;
    }
}
```

# Storage for created tokens and owners

I am using the following variables to store the created tokens and the owners
```
    ourToken[] tokens; //list of created tokens
    mapping(uint => address) public ownership; //mapping token to owner
```
here is how each variable will work
`tokens` this is an array that will, in order of creation, store the generated tokens
`ownership` is a mapping that, given the ID of a token, it gives us who owns. We could use the list above to get the owner but a mapping would save us computing time and provide a backup proof of ownership

# Token market

The buying and selling of tokens will happen internally on the contract. For this, we need to store the balance of users, so when they sell a token their balance increases, they will, later, be able to withdraw their balance.

```
mapping(address=>uint) public balance; //maps user balance
```

# Token creation

The way this contract is designed, anyone can create its own token and set the name and price. Upon creation, the token is assigned to the creator.
```
function createToken(string memory _name, uint value) public{//receives name and price of the token
        tokens.push(ourToken(currentId, _name, value, msg.sender)); //creates token and adds to the array
        ownership[currentId]=msg.sender; //sets creator as owner
        currentId++; //sets the ID for the next token
    }
```
By saying `ourToken(currenctId, _name, value, msg.sender)` we are, effectively, setting the variables defined in the `struct` previously, so
`ourToken(1, "igor", 10, 0xca35b7d915458ef540ade6068dfe2f44e8fa733c)` 
would generate the struct
```
ourToken{
    uint id=1; //ID 1 given automatically from the global variable
        string name="igor"; //name given on the builder
        uint value=10; //price set to 10wei
        address owner=0xca35b7d915458ef540ade6068dfe2f44e8fa733c; //random wallet I have used as example
}
```

# Token getters

It is important that we can see 2 things from the token
- price
- owner

For this, we can use the following functions

```
    function tokenValue(uint _id) public view returns (uint){ //receives a token ID
        return tokens[_id].value; //returns the price of given token
    }
    
    function tokenOwnership(uint _id) public view returns(address){ //receives token ID
        return ownership[_id]; //returns owner of given token
    }
```

The `ownership` mapping is useful in this case.

Our contract so far looks like
```
pragma solidity ^0.5.0;

contract uniqueToken{
    uint private currentId=0;
    struct ourToken{
        uint id;
        string name;
        uint value;
        address owner;
    }
    ourToken[] tokens;
    mapping(uint => address) public ownership;
    mapping(address=>uint) public balance;
    
    function tokenValue(uint _id) public view returns (uint){
        return tokens[_id].value;
    }
    
    function tokenOwnership(uint _id) public view returns(address){
        return ownership[_id];
    }
    
    function createToken(string memory _name, uint value) public{
        tokens.push(ourToken(currentId, _name, value, msg.sender));
        ownership[currentId]=msg.sender;
        currentId++;
    }
}
```

We still need to implement the functions to be able for someone to buy a token from someone else

# Token buy function
The following function will receive a payment from the message sender, store the payment received on the token contract and save the new balance of the seller. It is important, first, to check if the sent value is equal to or greater than the price the owner asks for the token

```
    function buyToken(uint _id) payable public{ //receives the ID of the wanted token
        require(msg.value>=tokens[_id].value); //throws error if buyer sends less than asked price
        balance[tokens[_id].owner]+=msg.value; //adds credit to seller balance
        tokens[_id].owner = msg.sender; //changes ownership of the token itself
        ownership[_id] = msg.sender; //changes ownership on the "backup" mapping
    }
```

# Changing token price

The contract must allow the owner of the token, and only the owner, to change the price he wants for a said token. The function I designed for it is
```
    function changeValue(uint _id, uint newValue) public{ //receives token ID and new price
        require(ownership[_id]==msg.sender); //throws error if the caller is not the owner of the given token
        tokens[_id].value=newValue; //sets the new value for the token
    }
```

The `require(ownership[_id]==msg.sender);` ensures that only the real owner of the token can change the asked price, else anyone would be able to get any token for free

# Check seller balance and withdraw

Once a token is sold the user will receive credit on its balance inside the contract. The ETH (wei) paid for the token will be stored on the contract. We must allow users to check their balances and withdraw the ETH from their sales.

```
    function myBalance() public view returns (uint){
        return balance[msg.sender];//shows balance inside the contract from caller
    }
    
    function withdraw() public{
    uint toSend = balance[msg.sender];
    balance[msg.sender]=0;
        msg.sender.transfer(toSend); //sends the balance to the caller
    }
```

You could improve the security, but I believe the implemented redundant security measures from the sell function are enough as the withdraw function withdraws all the balance from the user and before it sends it ensures that it cleans the balance first to avoid async exploits.

# How the contract looks in the end

```
pragma solidity ^0.5.0;

contract uniqueToken{
    uint private currentId=0;
    struct ourToken{
        uint id;
        string name;
        uint value;
        address owner;
    }
    ourToken[] tokens;
    mapping(uint => address) public ownership;
    mapping(address=>uint) public balance;
    
    function tokenValue(uint _id) public view returns (uint){
        return tokens[_id].value;
    }
    
    function tokenOwnership(uint _id) public view returns(address){
        return ownership[_id];
    }
    
    function createToken(string memory _name, uint value) public{
        tokens.push(ourToken(currentId, _name, value, msg.sender));
        ownership[currentId]=msg.sender;
        currentId++;
    }
    
    function buyToken(uint _id) payable public{
        require(msg.value>=tokens[_id].value);
        balance[tokens[_id].owner]+=msg.value;
        tokens[_id].owner = msg.sender;
        ownership[_id] = msg.sender;
    }
    
    function changeValue(uint _id, uint newValue) public{
        require(ownership[_id]==msg.sender);
        tokens[_id].value=newValue;
    }
    
    function myBalance() public view returns (uint){
        return balance[msg.sender];
    }
    
    function withdraw() public{
        uint toSend = balance[msg.sender];
        balance[msg.sender]=0;
        msg.sender.transfer(balance[msg.sender]);
    }
    
}
```

# Testing in practice

Finally, I am using Remix browser IDE to test how the token works. The prices are set in Wei. For reference 
1 ETH = 1000000000000000000 Wei (there are 18 zeroes there)

I have created the token "Igor" and it's ID automatically was set to zero and price of 1000000000000000000 Wei
![image.png](https://files.steempeak.com/file/steempeak/igormuba/clEtqgc6-image.png)

The account that owns the token is 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c and you can see on the screenshot that it shows the correct ownership

I have switched to the account 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c and if I buy the token with ID 0

The ownership has changed


And the account 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c balance is up on the contract
![image.png](https://files.steempeak.com/file/steempeak/igormuba/KGJq66WA-image.png)
![image.png](https://files.steempeak.com/file/steempeak/igormuba/RUZYrnKN-image.png)
 
Withdrawing from the sellers' contract balance

![image.png](https://files.steempeak.com/file/steempeak/igormuba/0KiABFcr-image.png)

#### Curriculum
- [(Part 13) Ethereum Solidity In Truffle - Testnet Environment Function Calls And Truffle Testing(PT 13)](https://steemit.com/utopian-io/@igormuba/part-13-ethereum-solidity-in-truffle-testnet-environment-function-calls-and-truffle-testing-pt-13)
- [(Part 12) Ethereum Solidity - Using Truffle, Ganache And Zeppelin To Deploy(PT 12)](https://steemit.com/utopian-io/@igormuba/part-12-ethereum-solidity-using-truffle-ganache-and-zeppelin-to-deploy-pt-12)
- [(Part 11) Ethereum Solidity - Multisig Contract As Bank,k Multiple Users, And Where To Implement App Logic(PT 11)](https://steemit.com/utopian-io/@igormuba/part-11-ethereum-solidity-multisig-contract-as-bank-k-multiple-users-and-where-to-implement-app-logic-pt-11)
- [(Part 10) Ethereum Solidity - Multiple inheritances, Diamond Problem And Function Polymorphism(PT 10)](https://steemit.com/utopian-io/@igormuba/part-10-ethereum-solidity-multiple-inheritance-diaomond-problem-and-function-polymorphism-pt-10)
- [(Part 9) Ethereum Solidity Assembly - Return, Memory, Hexadecimal, Pointers, And Memory Addressing(PT 9)](https://steemit.com/utopian-io/@igormuba/part-9-ethereum-solidity-assembly-return-memory-hexadecimal-pointers-and-memory-addressing-pt-9)
- [(Part 8) Ethereum Solidity - Assembly, Reducing Costs And Creation Your Low-Level Expression(PT 8)](https://steemit.com/utopian-io/@igormuba/part-8-ethereum-solidity-assembly-reducing-costs-and-creation-your-low-level-expression-pt-8)
- [(Part 7) Ethereum Solidity - Fallback, Ethereum Fractions, And Collateral Backed Contract(PT 7)](https://steemit.com/utopian-io/@igormuba/part-7-ethereum-solidity-fallback-ethereum-fractions-and-collateral-backed-contract-pt-7)
- [(Part 6) Ethereum Solidity - Custom Variable Functionalities, Libraries, Using Libraries For Security(PT 6)](https://steemit.com/utopian-io/@igormuba/part-6-ethereum-solidity-custom-varaible-functionalities-libraries-using-libraries-for-security-pt-6)
- [(Part 5) Ethereum Solidity - Custom Access Modifiers, Security Breach Alerts, Assert And Require(PT 5)](https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-custom-access-modifiers-security-breach-alerts-assert-and-require-pt-4)
- [(Part 4) Ethereum Solidity Development - Inheritance, Working With Multiple Contracts And Simple Mutability(PT 4)](https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-development-inheritance-working-with-multiple-contracts-and-simple-mutability-pt-4)
- [(Part 3) Ethereum Solidity Development - Contract Mutability, DelegateCall And Calling Functions By Address(PT 3)](https://steemit.com/utopian-io/@igormuba/part-3-ethereum-solidity-development-contract-mutability-delegatecall-and-calling-functions-by-address-pt-3)
- [(Part 2) Ethereum Solidity Development - Deploying, Security And ERC20 Compliance(PT 2)](https://steemit.com/utopian-io/@igormuba/part-2-ethereum-solidity-development-deploying-securiy-and-erc20-compliance-pt-2)
- [(Part 1) Ethereum Solidity Development - Getting Started + Lower Level Explanation (PT 1)](https://steemit.com/utopian-io/@igormuba/part-1-ethereum-solidity-development-getting-started-lower-level-explanation-pt-1)

# Beneficiaries

This post has as beneficiaries
@utopian.pay with 5%
using the SteemPeak beneficiary tool
![image.png](https://files.steempeak.com/file/steempeak/igormuba/CZTbpzrU-image.png)
πŸ‘  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and 78 others
properties (23)
authorigormuba
permlinkpart-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14
categoryutopian-io
json_metadata{"community":"steempeak","app":"steempeak","format":"markdown","tags":["utopian-io","tutorials","ethereum","solidity","blockchain"],"users":["igormuba","utopian.pay"],"links":["https://github.com/igormuba/EthereumSolidityClasses/tree/master/class14","https://steemit.com/utopian-io/@igormuba/part-13-ethereum-solidity-in-truffle-testnet-environment-function-calls-and-truffle-testing-pt-13","https://steemit.com/utopian-io/@igormuba/part-12-ethereum-solidity-using-truffle-ganache-and-zeppelin-to-deploy-pt-12","https://steemit.com/utopian-io/@igormuba/part-11-ethereum-solidity-multisig-contract-as-bank-k-multiple-users-and-where-to-implement-app-logic-pt-11","https://steemit.com/utopian-io/@igormuba/part-10-ethereum-solidity-multiple-inheritance-diaomond-problem-and-function-polymorphism-pt-10","https://steemit.com/utopian-io/@igormuba/part-9-ethereum-solidity-assembly-return-memory-hexadecimal-pointers-and-memory-addressing-pt-9","https://steemit.com/utopian-io/@igormuba/part-8-ethereum-solidity-assembly-reducing-costs-and-creation-your-low-level-expression-pt-8","https://steemit.com/utopian-io/@igormuba/part-7-ethereum-solidity-fallback-ethereum-fractions-and-collateral-backed-contract-pt-7","https://steemit.com/utopian-io/@igormuba/part-6-ethereum-solidity-custom-varaible-functionalities-libraries-using-libraries-for-security-pt-6","https://steemit.com/utopian-io/@igormuba/part-4-ethereum-solidity-custom-access-modifiers-security-breach-alerts-assert-and-require-pt-4"],"image":["https://files.steempeak.com/file/steempeak/igormuba/clEtqgc6-image.png","https://files.steempeak.com/file/steempeak/igormuba/KGJq66WA-image.png","https://files.steempeak.com/file/steempeak/igormuba/RUZYrnKN-image.png","https://files.steempeak.com/file/steempeak/igormuba/0KiABFcr-image.png","https://files.steempeak.com/file/steempeak/igormuba/CZTbpzrU-image.png"]}
created2019-01-13 21:12:18
last_update2019-01-13 21:12:18
depth0
children5
last_payout2019-01-20 21:12:18
cashout_time1969-12-31 23:59:59
total_payout_value26.631 HBD
curator_payout_value8.769 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length14,682
author_reputation129,826,667,899,336
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries
0.
accountutopian.pay
weight500
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,332,296
net_rshares67,270,207,034,343
author_curate_reward""
vote details (142)
@portugalcoin ·
$10.62
Thank you for your contribution @igormuba.
After analyzing your tutorial we suggest the following:

- It still has some problems with punctuation in the text.

We are waiting for more tutorials! Good Work!

Your contribution has been evaluated according to [Utopian policies and guidelines](https://join.utopian.io/guidelines), as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, [click here](https://review.utopian.io/result/8/2-1-1-1-1-2-1-3-).

---- 
Need help? Chat with us on [Discord](https://discord.gg/uTyJkNm).

[[utopian-moderator]](https://join.utopian.io/)
πŸ‘  , , , , , , , , , , , , , , , , , , , ,
properties (23)
authorportugalcoin
permlinkre-igormuba-part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14-20190114t220700252z
categoryutopian-io
json_metadata{"tags":["utopian-io"],"users":["igormuba"],"links":["https://join.utopian.io/guidelines","https://review.utopian.io/result/8/2-1-1-1-1-2-1-3-","https://discord.gg/uTyJkNm","https://join.utopian.io/"],"app":"steemit/0.1"}
created2019-01-14 22:07:00
last_update2019-01-14 22:07:00
depth1
children2
last_payout2019-01-21 22:07:00
cashout_time1969-12-31 23:59:59
total_payout_value8.044 HBD
curator_payout_value2.575 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length657
author_reputation603,431,569,859,011
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,381,277
net_rshares18,173,488,788,249
author_curate_reward""
vote details (21)
@igormuba ·
Hi, thank you for the time spent into reviewing my work. I am sorry that my grammar is not as consistent as I wish it were, I am actively trying to improve.

Posted using [Partiko Android](https://steemit.com/@partiko-android)
properties (22)
authorigormuba
permlinkigormuba-re-portugalcoin-re-igormuba-part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14-20190115t004323322z
categoryutopian-io
json_metadata{"app":"partiko","client":"android"}
created2019-01-15 00:43:24
last_update2019-01-15 00:43:24
depth2
children0
last_payout2019-01-22 00:43:24
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length226
author_reputation129,826,667,899,336
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,386,102
net_rshares0
@utopian-io ·
Thank you for your review, @portugalcoin! Keep up the good work!
properties (22)
authorutopian-io
permlinkre-re-igormuba-part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14-20190114t220700252z-20190117t120644z
categoryutopian-io
json_metadata"{"app": "beem/0.20.9"}"
created2019-01-17 12:06:45
last_update2019-01-17 12:06:45
depth2
children0
last_payout2019-01-24 12:06:45
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length64
author_reputation152,955,367,999,756
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,497,096
net_rshares0
@steem-ua ·
#### Hi @igormuba!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
**Feel free to join our [@steem-ua Discord server](https://discord.gg/KpBNYGz)**
properties (22)
authorsteem-ua
permlinkre-part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14-20190114t221754z
categoryutopian-io
json_metadata"{"app": "beem/0.20.14"}"
created2019-01-14 22:17:57
last_update2019-01-14 22:17:57
depth1
children0
last_payout2019-01-21 22:17:57
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length287
author_reputation23,214,230,978,060
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,381,654
net_rshares0
@utopian-io ·
Hey, @igormuba!

**Thanks for contributing on Utopian**.
We’re already looking forward to your next contribution!

**Get higher incentives and support Utopian.io!**
 Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via [SteemPlus](https://chrome.google.com/webstore/detail/steemplus/mjbkjgcplmaneajhcbegoffkedeankaj?hl=en) or [Steeditor](https://steeditor.app)).

**Want to chat? Join us on Discord https://discord.gg/h52nFrV.**

<a href='https://steemconnect.com/sign/account-witness-vote?witness=utopian-io&approve=1'>Vote for Utopian Witness!</a>
properties (22)
authorutopian-io
permlinkre-part-14-ethereum-solidity-token-uniqueness-non-fungibility-and-transacions-with-unique-tokens-pt-14-20190115t144431z
categoryutopian-io
json_metadata"{"app": "beem/0.20.9"}"
created2019-01-15 14:44:33
last_update2019-01-15 14:44:33
depth1
children0
last_payout2019-01-22 14:44:33
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length590
author_reputation152,955,367,999,756
root_title"(Part 14) Ethereum Solidity - Token Uniqueness, Non-Fungibility And Transacions With Unique Tokens(PT 14)"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id78,412,199
net_rshares0