Smart Contracts for applying regulatory compliance to tokenized securities issuance and trading
We would love your feedback. Have questions, want to contribute, or have general comments? Ping the team and join the conversation at https://gitter.im/harborhq.
R-Token is a permissioned token on the Ethereum blockchain, enabling token transfers to occur if and only if they are approved by an on-chain Regulator Service. The Regulator Service can be configured to meet relevant securities regulations, Know Your Customer (KYC) policies, Anti-Money Laundering (AML) requirements, tax laws, and more. Implemented with the correct configurations, the R-Token standard makes compliant transfers possible, both on exchanges and person to person, in ICOs and secondary trades, and across jurisdictions. R-Token enables ERC-20 tokens to be used for regulated securities.
R-Token implements ERC-20 methods transfer()
and transferFrom()
with an additional check to determine whether or not a transfer should be allowed to proceed. The implementation of check()
can take many forms, but a default whitelist approach is implemented by TokenRegulatorService
. Token and participant-level permissions, when used in different combinations, can be used to satisfy multiple regulatory exemptions. The ServiceRegistry
is included as a mechanism to facilitate upgrading the R-Token check logic as rules change over time.
- RegulatedToken
- Permissioned ERC-20 smart contract representing ownership of securities
- Compatible with existing wallets and exchanges that support the ERC-20 token standard
- Overrides the existing ERC-20 transfer method to check with an on-chain Regulator Service for trade approval
- RegulatorService
- Contains the permissions necessary for regulatory compliance
- Relies on off-chain trade approver to set and update permissions
- ServiceRegistry
- Accounts for regulatory requirement changes over time
- Routes the R-Token to the correct version of the Regulator Service
Upgradable, token-level trade permission and participant-level trade permissions.
- Configurable without code modification and need for more security auditing
- Upgradable so an owner/admin can change business logic as rules evolve over time
- An owner/admin can lock/unlock trading for a period of time
- An owner/admin can whitelist/blacklist partial token transfers
- An owner/admin can qualify/disqualify a trade participant from sending tokens
- An owner/admin can qualify/disqualify a trade participant from receiving tokens
The ServiceRegistry
is used to point many RegulatedToken
smart contracts to a single RegulatorService
. This setup is recommended so that rules and logic implemented by the RegulatorService
can be upgraded by changing a single RegulatorService
address held by the ServiceRegistry
.
When RegulatorService
logic needs to be updated, the migration path resembles a process like this:
- Deploy new RegulatorService (V2)
- Copy required state from Regulator Service V1 to RegulatorService V2
- Call
replaceService()
onServiceRegistry
with address pointing to RegulatorService V2
In the TokenRegulatorService
implementation of the RegulatorService
interface, there are token level permissions and participant level permissions. These permissions should be updated by an off-chain process like shown below:
Token-level permissions include:
locked
- controls locking and unlocking of all token trades for a particular tokenpartialAmounts
- allows or disallows transfers of partial token amounts
Participant-level permissions include:
PERM_SEND
- permission for a participant to send a token to another accountPERM_RECV
- permission for a participant to receive a token from another account
Administrative privileges on R-Token smart contracts are divided into two roles: Owner
and Admin
. We will continue to decentralize administration in future versions.
The privileges for each role are defined below:
RegulatedToken | ServiceRegistry | RegulatorService | |
---|---|---|---|
Owner | Can Mint | Transfer Owner / Replace Service | Update Token-Level Settings / Transfer Ownership / Transfer Admin |
Admin | N/A | N/A | Update Participant-Level Settings |
The R-Token project was created with Truffle so all truffle commands will work.
- Install dependencies.
yarn install
- Pick a 12 word mnemonic and put this in your bash profile so you can launch ganache-cli with a consistent seed.
export RTOKEN_DEVELOPMENT_MNEMONIC="YOUR_MNEMONIC_HERE"
- Run ganache-cli so truffle commands will work.
yarn test:ganache
truffle test
truffle migrate
Normal R-Tokens should only be minted under carefully regulated conditions, such as an ICO. Normal R-Tokens also restrict ERC20.transfer()
and ERC20.transferFrom()
to ensure that trades comply with government regulations or other business needs.
Kovan has three test tokens already deployed to it:
- Copper - CPPR - 0x5cdcc989560693e845060d271399216d8ab00c25
- Silver - SLVR - 0x9843430d81290c90701bd655a7f19222b1de1f5f
- Gold - GOLD - 0x88c3f6e2ddd8e65ec548197f2670623c5d876459
Mint 100
CPPR
tokens to address 0xd4afd5525ada1efa8ae661be1a0b373eb9e68498
on your local development
environment(localhost:8545).
node scripts/mint_test_tokens.js development 100 CPPR 0xd4afd5525ada1efa8ae661be1a0b373eb9e68498
Mint 100
GOLD
tokens to address 0xd4afd5525ada1efa8ae661be1a0b373eb9e68498
on kovan
.
node scripts/mint_test_tokens.js kovan 100 GOLD 0xd4afd5525ada1efa8ae661be1a0b373eb9e68498
Developers can control if TestRegulatedToken transfers succeed or fail by adjusting the transaction amount.
- Approved: 0 >= amount < 10
- Error, Token is locked: 10 >= amount < 20
- Error, Token is not divisible: 20 >= amount < 30
- Error, Sender cannot send: 30 >= amount < 40
- Error, Receiver cannot receive: 40 >= amount < 50
testToken.transfer(to, 5); // Approved
testToken.transfer(to, 15); // Rejected, Token is locked
testToken.transferFrom(from, to, 5); // Approved
testToken.transferFrom(from, to, 15); // Rejected, Token is locked