Token Permissions

A walk through and invitation to participate

Brooklyn Zelenka
Finhaven
8 min readMar 7, 2018

--

At Finhaven, we’re committed to helping build the open source ecosystems and interoperability of Ethereum and other blockchains. We’ve been making small pull requests and suggestions to various components we use, but recently we prepared a full Ethereum Improvement Proposal (EIP). This is a follow up technical post to our article on Managing the Ownership and Transfer of Security Tokens.

Check out Principal Engineer Brooklyn Zelenka’s description of the Validated Token ERC, browse some other work in progress like Ethereum Status Codes, and come join us in the GitHub comments section on how we can interoperate and work together. #BUIDL

Boris Mann

Motivation, Standards, and Community

There is an obvious desire for automated permissions on Ethereum across a wide range of applications. This is a huge undertaking, and we want to start the discussion on what the best patterns are for us to follow in building tokens and smart contracts that deal with permissions and validation.

Community standards are important. They let everyone share the responsibility of discovery and refining technology, anyone can help shape the discussion, and adopters get to speak a common language. In short, you can leverage the wider community, each build a portion of the infrastructure, partner with each other, and get more out of the network than you could build on your own. Since connections inside networks grow faster than the number of participants, the more the merrier!

There is clearly interest in validation. We submitted a Token Validation EIP, and there is contemporaneous art: Harbor’s Regulated Token System, KlerosPermission Standard Proposal, and Parity Technologies’ chain-bridged KYC offering (PICOPS), to mention a few.

We’re converging on a universal need: we have to comply with regulation (ex. KYC to comply with SEC rules) and business rules (ex. limit the volume of trades of a Non Fungible Token — NFT). Further, with a standard we can aggregate logic and build bridges across multiple regulators, businesses, and users (more on this in a bit).

This isn’t surprising: there is wide application for tokenizing assets, including financial instruments such as securities, microfinance, property (broadly), and so on. 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.

Decentralized Validation

VaaS

When an ecosystem is so new, it’s temping to try to build complete, end-to-end solutions. There’s (nearly) no one else to rely on, and walled gardens provide a feeling of control. Despite the human tendency towards centralization (ex. git vs GitHub), the real power of wiring all of our computers together isn’t to support modern mainframes. The irony of centralization in a distributed environment such as Ethereum should not be lost on any of us 😉

Validation-as-a-Service (VaaS) becomes a very useful concept in a decentralized system. Instead of maintaining your own whitelist, updating your software when regulation changes (in every jurisdiction!), and coordinating with off-chain providers, these changes can be made on-chain automatically, powered by a third-party, and everything Just Works. Developers want these validations to exist outside of the code that they need to maintain, come from a trusted source, and be easily accessible by their smart contracts.

Imagine regulators running their own smart contracts, accessible by anyone, or existing KYC providers going on-chain. They may charge a small fee for their service (as can any smart contract), and this is likely a very viable business model, especially when enabled by a shared protocol.

Caller ↔️ Validator

In the simplest case of our proposed protocol, we have something that looks like a straightforward client-server model. Each individual call looks exactly like this:

ex. the caller may be a smart contract checking if a token holder is on a whitelist

However, nothing is stopping a contract from having a several validators, nor a validator from having several callers. You may need to validate different actions differently (ex. minting, transferring, delegated operators). This avoids the validator having to handle many actions in a single API (rather than a huge number of very specific functions). Different use cases can simply be spun out into several validators, all callable from the same consumer.

If validators need to share functionality, they can communicate between each other using the same API. Validators may also be callers of other validators, which brings us to…

Acyclic Graphs and Aggregates

With all these validation contracts, the obvious next step is to compose them, and then build a validation graph. To put it another way, each validator can also be a client of other validators, using their responses as input. You can have straight aggregators (ANDs and ORs), or more complex logic, internal state, and so on.

For example, here a somewhat contrived example: your travel agent has decided to get with the times and offer vacations on the blockchain with HolidayToken. The token has one top-level validator (controlled by the travel agency) that checks other validators and non-validation contracts to verify:

  • that you are eligible for a travel visa 🎫
  • that you’re allowed to fly at all ✈️️
  • if you need any immunizations for your destination 🍹☣️
  • that your financial planner has budgeted enough for such a trip 💸
A very forward-thinking travel agent’s “HolidayToken” with validation DAG

