Security Token Manager documentation

This is the documentation for Security Token Manager. This open source project provides tooling and programming interfaces to interact and integrate security tokens on Ethereum and other blockchains.

_images/overview.png

Security Token Manager supports operations for security token governance.

  • Issue out new stock or bond series as security tokens
  • Distributing shares to primary market investors
  • Printing out cap table
  • Managing bad transactions and lost private keys
  • Paying dividends and interest
  • Delivering voting ballots
  • Maintaining audit logs of delivered actions

The command line tool is locally installed via Docker and available for Windows, OSX and Linux. The API is written in Python programming language.

New to tokens and securities? Read an introduction for security tokens

Installation

Security token interaction happens through a command line sto command that connects to an Ethereum network node and a local database. sto command is automatically installed via Docker.

Requirements

Skills needed

  • Command line usage experience
  • Ethereum and smart contract experience

Software or services needed

  • Ethereum node, for example a local Parity installation or Infura-node-as-a-service - see how to install
  • Docker

Normal users

This tool is for command line users and developers only. We do not provide an end user application as open source. For business services please contact TokenMarket business representatives.

Advanced users

The sto command line application is provided as a Docker image to minimize the issues with painful native dependency set up for your operating system. To use sto we will set up a command line alias, as Docker command itself is quite long.

Install Docker (Windows, OSX).

OSX and Linux

Set up a shell alias for sto command that executes Dockerised binary:

alias sto='docker run -p 8545:8545 -v `pwd`:`pwd` -w `pwd` miohtama/sto:latest'

Then you can do:

sto --help

Docker will automatically pull an image from Docker registry for your local computer on the first run. We map port 8545 to the localhost as that is normal Ethereum JSON-RPC API.

_images/help.png

After installing see how to set up the software.

Windows

Windows PowerShell instructions coming soon.

Meanwhile use Linux instructions and Linux Subsystem for Windows.

Developers

Python 3.6+ required.

Create Python virtual environment.

Then within the activated venv do:

git clone "git+https://github.com/TokenMarketNet/sto.git"
python -m venv venv  # Python 3 needed
source venv/bin/activate
pip install -U pip  # Make sure you are at least pip 18.1 - older versions will fail
pip install -e ".[dev,test]"

How to set up and first run

Below are short instructions how to set up an Ethereum node, account and configuration file for the Kovan testnet (no real money involved).

You need an Ethereum node. You can either install yourself (see Install Parity) or use a Ethereum node provider like Infura.

Sign up for Infura (Option a)

Sign up for Infura.

Get a Kovan node URL from your dashboard (use dropdown):

_images/infura.png

Install Parity (Option b)

First install Parity. For example on OSX using Brew package management:

brew install parity

Start Parity in another terminal and connect it to Kovan test network:

parity --chain=kovan

Parity will now sync you to Kovan network using warp (fast mode). This will take up to two hours. You can continue to follow instructions below.

Sign up for QuikNode (Option c)

Sign up for QuikNode.

Get a Kovan node on Parity and use the Web3 URL from your dashboard (Dev Tools):

screenshots/quiknode.png

Set up Ethereum account

To start playing with tokenised shares we first need to create a new Ethereum account we use for management operations.

Create an Ethereum account:

sto --network=kovan ethereum-create-account

This will give you a new raw private key and related Ethereum address to play with:

Creating new Ethereum account.
Account address: 0xDE5bC059aA433D72F25846bdFfe96434b406FA85
Account private key: 3fac35a57e1e2867290ae37d54c5de61d52644b42819ce6af0c5a9c25f4c...

Now create a file myconfig.ini and add the content:

# Your personal configuration file as we told you on Github example

# Network we are using
network = kovan

# This is for Parity - if you are using Infura or QuikNode get your Kovan node URL from your dashboard
ethereum-node-url = http://localhost:8545

# The private key for your generated Ethereum account
ethereum-private-key = 3fac35a57e1e2867290ae37d54c5de61d52644b42819ce6af0c5a9c25f4c....

Top up

Visit Kovan faucet.

Request Kovan ETH (KETH) on your account you just create above. A Github account is needed for verification. This should give you 1 Kovan ETH to play with and you become a testnet millionaire.

Diagnose and test run

Use sto diagnose command to check your account has balance and your Ethereum node works:

sto --config=myconfig.ini diagnose

This should output:

_images/diagnose.png

Now your can proceed to issue out your first play shares.

Issuing out security tokens

Before issuing out stock you need to have set up a functional Ethereum account set up.

To issue out stock you need to give stock name, ticker symbol and amount of shares:

sto --config=myconfig.ini issue --symbol=STO --name="Mikko's magic corp" --url="https://tokenmarket.net" --amount=10000

You will get a list of Ethereum transactions needed to perform this operation:

Prepared transactions for broadcasting for network kovan
TXID    Status      Nonce  From                                        To                                          Note
------  --------  -------  ------------------------------------------  ------------------------------------------  --------------------------------------------------------------
        waiting         1  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0x3cD6f4004e310c0E5Ae7eaf5B698386ccF1d78F2  Token contract for Mikko's magic corp
        waiting         2  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0x1abECD8dF601e6e56eca99Ec1F1c50eEAe61B289  Unrestricted transfer manager for Mikko's magic corp
        waiting         3  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0x3cD6f4004e310c0E5Ae7eaf5B698386ccF1d78F2  Setting security token transfer manager for Mikko's magic corp
        waiting         4  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0x3cD6f4004e310c0E5Ae7eaf5B698386ccF1d78F2  Creating 10000 initial shares for Mikko's magic corp

