EIP2980 - Swiss Compliant Asset Token
# Simple Summary
An interface for asset tokens, compliant with Swiss Law and compatible with ERC-20.
# Abstract
This new standard is an ERC-20 compatible token with restrictions that comply with the following Swiss laws: the Stock Exchange Act, the Banking Act, the Financial Market Infrastructure Act, the Act on Collective Investment Schemes and the Anti-Money Laundering Act. The Financial Services Act and the Financial Institutions Act must also be considered. The solution achieved meet also the European jurisdiction.
This new standard meets the new era of asset tokens (known also as "security tokens"). These new methods manage securities ownership during issuance and trading. The issuer is the only role that can manage a white-listing and the only one that is allowed to execute “freeze” or “revoke” functions.
# Motivation
In its ICO guidance dated February 16, 2018, FINMA (Swiss Financial Market Supervisory Authority) defines asset tokens as tokens representing assets and/or relative rights (FINMA ICO Guidelines). It explicitly mentions that asset tokens are analogous to and can economically represent shares, bonds, or derivatives. The long list of relevant financial market laws mentioned above reveal that we need more methods than with Payment and Utility Token.
# Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
The words "asset tokens" and "security tokens" can be considered synonymous.
Every ERC-2980 compliant contract MUST implement the ERC-2980 interface.
# ERC-2980 (Token Contract)
interface ERC2980 extends ERC20 {
/// @dev This emits when funds are reassigned
event FundsReassigned(address from, address to, uint256 amount);
/// @dev This emits when funds are revoked
event FundsRevoked(address from, uint256 amount);
/// @dev This emits when an address is frozen
event FundsFrozen(address target);
/**
* @dev getter to determine if address is in frozenlist
*/
function frozenlist(address _operator) external view returns (bool);
/**
* @dev getter to determine if address is in whitelist
*/
function whitelist(address _operator) external view returns (bool);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
The ERC-2980 extends ERC-20. Due to the indivisible nature of asset tokens, the decimals number MUST be zero.
# Whitelist and Frozenlist
The accomplishment of the Swiss Law requirements is achieved by the use of two distinct lists of address: the Whitelist and the Frozenlist. Addresses can be added to one or the other list at any time by operators with special privileges, called Issuers, and described below. Although these lists may look similar, they differ for the following reasons: the Whitelist members are the only ones who can receive tokens from other addresses. There is no restriction on the possibility that these addresses can transfer the tokens already in their ownership. This can occur when an address, present in the Whitelist, is removed from this list, without however being put in the Frozenlist and remaining in possession of its tokens. On the other hand, the addresses assigned to the Frozenlist, as suggested by the name itself, have to be considered "frozen", so they cannot either receive tokens or send tokens to anyone.
Below is an example interface for the implementation of a whitelist-compatible and a frozenlist-compratible contract.
Interface Whitelistable {
/**
* @dev add an address to the whitelist
* Throws unless `msg.sender` is an Issuer operator
* @param _operator address to add
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
*/
function addAddressToWhitelist(address _operator) external returns (bool);
/**
* @dev remove an address from the whitelist
* Throws unless `msg.sender` is an Issuer operator
* @param _operator address to remove
* @return true if the address was removed from the whitelist, false if the address wasn't in the whitelist in the first place
*/
function removeAddressFromWhitelist(address _operator) external returns (bool);
}
Interface Freezable {
/**
* @dev add an address to the frozenlist
* Throws unless `msg.sender` is an Issuer operator
* @param _operator address to add
* @return true if the address was added to the frozenlist, false if the address was already in the frozenlist
*/
function addAddressToFrozenlist(address _operator) external returns (bool);
/**
* @dev remove an address from the frozenlist
* Throws unless `msg.sender` is an Issuer operator
* @param _operator address to remove
* @return true if the address was removed from the frozenlist, false if the address wasn't in the frozenlist in the first place
*/
function removeAddressFromFrozenlist(address _operator) external returns (bool);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Issuers
A key role is played by the Issuer. This figure has the permission to manage Whitelists and Frozenlists, to revoke tokens and reassign them and to transfer the role to another address. No restrictions on the possibility to have more than one Issuer per contract. Issuers are nominated by the Owner of the contract, who also is in charge of remove the role. The possibility of nominating the Owner itself as Issuer at the time of contract creation (or immediately after) is not excluded.
Below is an example interface for the implementation of the Issuer functionalities.
Interface Issuable {
/**
* @dev getter to determine if address has issuer role
*/
function isIssuer(address _addr) external view returns (bool);
/**
* @dev add a new issuer address
* Throws unless `msg.sender` is the contract owner
* @param _operator address
* @return true if the address was not an issuer, false if the address was already an issuer
*/
function addIssuer(address _operator) external returns (bool);
/**
* @dev remove an address from issuers
* Throws unless `msg.sender` is the contract owner
* @param _operator address
* @return true if the address has been removed from issuers, false if the address wasn't in the issuer list in the first place
*/
function removeIssuer(address _operator) external returns (bool);
/**
* @dev Allows the current issuer to transfer its role to a newIssuer
* Throws unless `msg.sender` is an Issuer operator
* @param _newIssuer The address to transfer the issuer role to
*/
function transferIssuer(address _newIssuer) external;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Revoke and Reassign
Revoke and Reassign methods allow Issuers to move tokens from addresses, even if they are in the Frozenlist. The Revoke method transfers the entire balance of the target address to the Issuer who invoked the method. The Reassign method transfers the entire balance of the target address to another address. These rights for these operations MUST be allowed only to Issuers.
Below is an example interface for the implementation of the Revoke and Reassign functionalities.
Interface RevokableAndReassignable {
/**
* @dev Allows the current Issuer to transfer token from an address to itself
* Throws unless `msg.sender` is an Issuer operator
* @param _from The address from which the tokens are withdrawn
*/
function revoke(address _from) external;
/**
* @dev Allows the current Issuer to transfer token from an address to another
* Throws unless `msg.sender` is an Issuer operator
* @param _from The address from which the tokens are withdrawn
* @param _to The address who receives the tokens
*/
function reassign(address _from, address _to) external;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Rationale
There are currently no token standards that expressly facilitate conformity to securities law and related regulations. EIP-1404 (Simple Restricted Token Standard) it’s not enough to address FINMA requirements around re-issuing securities to Investors. In Swiss law, an issuer must eventually enforce the restrictions of their token transfer with a “freeze” function. The token must be “revocable”, and we need to apply a white-list method for AML/KYC checks.
# Backwards Compatibility
This EIP does not introduce backward incompatibilities and is backward compatible with the older ERC-20 token standard. This standard allows the implementation of ERC-20 functions transfer, transferFrom, approve and allowance alongside to make a token fully compatible with ERC-20. The token MAY implement decimals() for backward compatibility with ERC-20. If implemented, it MUST always return 0.
# Implementations
Although an official implementation of the ERC-2980 has not been presented, in the Specifications section some interfaces have been reported which, once implemented correctly and according to the reccomandations, allow to create an asset token compliant with this ERC.
# Security Considerations
The security considerations mainly concern the role played by the Issuers. This figure, in fact, is not generally present in common ERC-20 tokens but has very powerful rights that allow him to move tokens without being in possession and freeze other addresses, preventing them from transferring tokens. It must be the responsibility of the owner to ensure that the addresses that receive this charge remain in possession of it only for the time for which they have been designated to do so, thus preventing any abuse.
# Copyright
Copyright and related rights waived via CC0 (opens new window).