6.1 KiB
eip | title | author | type | category | status | created |
---|---|---|---|---|---|---|
902 | Token Validation | Brooklyn Zelenka <brooklyn@finhaven.com>, Tom Carchrae <tom@finhaven.com>, Gleb Naumenko <gleb@finhaven.com> | Standards Track | ERC | Draft | 2018-02-14 |
Simple Summary
A protocol for services providing token ownership and transfer validation.
Abstract
This standard provides a registry contract method for authorizing token transfers. By nature, this covers both initially issuing tokens to users (ie: transfer from contract to owner), transferring tokens between users, and token spends.
Motivation
The tokenization of assets has wide application, not least of which is financial instruments such as securities. Most jurisdictions have placed legal constraints on what may be traded, and who can hold such tokens which are regarded as securities. Broadly this includes KYC and AML validation, but may also include time-based spend limits, total volume of transactions, and so on.
Regulators and sanctioned third-party compliance agencies need some way to link off-chain compliance information such as identity and residency to an on-chain service. The application of this design is broader than legal regulation, encompassing all manner of business logic permissions for the creation, management, and trading of tokens.
Specification
TokenValidator
interface TokenValidator {
function check(
address _token,
address _subject
) public returns(byte result)
function check(
address _token,
address _from,
address _to,
uint256 _amount
) public returns (byte result)
}
Methods
check/2
function check(address _token, address _subject) public returns (byte _resultCode)
parameters
_token
: the token under review_subject
: the user or contract to checkreturns a one-byte status code, often encoded as hex
check/4
function check(address token, address from, address to, uint256 amount) public returns (byte resultCode)
parameters
_token
: the token under review_from
: in the case of a transfer, who is relinquishing token ownership_to
: in the case of a transfer, who is accepting token ownership_amount
: The number of tokens being transferredreturns a one-byte status code, often encoded as hex
ValidatedToken
interface ValidatedToken {
event Validation(
address indexed subject,
byte indexed result
)
event Validation(
address indexed from,
address indexed to,
uint256 value,
byte indexed result
)
}
Events
Validation/2
event Validation(address indexed subject, byte indexed resultCode)
This event MUST be fired on return from a call to a TokenValidator.check/2
.
parameters
subject
: the user or contract that was checkedresultCode
: a status code
Validation/4
event Validation(
address indexed from,
address indexed to,
uint256 amount,
byte indexed result
)
This event MUST be fired on return from a call to a TokenValidator.check/4
.
parameters
from
: in the case of a transfer, who is relinquishing token ownershipto
: in the case of a transfer, who is accepting token ownershipamount
: The number of tokens being transferredresultCode
: a status code
Rationale
This proposal includes a financial permissions system on top of any financial token. This design is not a general roles/permission system. In any system, the more you know about the context where a function will be called, the more powerful your function can be. By restricting ourselves to token transfers (ex. ERC20 or EIP-777), we can make assumptions about the use cases our validators will need to handle, and can make the API both small, useful, and extensible.
The events are fired by the calling token. Since Validator
s may aggregate or delegate
to other Validator
s, it would generate a lot of useless events were it the
Validator
's responsibility. This is also the reason why we include the token
in the call/4
arguments: a Validator
cannot rely on msg.sender
to determine
the token that the call is concerning.
We have also seen a similar design from R-Token that uses an additional field: spender
.
While there are potential use cases for this, it's not widely used enough to justify passing
a dummy value along with every call. Instead, such a call would look more like this:
function approve(address spender, uint amount) public returns (bool success) {
if (validator.check(this, msg.sender, spender, amount) == okStatusCode) {
allowed[msg.sender][spender] = amount;
Approval(msg.sender, spender, amount);
return true;
} else {
return false;
}
}
A second check/2
function is also required, that is more general-purpose, and does not
specify a transfer amount or recipient. This is intended for general checks,
such as checking roles (admin, owner, &c), or if a user is on a simple whitelist.
We have left the decision to make associated Validator
addresses public, private, or hardcoded
up to the implementer. The proposed design does not include a centralized registry.
It also does not include an interface for a Validated
contract.
A token may require one or many Validator
s for different purposes,
requiring different validations for different, or just a single Validator
.
The potential use cases are too varied to provide a single unified set of methods.
We have provided a set of example contracts here
that may be inherited from for common use cases.
The status codes in the byte
returns are unspecified. Any status code scheme
may be used, though a general status code proposal is fortcoming.
By only defining the validation check, this standard is widely compatible with ERC-20, EIP-721, EIP-777, future token standards, centralized and decentralized exchanges, and so on.
Implementation
Copyright
Copyright and related rights waived via CC0.