The above graph may look like there’s some duplication at IDChecker, but this is likely not so. Since the validator will be receiving both who is sending the message and which contract this is ultimately about, it may be providing different information to different requesters.

Technical Design Considerations

Power vs Generality

In any system, the more you know about the context where a function will be called, the more powerful your function can be, but the fewer use cases it can handle. By restricting ourselves to token transfers (ex. ERC-20 and EIP-777) we can make assumptions about the use cases our validators will need to handle, and can make the API small, useful, and extensible.

Another option that we explored to get more generality was encoding everything as binary (bytesN) and casting or parsing into more semantic types for specific use cases. This is an entirely plausible solution, but there are trade-offs. You quickly loose easy interoperability since we now need to know how to interpret the raw bits (which largely defeats the purpose of having a standard). bytes32 doesn’t get you full generality, either, since there are use cases that are won’t fit into a single machine word, or are a better fit for a reference type.

Asynchrony

Not all validations need to be completed in a single request. By including status codes, we can signal that we’re waiting on another contract, or for something to happen off-chain. By bubbling up that a user’s request is awaiting approval, the human on the other end knows that the wheels are in motion. We explore this somewhat in our early status code work.

Since our proposed validation standard is meant to stay very focused, we have not included callback methods to help avoid polling, but it’s absolutely something that belongs in another EIP.

Semantic Status Codes

This validation spec specifies unit8 or hex status codes instead of returning Booleans. The simple reasoning is semantic richness: there are many ways to map Booleans to uint8 or hex status codes (ex. 0 == false), and we can get more fine grained about different kinds of pass and fail responses. In fact, our current status code draft has an entire row of more semantic failures, much like 400s & 500s in HTTP status codes. This is a quick win, enabling developers to more easily write fully automated, self-sufficient contracts.

Example: high-level status code sequence diagram

API Matching

The signatures look very similar to (though not the same as) those in ERC-20 and EIP-777. These are well designed APIs, and cover exactly what we’re focused on: tokens. Token validation is going to need to be compatible with these and future standards.

We attempted to strike a balance: we don’t want to parrot the ERC-20 API directly, since it may not always be the One True Token. The current design is able to handle ERC-20, EIP-721 (NFTs/collectibles), and EIP-777 with just two methods:

  • checking for transfer of a token amount between two users
  • checking if a user is authorized at all (ex. delegate operator, view balance)

These functions have the same name: check. Solidity has variadic functions and overloading, which gives us this nice economy of naming, and doesn’t force us to impose a use case directly in the name. Please note that the validator spec is not being used to emulate optional arguments; these are distinct functions.

Unbounded Complexity

By having nested validation with aggregation, we can model literally any kind of conditional logic: simple ORs, ANDs, and XORs, switching subvalidators based on amount being transferred, if the block height is even, the phase of the moon, and so on. It’s all fair game.

With great power comes great responsibility

— Spider-Man

Of course this is a double-edged sword, since more complex validation logic is harder to explain to a user if they fail validation, especially when you don’t own all of the contract code and state, and there’s a gas limit. In short: we recommend exercising constraint and keeping hierarchies reasonable.

Future Directions

Validator Helper Library

The EIP links to reference implementations, but we may be able to go further.

The team at Finhaven is a big fan of open source software, and enjoy writing libraries. We’re in the early phases of designing a library that would provide helpers for validation, complete with rollback, status codes, aggregation helpers, and so on.

No promises on a release yet, since Solidity does limit how abstract such a library could be, but we’re looking into it.

Status Code EIP

Status codes are ubiquitous (and very useful!) on the “traditional” internet. We’ve mentioned these several times in this post, and yet they’re unspecified in the proposal. There are a couple designs that we’re exploring, but a square grid of hex statuses seems to be bearing the most fruit. This has the potential to smooth over a huge number of currently ad hoc use cases on Ethereum and elsewhere. Want to see something added/removed/changed completely? Let us know!

Continuing to Engage with the Community

We are one team, situated in a particular context, working on our business needs, while trying to be mindful of what’s best for the ecosystem. To broaden our perspective as much as possible, we want to see what works and what doesn’t for others. We’re already reaching out to potential partners in the industry, but we want to hear from you!

The more input, the better we can all make this standard.

Get in touch on our website, ping FinhavenHQ, Brooklyn Zelenka (expede) or Boris Mann (bmann) on Twitter, or hang out in the #dev channel on our Discord server.

--

--