Next see how to broadcast created transactions.

Issuing tokens in restricted mode

The security token can deployed with –transfer-restriction. The default value of this flag is unrestricted. When –transfer-restriction=”restricted” the restricted mode is enabled. In restricted mode the user address should be whitelisted in a KYC smart contract. See How to whitelist an address For more info on whitelisting. sto –config=myconfig.ini issue –symbol=STO –name=”Mikko’s magic corp” –url=”https://tokenmarket.net” –amount=10000

Tutorial for issuing tokens in restricted mode

  1. Deploy the KYC smart contract:

    sto --config=myconfig.ini kyc-deploy
    
  2. WhiteList the address that will be used to deploy the SecurityToken smart contract. This is needed so that the initial balance is set correctly in the security token. If owner address is not whitelisted then security will have initial balance of zero. To whitelist the address:

    sto --config=myconfig.ini kyc-manage --whitelist-address='Address_that_will_be_used_to_deploy_security_token'
    
  3. Deploy the security token smart contract:

    sto --config=myconfig.ini issue --symbol=STO --name="Mikko's magic corp" --url="https://tokenmarket.net" --amount=10000 --transfer-restriction="restricted"
    

    See How to whitelist an address For more info on whitelisting

  4. Broadcast the transaction to the ethereum network:

    sto --config=myconfig.ini tx-broadcast
    
  5. Make sure the transaction ran sucessfully on the ethereum network:

    sto --config=myconfig.ini tx-update
    

    See broadcast created transactions for more info.

  6. Before distributing token whitelist all the user addresses that will participate in the token distribution. To whitelist customer address follow step 2.

  7. Distribute the tokens as described in the csv input infile. For more info see Distribute Tokens for more info:

    sto --config=myconfig.ini distribute-multiple --csv-input=example-distribution.csv --address=0x....
    
  8. Repeat step 3 and 4.

  9. To scan all transactions of your security token use token-scan command. Use the token address for which you have created a distribution:

    sto --config=myconfig.ini token-scan --token-address=0x1091aA1ED6070eDEDFdf46f665C1eD78Bd2c7431
    
  10. To verify that balances have been set right, view the cap table:

    sto --config=myconfig.ini cap-table --identity-file=example-ids.csv --token-address=0x..
    
See View token holder cap table for more info.

Further information

See issue.

Broadcasting transactions

Ethereum transactions are first written to a local SQlite database. A separate step of broadcasting transactions is needed in order to write the data to Ethereum blockchain. Furthermore local database allows us to add human friendly annotations for transactions, so that diagnostics and future audits are easy.

Using a local database and locally generated nonces ensures we can always safely rebroadcast transactions and issue out new transactions even under severe network conditions.

To broadcast:

sto --config=myconfig.ini tx-broadcast

Transactions are send out to Ethereum network and they get a transaction id. You will see txid in output:

Pending 5 transactions for broadcasting in network kovan
Our address 0xDE5bC059aA433D72F25846bdFfe96434b406FA85 has ETH balance of 0.955684 for operations
TXID                                                                Status and block      Nonce  From                                        To                                          Note
------------------------------------------------------------------  ------------------  -------  ------------------------------------------  ------------------------------------------  ---------------------------------------------------------
0x6bb9755f492f9d4497457df0da8cfd91ab32efaad7bb67444f4e2e00351e9427  broadcasted              74  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xdaE00e2fbD21924443e133E14A9206CeDC046824  Deploying token contract for Moobar
0xefd6ad3b3c8a8364b315b6c73667baf6d657493d8dad14423b41a32b22444d60  broadcasted              75  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0x533FeDE8F86C3e8a7923fEa4f55007f25AF5db30  Deploying unrestricted transfer policy for Moobar
0x4d31a1d15c1f479c48a21798f5d81d275b34b3fa8cbf9e450dc2ad20b0001e41  broadcasted              76  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xdaE00e2fbD21924443e133E14A9206CeDC046824  Whitelisting deployment account for Moobar issuer control
0xe45a64c71a42100858b9880c40a59e7728fb4c5a11adf14ff509323fc08f21de  broadcasted              77  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xdaE00e2fbD21924443e133E14A9206CeDC046824  Making transfer restriction policy for Moobar effective
0x948b9925f8afe134b39e8c3384c51e0027c839a9737b6307ab77419992b293c7  broadcasted              78  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xdaE00e2fbD21924443e133E14A9206CeDC046824  Creating 10000 initial shares for Moobar
Run sto tx-update to monitor your transaction propagation status

Update transaction status

Blockchain transactions are asynchronous. First the transactions are broadcasted to the network. The transactions propagade from a node to a node until a miner node decides to include your transactions in a block.

tx-update command will read tranactions from network and update the local database for pending transasctions. It will also detect if a transaction has failed e.g. due to smart contract permission errors.

To check your transaction status:

sto --config=myconfig.ini tx-update

After a while repeating this command you should see all your transactions included in blockchain with success status:

