ERC1400 — Implementation Approach – Polymath Network
ERC1400 has received immense support from the community since its inception and has evolved as the most accepted and versatile standard for securities on Ethereum. After multiple rounds of interactions with the community (e.g. community calls, Ethereum Magician Token Rings), the ERC1400 standard is now mature enough to move into the next stage of its development life cycle to lead the security token space.
ERC1400 is also called a library of security token standards. It acts as an umbrella and additional standards falling under the umbrella include:
ERC1400 is a community-driven standard which allows the community to implement ERC1400 API call in their own ways. View three different implementations below:
Polymath is one of the major contributors in the security token community and Polymath has its own security token implementation called ST20 which conforms to the ERC1400 standard. We are very excited to adopt the ERC1400 standard for the security token contract of our ST20 protocol in the 3.0 release of polymath-core. To learn more about the 3.0 release, read the blog post from Polymath’s Head of Technology, Adam Dossa.
For the ease of understanding the
ERC1400 implementation approach, we will take a look into the 3 key functions that have complex logic whilst being simple in functionality.
In the ERC20 standard there are two functions called
allowance() which are used to verify the transaction in terms of whether it will succeed or not before executing on-chain. Similarly, ERC1400 facilitates
canTransferFrom() which verifies the transaction before executing the transaction on-chain. In order to achieve this functionality, we introduced a new stateless function called
ITransferManager interface (it is an interface that every transfer restriction module needs to follow in the ST20 protocol).
bytes calldata _data
returns(Result result, bytes32 partition);
canTransferFrom() loops over all the transfer managers attached to a security token and calls the
verifyTransfer() function of every attached transfer manager to validate the transfer rule. If any of the transfer managers invalidate the transaction inputs then
canTransfer/ canTransferFrom will return the reason for failure, identified by the
byte return value and this byte value can be mapped with an off-chain directory (following the
ERC-1066 standard). It signifies that if the transaction will be executed on-chain at the same time it will not succeed. To get more insight into the failure causes we are returning
application reason code i.e the transfer manager address that causes the failure of the transaction. It is more specific to our developers who will use that address of transfer manager for debugging.
This is one of the key functions of
ERC1410 that will facilitate the querying of the partition balance. The current implementation of the ST20 security token is not leveraging the partition functionality extensively. We take this decision in favor of avoiding the complexity of the protocol in our upcoming release. Wait!! then how did we implement balanceOfByPartition() if there is not a partitioning functionality?
The answer is that we are trying to make our protocol intelligent enough to automatically understand which partition balance needs to be deducted or which partition balance needs to be increased without giving the partition name explicitly. Moving into the same direction in our upcoming release of polymath-core we are introducing two partitions i.e
UNLOCKED. A token holder can easily query its balances of the partitions using the
balanceOfByPartition() function. It loops through all the transfer managers and queries the balance as per the given partition by using the
getTokensByPartition() function, which will be implemented by all transfer managers.
TransferManagers will return the locked and unlocked balances according to their transfer rules. Where
UNLOCKED partition value will be the minimum of all the unlocked balances retrieved from different transfer managers while
LOCKED partition value will be the maximum of all the locked balances.
As per the
ERC1410 specs this function is used to transfer the ownership of the tokens from a given partition. How does this function work in our implementation?
* @notice Transfers the ownership of tokens from a specified partition from one address to another address
* @param _partition The partition from which to transfer tokens
* @param _to The address to which to transfer tokens to
* @param _value The amount of tokens to transfer from `_partition`
* @param _data Additional data attached to the transfer of tokens
* @return The partition to which the transferred tokens were allocated for the _to address
bytes memory _data
) public returns (bytes32)
The latest release will only support two partitions
UNLOCKED. As the literal meaning of
LOCKED partition suggests, tokens in the locked partition are locked by nature while
UNLOCKED partition tokens are free to transact. It means token holders can only transfer
UNLOCKED partition value.
treansferByPartition() returns the receiving partition of the
_to address, which is hard to determine. To resolve this we follow a simplistic approach where the return partition will be
LOCKED if the change in
LOCKED partition of
_to address is equal to the
_value transferred otherwise it is
UNLOCKED . This solution will give you probabilistic information rather than precise information about the return partition.
Polymath’s 3.0 implementation of ST20 is fully compliant with the ERC1400 security token standards i.e Document standard
ERC1643 , Controller standard
ERC1644, Core security token standard
ERC1594 & Partially fungible token standard
ERC1410. Full Implementation can be found here and related getters can be found here.
The ST20 3.0 security token contract is fully upgradable so that additional partitions or other functionality can be easily supported in future releases.