How to issue your own privacy token on SERO

SERO Protocol
9 min readMay 7, 2019

--

How to issue your own privacy token on SERO

Want to issue your own privacy token? You’ve come to the right place!
This step by step tutorial article will help you issue your first ever privacy token based on SERO.

This tutorial has been done on Betanet. The steps will be same for Mainnet.

Things you’ll need :

  1. SERO full node wallet. Download from here : https://github.com/sero-cash/wallet/releases
  2. Make sure the full node wallet is fully synced.
  3. Remix Editor : http://remix.web.sero.cash
  4. Some SERO balance in your full node wallet’s main account.

Step 1 : Open full node wallet

SERO Full Node Wallet

Open your full node and make sure it is synced upto latest blocks.

Step 2 : Open Gero Javascript Console

Go to
C:\Users\%username%\AppData\Roaming\SERO Wallet\binaries\gero\unpacked\geropkg

Double click on “attach.bat” to start gero

gero javascipt console

Step 3 : Unlocking your account

Run this command in gero javascript console.

sero.getBalance(sero.accounts[0])

NOTE : In order to run commands in gero follow :
Copy>>Right Click(in gero)>>Enter

This command will show you the current balance of your node wallet.

Checking balance in gero

Now enter personal.unlockAccount(sero.accounts[0])
and input your node wallet password to unlock your account.

Unlocking account in gero

If you input the correct password, you’ll get a output result of true

Step 4 : Deploying Smart Contract

Go to http://remix.web.sero.cash/ and a sample code will appear automatically.

Edit source code

Create a new source file(by click the “+” sign at the top left), then enter the source code as follows.