TXID                                                                Status and block      Nonce  From                                        To                                          Note
------------------------------------------------------------------  ------------------  -------  ------------------------------------------  ------------------------------------------  ---------------------------------------------------------
0x4bd273895b21a3b57e93113c26895ea142f989cde13ff0c23bb330de1889238a  success:9513331          70  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xc48DA079aab7FEf3a2476B493f904509d1891Fa3  Deploying unrestricted transfer policy for Doobar
0xc5bb03a49bdc58cecb0ad36ff7f1aac84e29b08c2ed67c17d7ecab2f55d63c54  success:9513331          71  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xC423aCf9757c25048E0f10F21A4eC6a1322b4299  Whitelisting deployment account for Doobar issuer control
0xbbe0e59db71839b4b7cf7c8ac082c9204513243d3ae3ca38c98b8d443f9699ed  success:9513331          72  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xC423aCf9757c25048E0f10F21A4eC6a1322b4299  Making transfer restriction policy for Doobar effective
0x565eda7f18c9d05255b3f29c9d677734bbdb97e25d62d10d1033208030dda0a7  success:9513331          73  0xDE5bC059aA433D72F25846bdFfe96434b406FA85  0xC423aCf9757c25048E0f10F21A4eC6a1322b4299  Creating 10000 initial shares for Doobar

You can also enter TXID to Kovan EtherScan explorer to see how your transactions are doing to check more information about your transactions.

After you have get your transactions to Ethereum blockchain, see how to view the token summary.

Further information

See tx-broadcast or tx-update commands.

Restricting token transfers

Introduction

Unlike cryptocurrencies, security tokens have restrictions on transfers.

  • The real world identity of a receiver must be resolved before a transfer to maintain up-to-date shareholder registry information
  • For limited private companies, restricted shares are often subject to company’s approval before they can be given to a new owner
  • Bearer shares, or shares without known owner on a shareholder ledger, are illegal in the most jurisdictions

For all of these problems the solution is to “whitelist” token receivers, or shareholders, beforehand.

  • A centralised service maintains real world identity information of blockchain addresses offchain
  • This centralised service reports to blockchain who are allowed to receive new transfers

Using Know Your Customer smart contract to ensure good ownership

Security tokens in the restricted mode need addresses to be whitelisted. Addreses are whitelisted using a KYC smart contract.

Deploying KYC smart Contract

To deploy the KYC smart contract:

sto --config=myconfig.ini kyc-deploy

If the smart contract is already deployed then it wont be re-deployed.

Whitelist an ethereum address

Adresses can only whitelisted by the owner of the smart contract:

sto --config=myconfig.ini kyc-manage --whitelist-address='0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF'

The command will also broadcast the transaction to the ethereum network. There is no need to run command tx-broadcast.

Token summary

Introduction

Token summary commands allow you to check the overview of existing deployed STO smart contracts.

Viewing summary

After all your transactions have been pushed out and are succesfully included in blocks, you can view the token status by entering the contract address:

sto --config=myconfig.ini token-status --address=0xa2016C64D4687Ad4184bA1dA98711e83a36eD1c2

This outputs:

Name: Boobar
Symbol: STO
Total supply: 10000
Decimals: 18
Owner: 0xDE5bC059aA433D72F25846bdFfe96434b406FA85
Transfer verified: 0x7598E970888F51d7D35468E50768Fa5F21B46Bb3

Distributing shares

The command line tool supports a simple CSV import to distribute shares to shareholders.

  • Shares are moved to a hot wallet account, as configured above. (In the future, smart contract based and optimised distribution methods are supported.)
  • sto command reads a CSV file with investor info - see example CSV file below for column information
  • Transactions are prepared for broadcasting
  • Transactions are broadcasted and an audit log is written to the database

Each imported transaction must have an unique external_id attribute, so that we can track which distribution transaction corresponds incoming payment transaction.

First you need to record down the issued token address from above.

Example how to import CSV. We use an example file from the source code repository:

 # Download example CSV file provided with source code repository
curl -O "https://raw.githubusercontent.com/TokenMarketNet/sto/master/docs/source/example-distribution.csv"

# Your token contract address goes here
sto --config=myconfig.ini distribute-multiple --csv-input=example-distribution.csv --address=0x....

This should output:

Distribution created 2 new transactions and there was already 0 old transactions in the database

Now you can broadcast your distribution transactions with sto tx-broadcast (see broadcasting).

Further information

See distribute-multiple command.

Cap table

Introduction

Cap table show the current ownership, or token holding addresses, of security tokens.

Cap table can be printed for the current moment or any moment in the past.

Cap table output may contain the real world identities of the owners, if supplied via external CSV file, or just plain Ethereum addresses.

Synchronising with blockchain

To print out the cap table, first you need to build the local database of token transactions.

Token holder balances ae managed in a blockchain. Accessing token holder information real time from a blockchain is non-trivial. For complex operations, like printing out the cap table, we need to crunch the blockchain data first to a local database.

sto can scan the blockchain and construct a database of all past token transactions. Based on this information we can print out the cap table in any point of time.

Scanning token holders

To scan all transactions of your security token use token-scan command. Use the token address for which you have created a distribution.

sto --config=myconfig.ini token-scan --token-address=0x1091aA1ED6070eDEDFdf46f665C1eD78Bd2c7431

Scan may take few minutes, as the operation walks through the whole blockchian. In the end, it should print:

Scanning token: Mikko's corp 5
Current last block for chain kovan: 9880112
Scanning blocks: 133739 - 9880112
Last scan ended at block: 133749
Scanning block: 9524384, batch size: 500000: : 9890620it [00:13, 104737.39it/s]
Updated 3 token holder balances

Reruns

Rerunning sto token-scan starts from the block where it was left last time. We look back few blocks (10) to ensure that any transfers lost in minor blockchain forks are corrected.

About the scan algorithm

The provided scan algorithm is referential in the nature. It may not scale to large number or tokens or token holders. The algorithm has been designed the limitations of SQLite databases in mind.

Printing to cap table

After you have scanned the balances you can print the cap table.

Further information

See token-scan command.

Printing out cap table

Printing out the token holder cap table

Use sto cap-table command to print out different views on the table.

Here we print out the cap table

First we download the file that contain read world identities of token holder addresses:

# Download example CSV file provided with source code repository
curl -O "https://raw.githubusercontent.com/TokenMarketNet/sto/master/docs/source/example-ids.csv"

Then we can use this file and our local token transfer database to print out the current cap table:

sto --config=myconfig.ini cap-table \
    --identity-file=example-ids.csv \
    --token-address=0xAEFafd1Ae9b0e9acFF2b22596C40da3FFD8dff99

Cap table looks like this:

_images/captable.png

Further information

See cap-table command for ordering and formatting options.

Cap table for any ERC-20 token

These are quick instructions to print the cap table for any ERC-20 token.

sto token-scan and sto cap-table command support creating token holder database of any ERC-20 token, not just security tokens or tokens you have issued yourself. If you need to use token holder or transfer data in your application you can read it directly from sto SQLite database.

Note

As most of the ERC-20 tokens are payment terms, using term cap table is little bit misleading. The term “token holders” is more generic.

Preparing and printing out token holders

Here is a quick tutorial how to print out the token holders of Reality Clash token.

First create a INI configuration while that connects to Infura Ethereum mainnet node or your local mainnet node.

mainnet.ini example:

# Network we are using
network = ethereum

# Get this from your Infura dashboard
ethereum-node-url = https://mainnet.infura.io/v3/453...

Then scan all RCC token transactions of all time. Please note that the scan process may take anywhere between 15 minutes to few hours depening on how fast your connection to the node and computer are.

sto --config=mainnet.ini token-scan --token-address=0x9b6443b0fb9c241a7fdac375595cea13e6b7807a
_images/scan-reality-clash.png

Note

If the scan is interrupted it will pick up where it was left last time. You can also manually interrupt the application with CTRL+C.

Now you can print out the cap table. Here is how to print out top 10 token holders:

sto --config=mainnet.init cap-table \
    --token-address=0x9b6443b0fb9c241a7fdac375595cea13e6b7807a \
    --order-by=balance \
    --order-direction=desc \
    --max-entries=10

And it prints out the RCC top holders table:

_images/rcc-captable.png

Contract verification on EtherScan

Verifying contracts on EtherScan

EtherScan is a popular service for blockchain exploring. It’s verify contract feature allows you to create reproducible builds of your Solidity source code and then EtherScan can introspect your contract state. This is very useful for diagnostics.

For example, you can see browse STO transactions easily:

_images/etherscan.png

To verify your contracts on EtherScan, you need to first ensure all contract deployement transactions are broadcasted and mined.

Then add your EtherScan API key in myconfig.ini:

# Obtained after signing in to etherscan.io
etherscan-api-key = T2JC4....

Now you can run verify:

sto --config=myconfig.ini tx-verify

Further information

See tx-verify.

Dividends and interest

Introduction

Dividends, interest or royalies can be generally lumped together as payouts. We support doing

  • Dumb payouts: wiring stable coins directly to the owner address
  • Payout contract:

Payout contract

The Payout contract provides the ability to set up dividend distribution.

Payout Deploy

To deploy payout smart contract:

sto --config=myconfig.ini payout-deploy --token-address="0x.." --payout-token-address="0x.." --payout-token-name="CrowdsaleToken" --kyc-address="0x.." --payout-name='Pay X' --uri="http://tokenmarket.net" --type=0
  • --token-address is the address of the deployed security token.
  • --payout-token-address is the address token used in paying out.
  • --payout-token-name is the name of the payout token. This should be the same name as defined in the smart contract.
  • --kyc-address is the address of the deployed kyc smart contract.
  • --payout-name is the name you want to give to your Payout smart contract
  • --uri uri used for announcement
  • --type used in announcement smart contract

Payout Approve

In order to release token to the Payout smart contract, they first need to be approved. This should only be run once:

sto --config=myconfig.ini payout-approve --payout-token-name="CrowdsaleToken"

--payout-token-name name of the payout_token used earlier to deploy payout smart contract.

Payout deposit

To fetch the approved tokens call command:

sto --config=myconfig.ini payout-deposit

Voting

Introduction

Shareholder voting is a process where equity owners participate in the company wide decisions. We support voting both offchain and onchain.

  • In offchain voting, you take a snapshot of registered assembly participants and their voting rights. Then you use a special corporate governance platform to organise voting.
  • In onchain voting, the participants vote on each topic transparently on blockchain, using their token wallets

Off-chain voting

In off-chain voting, shareholders need to register to present themselves in a general assembly beforehand.

  1. A snapshot of eligible votes the certain point of time, see cap table management
  2. Issuer invites the shareholders to the meeting through email address they have in the shareholder registry
  3. Issuer opens a master account in the corporate governance system
  4. Issuer gives registered participants an shareholder account and allocates voting rights proportionally to their registered shares
  5. The general assembly meeting is run the corporate governance system, each agenda item is voted individually online
  6. Participants chat with the meeting chair and other participants online in the corporate governance system
  7. The meetings minutes is automatically produced afterwards

An example of a suitable corporate governance and voting service is KoreConX.

Using on-chain voting with voting contract

This gives shareholders the ability to vote on-chain.

Voting Deploy

To deploy the voting smart contract run:

sto --config=myconfig.ini voting-deploy --token-address="0x..." --kyc-address="0x.." --voting-name="abcd" --uri="http://tokenmarket.net" --type="0"
  • --token-address is the address of the deployed security token.
  • --kyc-address is the address of the deployed kyc smart contract.
  • --voting-name is the name you want to give to your Voting smart contract
  • --uri uri used for announcement
  • --type used in announcement smart contract