pragma solidity ^0.4.16;
contract SeroInterface {
/**
* the follow topics is system topics,can not be changed at will
*/
bytes32 private topic_sero_issueToken = 0x3be6bf24d822bcd6f6348f6f5a5c2d3108f04991ee63e80cde49a8c4746a0ef3;
bytes32 private topic_sero_send = 0x868bd6629e7c2e3d2ccf7b9968fad79b448e7a2bfb3ee20ed1acbc695c3c8b23;
bytes32 private topic_sero_currency = 0x7c98e64bd943448b4e24ef8c2cdec7b8b1275970cfe10daf2a9bfa4b04dce905;
bytes32 private topic_sero_balanceOf = 0xcf19eb4256453a4e30b6a06d651f1970c223fb6bd1826a28ed861f0e602db9b8;
/**
*
@dev convert bytes 32 to string
*
@param x the string btyes32
*/
function bytes32ToString(bytes32 x) public pure returns (string) {
uint charCount = 0;
bytes memory bytesString = new bytes(32);
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char!= 0) {
bytesString[charCount] = char;
charCount++;
} else if (charCount!= 0){
break;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
/**
*
@dev the get currency from the tx params
*/
function sero_msg_currency() internal returns (string) {
bytes memory tmp = new bytes(32);
bytes32 b32;
assembly {
log1(tmp, 0x20, sload(topic_sero_currency_slot))
b32:= mload(tmp)
}
return bytes32ToString(b32);
}
/**
*
@dev issue the token
*
@param _total the totalsupply of the token
*
@param _currency the currency ot the token
*/
function sero_issueToken(uint256 _total,string memory _currency) internal returns (bool success){
bytes memory temp = new bytes(64);
assembly {
mstore(temp, _currency)
mstore(add(temp, 0x20), _total)
log1(temp, 0x40, sload(topic_sero_issueToken_slot))
success:= mload(add(temp, 0x20))
}
return;
}
/**
*
@dev transfer the token to the receiver
*
@param _receiver the address of receiver
*
@param _currency the currency of token
*
@param _amount the amount of token
*/
function sero_send_token(address _receiver, string memory _currency, uint256 _amount)internal returns (bool success){
return sero_send(_receiver,_currency,_amount,””,0);
}
/**
*
@dev transfer the token or ticket to the receiver
*
@param _receiver the address of receiver
*
@param _currency the currency of token
*
@param _amount the amount of token
*
@param _category the category of the ticket
*
@param _ticket the Id of the ticket
*/
function sero_send(address _receiver, string memory _currency, uint256 _amount, string memory _category, bytes32 _ticket)internal returns (bool success){
bytes memory temp = new bytes(160);
assembly {
mstore(temp, _receiver)
mstore(add(temp, 0x20), _currency)
mstore(add(temp, 0x40), _amount)
mstore(add(temp, 0x60), _category)
mstore(add(temp, 0x80), _ticket)
log1(temp, 0xa0, sload(topic_sero_send_slot))
success:= mload(add(temp, 0x80))
}
return;
}
/**
*
@dev the balance of this contract
*
@param _currency the currency ot the token
*/
function sero_balanceOf(string memory _currency) internal returns (uint256 amount){
bytes memory temp = new bytes(32);
assembly {
mstore(temp, _currency)
log1(temp, 0x20, sload(topic_sero_balanceOf_slot))
amount:= mload(temp)
}
return;
}
}
contract THANOSCoin is SeroInterface {
string public currency;
address private owner;
uint256 public totalSupply;
uint8 public decimal = 6;
constructor(uint256 _initialSupply, string _currency) public payable {
totalSupply = _initialSupply * 10 ** uint256(decimal);
require(sero_issueToken(totalSupply, _currency));
owner=msg.sender;
currency = _currency;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(owner==msg.sender);
return sero_send_token(_to,currency,_value);
}
function withDraw(address _to) public{
require(owner==msg.sender);
uint256 balance = sero_balanceOf(“SERO”);
require(balance > 0);
sero_send_token(_to,”SERO”,balance);
}
function getDecimal() public view returns (uint8) {
return decimal;
}
}

Here, the token name has been put as THANOSCoin, you can edit the token name as per your choice but must satisfy these following things.

  • Cannot be duplicated globally
  • Cannot exceed 24 characters
  • Only use figures 0-9 uppercase letters a-z and underline _
  • Cannot involve the keyword sero.
  • Is case insensitive

Step 5 : Compile THANOSCoin.sol

Once you have changed the token name according to your choice, click on “Start to compile”

Compiling in Remix Editor

Once done, click on “Details” drop down go to the code of WEB3DEPLOY and click on Copy. Paste the code on a new source code file.

Copy the WEB3DEPLOY code under Details dropdown
Make sure your correct contract is selected

NOTE : Make sure when you copy the WEB3DEPLOY code, the dropdown menu has selected your token name.

Now in the above copied WEB3DEPLOY code, put
value: web3.toTa(1) below the gas: ‘4700000’,

Add the value function below gas.

This will deduct 1 SERO for smart contract execution.

The final WEB3DEPLOY code should look like this :

var _initialSupply = 1000000;
var _currency = ‘THANOSCOIN’;
var thanoscoinContract = web3.sero.contract([{“constant”:false,”inputs”:[{“name”:”_to”,”type”:”address”}],”name”:”withDraw”,”outputs”:[],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”totalSupply”,”outputs”:[{“name”:””,”type”:”uint256"}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”getDecimal”,”outputs”:[{“name”:””,”type”:”uint8"}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”decimal”,”outputs”:[{“name”:””,”type”:”uint8"}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“constant”:true,”inputs”:[{“name”:”x”,”type”:”bytes32"}],”name”:”bytes32ToString”,”outputs”:[{“name”:””,”type”:”string”}],”payable”:false,”stateMutability”:”pure”,”type”:”function”},{“constant”:false,”inputs”:[{“name”:”_to”,”type”:”address”},{“name”:”_value”,”type”:”uint256"}],”name”:”transfer”,”outputs”:[{“name”:”success”,”type”:”bool”}],”payable”:false,”stateMutability”:”nonpayable”,”type”:”function”},{“constant”:true,”inputs”:[],”name”:”currency”,”outputs”:[{“name”:””,”type”:”string”}],”payable”:false,”stateMutability”:”view”,”type”:”function”},{“inputs”:[{“name”:”_initialSupply”,”type”:”uint256"},{“name”:”_currency”,”type”:”string”}],”payable”:true,”stateMutability”:”payable”,”type”:”constructor”}]);
var thanoscoin = thanoscoinContract.new(
_initialSupply,
_currency,
{
from: web3.sero.accounts[0],
data: ‘0x608060408190527f3be6bf24d822bcd6f6348f6f5a5c2d3108f04991ee63e80cde49a8c4746a0ef36000557f868bd6629e7c2e3d2ccf7b9968fad79b448e7a2bfb3ee20ed1acbc695c3c8b236001557f7c98e64bd943448b4e24ef8c2cdec7b8b1275970cfe10daf2a9bfa4b04dce9056002557fcf19eb4256453a4e30b6a06d651f1970c223fb6bd1826a28ed861f0e602db9b86003556007805460ff191660061790556108ce38819003908190833981016040528051602082015160075460ff16600a0a82026006819055919201906100e2908264010000000061011a810204565b15156100ed57600080fd5b60058054600160a060020a03191633179055805161011290600490602084019061015a565b5050506101f5565b60408051818152606080820183526000929091906020820161080080388339019050509050828152836020820152600054604082a1602001519392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061019b57805160ff19168380011785556101c8565b828001600101855582156101c8579182015b828111156101c85782518255916020019190600101906101ad565b506101d49291506101d8565b5090565b6101f291905b808211156101d457600081556001016101de565b90565b6106ca806102046000396000f3006080604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630a67d2c7811461008757806318160ddd146100b757806334ce10c4146100de57806376809ce3146101095780639201de551461011e578063a9059cbb146101ab578063e5a6b10f146101f0575b600080fd5b34801561009357600080fd5b506100b573ffffffffffffffffffffffffffffffffffffffff60043516610205565b005b3480156100c357600080fd5b506100cc6102be565b60408051918252519081900360200190f35b3480156100ea57600080fd5b506100f36102c4565b6040805160ff9092168252519081900360200190f35b34801561011557600080fd5b506100f36102cd565b34801561012a57600080fd5b506101366004356102d6565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610170578181015183820152602001610158565b50505050905090810190601f16801561019d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101b757600080fd5b506101dc73ffffffffffffffffffffffffffffffffffffffff6004351660243561048f565b604080519115158252519081900360200190f35b3480156101fc57600080fd5b50610136610556565b60055460009073ffffffffffffffffffffffffffffffffffffffff16331461022c57600080fd5b61026a6040805190810160405280600481526020017f5345524f000000000000000000000000000000000000000000000000000000008152506105e4565b90506000811161027957600080fd5b6102b9826040805190810160405280600481526020017f5345524f000000000000000000000000000000000000000000000000000000008152508361061b565b505050565b60065481565b60075460ff1690565b60075460ff1681565b60408051602080825281830190925260609160009183918391829184919080820161040080388339019050509350600092505b60208310156103a5576008830260020a870291507fff0000000000000000000000000000000000000000000000000000000000000082161561038f5781848681518110151561035457fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060019094019361039a565b841561039a576103a5565b600190920191610309565b846040519080825280601f01601f1916602001820160405280156103d3578160200160208202803883390190505b509050600092505b848310156104855783838151811015156103f157fe5b9060200101517f010000000000000000000000000000000000000000000000000000000000000090047f010000000000000000000000000000000000000000000000000000000000000002818481518110151561044a57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001909201916103db565b9695505050505050565b60055460009073ffffffffffffffffffffffffffffffffffffffff1633146104b657600080fd5b6004805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815261054f938793919290918301828280156105445780601f1061051957610100808354040283529160200191610544565b820191906000526020600020905b81548152906001019060200180831161052757829003601f168201915b50505050508461061b565b9392505050565b6004805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156105dc5780601f106105b1576101008083540402835291602001916105dc565b820191906000526020600020905b8154815290600101906020018083116105bf57829003601f168201915b505050505081565b6040805160208082528183019092526000916060919080820161040080388339019050509050828152600354602082a15192915050565b600061063e84848460206040519081016040528060008152506000600102610646565b949350505050565b6040805160a080825260c0820190925260009160609190602082016114008038833901905050905086815285602082015284604082015283606082015282608082015260015460a082a16080015196955050505050505600a165627a7a72305820c4d60e4faa48f918367a3c925cfecf8484db649cfd6953df76495cad4149e5140029’,
gas: ‘4700000’,
value: web3.toTa(1)
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address!== ‘undefined’) {
console.log(‘Contract mined! address: ‘ + contract.address + ‘ transactionHash: ‘ + contract.transactionHash);
}
})

Edit the supply under function var _initialSupply =
Edit token ticker under funtion var _currency =
NOTE : Make sure the token ticker is in capital letters and minimum 6 letters.

WEB3DEPLOY code in Remix Editor

Also copy the ABI and paste in a notepad file, will be used at later stage.

Copy ABI

Step 6 : Executing the contract and issuing token

Now go to Gero Javascript Console and paste the WEB3DEPLOY code and click Enter to run it. It will start to execute and a timer will be shown on screen.

Contract is being executed

Once it reaches this null function, give it some time to process the transaction.

If you did everything right, after a while your contract will be deployed.

Contract has been executed and anonymous token has been issued!

VOILA! You have just issued your anonymous token based on SERO.

NOTE : After the transaction is submitted, the contract address is obtained. This address is very important and must be saved.

Step 7 : Adding Contract to Node Wallet

Now go to your node wallet and click on “Contracts” on top right.

SERO Full Node Wallet

Notice that by now your 1 SERO would have been deducted from your account.

Click on “Watch Contract” and the following window will pop up on your screen.

Watch Contract

CONTRACT ADDRESS :
Paste the contract address that you saved in the Step 6. (There must be no spaces)

CONTRACT NAME
In the space given for “Contract Name” type your token’s name.

JSON INTERFACE
In the JSON INTERFACE, paste the ABI code that you obtained in Step 5.

The final result after editing will look like this.

Adding custom contract

Click “OK” and if you did everything right you’ll get a message “Added custom contract”

Custom Contract added

Step 8 : Transfer of tokens to owner’s address.

At this point, check the balance and you will find that all the coins are still at the contract address, not at the Owner address. We will now transfer them to owners address.

Click on the custom contract under “Contracts” that you just added.

SERO Full Node Wallet

Now scroll down and click on “Transfer” under “Pick a function”

Choose “Transfer”

Once you click you’ll get below window.

Transfer function

Type in your node wallet address under “to-address”

Type in the supply amount(or any amount of tokens) under the “value” field and click on “EXECUTE”

SERO Full Node Wallet- Smart Contract Transfer function

Enter your node wallet password and the function will be executed after 12 confirmations.

Fill your password to execute smart contract funtion
2 of 12 confirmations

Now all the tokens must show under your Main Account.

SERO Full Node Wallet — Main Account

You can now send these tokens to any SERO address or to any SERO Flight Wallet address.

Congratulations on issuing your own anonymous token!

SERO Fee for Issuing Anonymous Tokens

* * In order to limit meaningless token names to be registered**
* The SERO Consensus Mechanism charges each successful registered token name.
* The SERO coins received will go the SERO Foundation.

* The fee charged depends on the length of the anonymous token name:
Length | Fee
— — — — — -
<=3 | Not Eligible
4 | 1000 SERO
5 | 10 SERO
6 | 1 SERO
>=7 | 0.1 SERO

Rules for Anonymous Token names:
1. Only uppercase letters [A-Z], numbers [0–9], underscores _
2. Cannot contain “SERO” as keywords
3. Must start with a letter
4. Up to 32 bytes

Payment methods

Add a value field when registering with a fee.

Var serointerfaceContract = web3.sero.contract([{"co ... ... on"}]);
Var serointerface = serointerfaceContract.new(
{
From: web3.sero.accounts[0],
Data: '0x6080 ... ... 60029',
Gas: '4700000',
Value: web3.toTa(1), // 6 word name fee 1 SERO
}, function (e, contract){
Console.log(e, contract);
If (typeof contract.address !== 'undefined') {
Console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
```

Need Support ? Loved it? or Got feedback? We are always open to hear from our lovely SERO family. Reach us any of our below given SERO community links.

You can also join our SERO Discord and address your queries.
SERO Discord : https://discordapp.com/invite/3AZVMRU

Official links

Official website : https://sero.cash
Tencent : https://v.qq.com/x/page/s0792e921ok.html
YouTube : https://youtu.be/UNG2boG49Io
Twitter : https://twitter.com/SEROdotCASH
Medium : https://medium.com/@SERO.CASH
Github : https://github.com/sero-cash
Reddit : https://www.reddit.com/user/SEROofficial
BitcoinTalk ANN : https://bitcointalk.org/index.php?topic=5123382.0
Linkedin :https://www.linkedin.com/company/sero-global-inc/
Facebook : https://www.facebook.com/SEROProtocol
Gitter Community : https://gitter.im/sero-cash/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link
SERO VS Zcash encryption speed comparison :https://www.youtube.com/watch?v=bc6yHTLSl5M

Telegram Community

Chinese group : https://t.me/SeroOfficialChs
English group : https://t.me/SeroOfficial
SERO Announcement : https://t.me/SEROannouncements
SERO Official Technical Support : https://t.me/SeroFans

SERO Discord : https://discord.gg/3AZVMRU

--

--

SERO Protocol
SERO Protocol

Written by SERO Protocol

World’s first Zero-Knowledge Proof based Privacy Protection platform for decentralised applications which supports smart contract and uses SuperZK protocol.

No responses yet