Smart contracts

Introduction

TokenMarket provides its in-house developed security token smart contracts for Ethereum blockchain.

_images/smart-contracts-overview.png

Key points

  • Ethereum public blockchain
  • Can present tokenised equity (shares) and debt (bonds) financial instruments
  • ERC-20 based
  • Securities componentes added to support corporate governance and shareholder management
  • Open source
  • Tools available for developers to manage and integrate

Source code of security token smart contracts can be found on Github.

Other security token standard candidates

Security Token Manager tool (sto) is designed to work with other security tokens as well, as most ERC-20 based security tokens follow very similar structure.

We believe it is still very early for standardisation efforts of security token protocols or blockchains. We also believe that with out vast experience with smart contracts, issuances and securities regulation allows us to make the best design decisions in security token programming.

Other token standards include

  • ERC-1400
  • ERC-1462
  • ERC-1600
  • ST-20

Securities vs. cryptocurrencies

Securities (real world assets) differ from cryptocurrencies (virtual assets)

  • Securities have an issuer and there exists an implicit trust between the investors and the issuer
  • Securities often need to have real world identities associated with the ownership - a shareholder registry
  • Securities pay dividends or interest

By their nature, security tokens needs less hardcode decentralisation, as there always exist corresponding assets in the real world. Or opposite, losing of private keys cannot result losing the ownership of your assets.

Issuer control mechanism

_images/issuer-control.png

TokenMarket security token can run both on public and private blockchains. It is immune to negative effects typically assumed with cryptocurrencies, like hacks and lost private keys. The issuer maintains the master shareholder registry access which ultimately allows to fix human errors shareholders cause for themselves.

The company board nonimates a technical advisor who will execute board decisions like paying dividends or issuing new shares. Other technical advisor activities include managing shareholders registry, recovering shares from lost private keys and fixing human errors in invalid transfers.

TokenMarket security token smart contract has role based mechanism to delegate authority or partial authority to different set of keys. The technical advisor manages these keys. For the security reasons, the technical advisor is using a multisignature wallet where multiple people need to confirm critical activities that affect the shareholder balances.

More about different roles in the SecurityToken source code.

Restricting share transfers

TokenMarket security token supports restricting share transfers. This helps to

  • Enable collection of real world identities of shareholders
  • Ensure all investors receiving shares are qualified to be in the cap table
  • Make shares restricted shares and ensure Board can approve any new shareholders
  • Ensure there is an online communication method for all investors

There can be multiple parties that maintain real world identity registries and whitelists.

See AdvancedTransfeAgent for source code.

Fixing human errors

The issuer, with the help of the technical advisor, can fix errors caused by the shareholder mistakes.

Recovering lost shares

Unlike decentralised cryptocurrencies, issuer controlled financial instruments allow more relaxed private key management. Because real world identifies are known and the issuer can replace damaged tokenised shares, it is possible to establish a process where a bad key management errors are recovered. This is not totally different for replacing a lost credit cards.

In the case a shareholder reports that they have lost access to their private key, they can go through a recovery process where the lost shares are invalidated and the corresponding amount of new shares are issued to the shareholder.

_images/recovery.png

For more information see forceTransfer() function in the source code.

Unauthorised trades

The shareholder might become a victim of fraud and have their shares stolen. This is not different of mismanaging one’s online bank account or credit cards and have an unauthorised transfers there.

  • The shareholder does not properly manage their private keys and unauthorised party gains access
  • The shareholder organisation is a victim of insider traud

If the unauthorised party manages to liquidate the shares, how cases of rights on stolen title are resolved depend on a jurisdiction. The issuer and its technical advisor can always follow the court decisions if unsure. For more insights read this Twitter discussion.

Custodianship

_images/custodian.png

In custodised assets

  • Assets owner multiple entities are pooled into the same wallet
  • Sometimes this is for security (cold wallet), sometimes this is necessary for business activity (exchange hot wallets)
  • We need to be able clear ultimate beneficial owners for the assets in this custodian wallet

Custodians need to ensure take care that their benefactors receive payouts and voting rights correctly.

There are two typical case of custodianships for security tokens: custodian companies and exchanges.

Custodial companies

For institutional investors, it is often required to use a custodian company for the concern of separation of duties.

With TokenMarket security tokens, the custodian can safely hold investors’ assets in a pooled cold wallet and then report the the ultimate beneficial ownership structure behind those assets.

Exchange wallets

Exchange that are based on hot wallets do not offer blockchain transparency for ownership over trades.

Exchanges trading security tokens must report both

  • New ownership
  • Trades made (as consolidated tape)

Good information about reporting requirements can be found in European Union MIFID II RTS (Regulatory Technical Standards).

Real time reporting protocol

TokenMarket provides a HTTPS based protocol for reporting trades and changes in the ownership. Details to followCustodianship.png.

Payouts

Smart contract support on-chain payouts - dividends and interest.

See payouts for more information.

Voting

Smart contract support on-chain and off-chaibn voting for shareholders.

See voting for more information.

Announcements

Announcements is a mechanism built into the security token to allow the issuer to inform market participants about the events

  • Attaching metadata to tokens, like company legal information and International Securities Identification Number (ISIN)
  • Inform traders about upcoming declaration dates for dividends

The security tokens can be self describing on a blockchain. In the future, there is less need to maintain a registry of different securities, as you can get the same information direcly from a blockchain in the form of issuer announcements.

For more about different roles in the SecurityToken source code.

Command line reference

Here is the command line reference for sto command.

Options and config files

Settings can be either given in a config file, specified by --config-file switch or directly to the main command.

E.g. these are equivalent.

Command line:

sto --ethereum-node-url="https://mainnet.infura.io/v3/453d2049c15d4a8da5501a0464fa44f8" token-scan ...

As with INI file mainnet.ini:

# Infura mainnet net node url
ethereum-node-url = https://mainnet.infura.io/v3/453d2049c15d4a8da5501a0464fa44f8
sto --config-file=mainnet.ini token-scan ...

Subcommands take their own options that cannot be specified in the settings file.

Main command and options

When running sto --help you get list of settings and subcommands:

Usage: sto [OPTIONS] COMMAND [ARGS]...

  TokenMarket security token management tool.

  Manage tokenised equity for things like issuing out new, distributing and revoking shares.

  For full documentation see https://docs.tokenmarket.net/

Options:
  --config, --config-file PATH  INI file where to read options from
  --database-file PATH          SQLite file that persists transaction broadcast status
  --network TEXT                Network name. Either 'ethereum' or 'kovan' are supported for now.
  --ethereum-node-url TEXT      Parity or Geth JSON-RPC to connect for Ethereum network access
  --ethereum-abi-file TEXT      Solidity compiler output JSON to override default smart contracts
  --ethereum-gas-price TEXT     How many GWei we pay for gas
  --ethereum-gas-limit INTEGER  What is the transaction gas limit for broadcasts
  --ethereum-private-key TEXT   Private key for the broadcasting account
  --etherscan-api-key TEXT      EtherScan API key used for the contract source code verification
  --log-level TEXT              Python logging level to tune the verbosity of the command
  --auto-restart-nonce BOOLEAN  Automatically restart nonce for the deployment account if starting with a fresh database
  --help                        Show this message and exit.

Commands:
  cap-table                Print out token holder cap table.
  deploy-crowdsale-token   Command to be used only for testing
  diagnose                 Check your node and account status.
  distribute-multiple      Distribute shares to multiple shareholders whose address info is read from a file.
  distribute-single        Send out tokens to one individual shareholder.
  ethereum-create-account  Creates a new Ethereum account.
  issue                    Issue out a new security token.
  issue-logs               Print out transactions of for tokens issued in the past.
  kyc-deploy               Deploys Kyc contract to desired ethereum network.
  kyc-manage               Whitelist a address in KYC smart contract.
  payout-approve           approve tokens to the payout contract
  payout-deploy            Deploys Voting contract to desired ethereum network network, ethereum-abi-file, ethereum-private-key, ethereum-node-url are required args
  payout-deposit           the private key here needs to belong to the customer who wants to fetch tokens
  payout-dividends
  reference                Print out the command line reference for the documentation.
  token-scan               Update token holder balances from a blockchain to a local database.
  token-status             Print token contract status.
  tx-broadcast             Broadcast waiting transactions.
  tx-last                  Print latest transactions from database.
  tx-next-nonce            Print next nonce to be consumed.
  tx-restart-nonce         Resets the broadcasting account nonce.
  tx-update                Update transaction status.
  tx-verify                Verify source code of contract deployment transactions on EtherScan.
  version                  Print version number and exit.
  voting-deploy            Deploys Voting contract to desired ethereum network network, ethereum-abi-file, ethereum-private-key, ethereum-node-url are required args

cap-table

Print out token holder cap table.

The token holder data must have been scanned earlier using token-scan command.

You can supply optional CSV file that contains Ethereum address mappings to individual token holder names.

Usage: sto cap-table [OPTIONS]

  Print out token holder cap table.

  The token holder data must have been scanned earlier using token-scan
  command.

  You can supply optional CSV file that contains Ethereum address mappings
  to individual token holder names.

Options:
  --identity-file PATH            CSV file containing address real world
                                  identities
  --token-address TEXT            Token contract address  [required]
  --order-by [balance|name|updated|address]
                                  How cap table is sorted
  --order-direction [asc|desc]    Sort direction
  --include-empty BOOLEAN         Sort direction
  --max-entries INTEGER           Print only first N entries
  --accuracy INTEGER              How many decimals include in balance output
  --help                          Show this message and exit.

deploy-crowdsale-token

Command to be used only for testing

Usage: sto deploy-crowdsale-token [OPTIONS]

  Command to be used only for testing

Options:
  --help  Show this message and exit.

diagnose

Check your node and account status.

This command will print out if you are properly connected to Ethereum network and your management account has enough Ether balance.

Usage: sto diagnose [OPTIONS]

  Check your node and account status.

  This command will print out if you are properly connected to Ethereum
  network and your management account has enough Ether balance.

Options:
  --help  Show this message and exit.

distribute-multiple

Distribute shares to multiple shareholders whose address info is read from a file.

Usage: sto distribute-multiple [OPTIONS]

  Distribute shares to multiple shareholders whose address info is read from
  a file.

Options:
  --csv-input TEXT  CSV file for entities receiving tokens  [required]
  --address TEXT    Token contract address  [required]
  --help            Show this message and exit.

distribute-single

Send out tokens to one individual shareholder.

Usage: sto distribute-single [OPTIONS]

  Send out tokens to one individual shareholder.

Options:
  --token-address TEXT  Token contract address  [required]
  --to-address TEXT     Receiver  [required]
  --external-id TEXT    External id string for this transaction - no
                        duplicates allowed  [required]
  --email TEXT          Receiver email (for audit log only)  [required]
  --name TEXT           Receiver name (for audit log only)  [required]
  --amount TEXT         Amount of tokens as a decimal number  [required]
  --help                Show this message and exit.

ethereum-create-account

Creates a new Ethereum account.

Usage: sto ethereum-create-account [OPTIONS]

  Creates a new Ethereum account.

Options:
  --help  Show this message and exit.

issue

Issue out a new security token.

  • Creates a new share series
  • Allocates all new shares to the management account
  • Sets the share transfer restriction mode
Usage: sto issue [OPTIONS]

  Issue out a new security token.

  * Creates a new share series

  * Allocates all new shares to the management account

  * Sets the share transfer restriction mode

Options:
  --symbol TEXT                [required]
  --name TEXT                  [required]
  --url TEXT                   [required]
  --amount INTEGER             [required]
  --transfer-restriction TEXT
  --help                       Show this message and exit.

issue-logs

Print out transactions of for tokens issued in the past.

Usage: sto issue-logs [OPTIONS]

  Print out transactions of for tokens issued in the past.

Options:
  --help  Show this message and exit.

kyc-deploy

Deploys Kyc contract to desired ethereum network. required args network, ethereum-abi-file, ethereum-private-key, ethereum-node-url

Usage: sto kyc-deploy [OPTIONS]

  Deploys Kyc contract to desired ethereum network. required args network,
  ethereum-abi-file, ethereum-private-key, ethereum-node-url

Options:
  --help  Show this message and exit.

kyc-manage

Whitelist a address in KYC smart contract. network, ethereum-abi-file, ethereum-private-key, ethereum-node-url are required args

Usage: sto kyc-manage [OPTIONS]

  Whitelist a address in KYC smart contract. network, ethereum-abi-file,
  ethereum-private-key, ethereum-node-url are required args

Options:
  --whitelist-address TEXT  address to whitelist  [required]
  --help                    Show this message and exit.

payout-approve

approve tokens to the payout contract

Usage: sto payout-approve [OPTIONS]

  approve tokens to the payout contract

Options:
  --payout-token-address TEXT  address of payout token contract
  --payout-token-name TEXT     name of the payout token smart contract
                               [required]
  --help                       Show this message and exit.

payout-deploy

Deploys Voting contract to desired ethereum network network, ethereum-abi-file, ethereum-private-key, ethereum-node-url are required args

Usage: sto payout-deploy [OPTIONS]

  Deploys Voting contract to desired ethereum network network, ethereum-abi-
  file, ethereum-private-key, ethereum-node-url are required args

Options:
  --token-address TEXT         address of security token contract
  --payout-token-address TEXT  address of payout token contract
  --payout-token-name TEXT     name of the payout smart contract
  --kyc-address TEXT           address of kyc contract
  --payout-name TEXT           name of the payout,  [required]
  --uri TEXT                   announcement uri  [required]
  --type INTEGER               announcement type  [required]
  --options LIST               additional payout contract options
  --help                       Show this message and exit.

payout-deposit

the private key here needs to belong to the customer who wants to fetch tokens

Usage: sto payout-deposit [OPTIONS]

  the private key here needs to belong to the customer who wants to fetch
  tokens

Options:
  --help  Show this message and exit.

payout-dividends

None

Usage: sto payout-dividends [OPTIONS]

Options:
  --transfer-amount INTEGER  amount of sto tokens to trade for payout token
                             [required]
  --help                     Show this message and exit.

reference

Print out the command line reference for the documentation.

Usage: sto reference [OPTIONS]

  Print out the command line reference for the documentation.

Options:
  --help  Show this message and exit.

token-scan

Update token holder balances from a blockchain to a local database.

Reads the Ethereum blockchain for a certain token and builds a local database of token holders and transfers.

If start block and end block information are omitted, continue the scan where we were left last time. Scan operations may take a while.

Usage: sto token-scan [OPTIONS]

  Update token holder balances from a blockchain to a local database.

  Reads the Ethereum blockchain for a certain token and builds a local
  database of token holders and transfers.

  If start block and end block information are omitted, continue the scan
  where we were left last time. Scan operations may take a while.

Options:
  --start-block INTEGER  The first block where we start (re)scan
  --end-block INTEGER    Until which block we scan, also can be 'latest'
  --token-address TEXT   Token contract address  [required]
  --help                 Show this message and exit.

token-status

Print token contract status.

Usage: sto token-status [OPTIONS]

  Print token contract status.

Options:
  --address TEXT  Token contract address  [required]
  --help          Show this message and exit.

tx-broadcast

Broadcast waiting transactions.

Send all management account transactions to Ethereum network. After a while, transactions are picked up by miners and included in the blockchain.

Usage: sto tx-broadcast [OPTIONS]

  Broadcast waiting transactions.

  Send all management account transactions to Ethereum network. After a
  while, transactions are picked up by miners and included in the
  blockchain.

Options:
  --help  Show this message and exit.

tx-last

Print latest transactions from database.

Usage: sto tx-last [OPTIONS]

  Print latest transactions from database.

Options:
  --limit INTEGER  How many transactions to print
  --help           Show this message and exit.

tx-next-nonce

Print next nonce to be consumed.

Usage: sto tx-next-nonce [OPTIONS]

  Print next nonce to be consumed.

Options:
  --help  Show this message and exit.

tx-restart-nonce

Resets the broadcasting account nonce.

Usage: sto tx-restart-nonce [OPTIONS]

  Resets the broadcasting account nonce.

Options:
  --help  Show this message and exit.

tx-update

Update transaction status.

Connects to Ethereum network, queries the status of our broadcasted transactions. Then print outs the still currently pending transactions or freshly mined transactions.

Usage: sto tx-update [OPTIONS]

  Update transaction status.

  Connects to Ethereum network, queries the status of our broadcasted
  transactions. Then print outs the still currently pending transactions or
  freshly mined transactions.

Options:
  --help  Show this message and exit.

tx-verify

Verify source code of contract deployment transactions on EtherScan.

Users EtherScan API to verify all deployed contracts from the management account.

Verify all past contract deployments:

sto verify

Verify certain deployed contracts:

sto verify –contract-addresses=0x1D88fd4fC47711Fc28d105aE2D96A4A9E5c2ae9C,0x57aa933E93Ea627a746DD335c23A90c8D8da825B
Usage: sto tx-verify [OPTIONS]

  Verify source code of contract deployment transactions on EtherScan.

  Users EtherScan API to verify all deployed contracts from the management
  account.

  Verify all past contract deployments:

      sto verify

  Verify certain deployed contracts:

      sto verify --contract-addresses=0x1D88fd4fC47711Fc28d105aE2D96A4A9E5c2
      ae9C,0x57aa933E93Ea627a746DD335c23A90c8D8da825B

Options:
  --contract-addresses TEXT  Comma separated list of contract addresses to
                             verify
  --help                     Show this message and exit.

version

Print version number and exit.

Usage: sto version [OPTIONS]

  Print version number and exit.

Options:
  --help  Show this message and exit.

voting-deploy

Deploys Voting contract to desired ethereum network network, ethereum-abi-file, ethereum-private-key, ethereum-node-url are required args

Usage: sto voting-deploy [OPTIONS]

  Deploys Voting contract to desired ethereum network network, ethereum-abi-
  file, ethereum-private-key, ethereum-node-url are required args

Options:
  --token-address TEXT  address of security token contract  [required]
  --kyc-address TEXT    address of kyc contract
  --voting-name TEXT    name of the voting,  [required]
  --uri TEXT            announcement uri  [required]
  --type INTEGER        announcement type  [required]
  --options LIST        additional voting contract options
  --help                Show this message and exit.

Developer notes

Information for package developers.

Making a release

Instructions for the future-maintainers-to-be.

First send out PyPi release:

# First edit setu.py manually - auto version bump is broken
# Build and upload PyPi egg
export VERSION=0.2.0
make reference
make release

Then push out new Docker:

# Build docker image
docker login --username=miohtama
make publish-docker

Tutorial to add a new command and test if process works end to end

For the purpose of this tutorial, lets create a command ethereum-token-transfer that takes a private key and calls transfer()

  1. Add the command in sto.cli.main:
@cli.command(name="ethereum-token-transfer")
@click.option('--csv-input', required=True, help="CSV file for entities receiving tokens")
@click.option('--address', required=True, help="Token contract address")
@click.pass_obj
def ethereum_token_transfer(config: BoardCommmadConfiguration):
    from sto.distribution import read_csv
    from sto.ethereum.distribution import distribute_tokens

    dists = read_csv(logger, csv_input)
    if not dists:
        sys.exit("Empty CSV file")

    new_txs, old_txs = distribute_tokens(
        logger,
        dbsession,
        config.network,
        ethereum_node_url=config.ethereum_node_url,
        ethereum_abi_file=config.ethereum_abi_file,
        ethereum_private_key=config.ethereum_private_key,
        ethereum_gas_limit=config.ethereum_gas_limit,
        ethereum_gas_price=config.ethereum_gas_price,
        token_address=address,
        dists=dists,
    )
    # write the logic in `distribute_tokens` or refer to `distribute_tokens` method in `sto.ethereum.distribution`
  1. Write the necessary fixtures to deploy the smart contracts needed to deploy security token. Use the deploy fixture in tests.cli.test_cli.
@pytest.fixture
def kyc_contract(deploy, dbsession, monkeypatch_get_contract_deployed_tx, get_contract_deployed_tx):
    args = {}
    deploy('BasicKYC', args)
    tx = get_contract_deployed_tx(dbsession, 'BasicKYC')
    return tx.contract_address
  1. Before issuing tokens whitelist the address that will be used to deploy security token smart contract
@pytest.fixture
def whitelisted_owner():
    result = click_runner.invoke(
            cli,
            [
                '--database-file', db_path,
                '--ethereum-private-key', private_key_hex,
                '--ethereum-gas-limit', 999999999,
                'kyc-manage',
                '--whitelist-address', priv_key_to_address(private_key_hex)
            ]
        )
        assert result.exit_code == 0
  1. Deploy the security token smart contract in restricted mode and broadcast the transaction.
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        'issue',
        '--name', "Moo Corp",
        '--symbol', "MOO",
        '--url', "https://tokenmarket.net",
        '--amount', 9999,
        '--transfer-restriction', request.param
    ]
)

assert result.exit_code == 0
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        'tx-broadcast',

    ]
)
assert result.exit_code == 0
  1. Whitelist customer address that will participate in the token distribution.
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        'kyc-manage',
        '--whitelist-address', entry.address
    ]
)
assert result.exit_code == 0
  1. Distribute the tokens.
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        "distribute-multiple",
        '--csv-input', sample_csv_file,
        '--address', token_address
    ]
)
  1. Scan token to update balances
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        "token-scan",
        "--token-address", token_address,
    ]
)
  1. Check the cap table
result = click_runner.invoke(
    cli,
    [
        '--database-file', db_path,
        '--ethereum-private-key', private_key_hex,
        '--ethereum-gas-limit', 999999999,
        "cap-table",
        "--identity-file", csv_file,
        "--token-address", token_address,
    ]
)
# parse result.output to check the exact number of entries created as specified in the csv