We just open-sourced the Tokenize.it Smart Contracts

Christoph Jentzsch
Corpus
Published in
10 min readMar 24, 2023

--

Currently, fundraising is a mess. It’s a complex and overwhelming process, involving various jurisdictions, legal frameworks, and payment methods. Tokenize.it aims to simplify the process of private and public rounds, as well as employee participation, by creating standards in the form of smart contracts in conjunction with a tailored legal approach. This allows for instant settlement at pre-defined terms. The Ethereum blockchain provides a battle-tested ledger to record token balances and transactions.

An important part of this approach are the smart contracts, which we quietly released to the public not too long ago.

Consider this post as an introduction to our smart contracts. Keep reading to learn more!

Principles

We followed a set of guiding principles when writing these smart contracts. These principles influenced what we did and didn’t do, and are important to understand before we dive into the technical details.

  1. Simplicity & Security
    They go hand in hand. We kept the contracts as simple as possible, often even at the expense of some nice-to-have features which would have added complexity. This approach makes the contracts more readable for a technical audience and makes it easier to detect potential bugs. We kept the number of lines of code below 700 — after Prettier formatting. We avoided extensive gas cost optimizations, such as using assembly or compressing storage by putting many variables in a 256-bit slot, in favor of readability and simplicity. We believe this was the most important security decision we made.
  2. Modularity
    We separated each major functionality, including the token, an allow list, and two different investment styles, into their own smart contracts, making them easily interchangeable. That way, we allow updating individual parts of the whole system as needed in the future. For example, swapping the AllowList contract (which is set in the Token contract) allows for new features to be added if needed.
  3. Reuse of proven code
    We based all of our smart contracts on the widely used and battle-tested libraries from OpenZeppelin. We owe a debt of gratitude to this library and the giants whose shoulders we stand on. This approach allowed us to keep the actual written code to a minimum, since most of the functionality lies in the inherited contracts.

Now that you have an understanding of our guiding principles, let’s dive into the contracts themselves (the following text was authored by our superstar developer, Malteish):

Smart contracts

Let’s start with an overview of our contracts and their functions. The following diagram shows the contracts we will discuss in the next paragraphs.

The “platform” (green) will be operated by Tokenize.it and consists of:

  • AllowList, which stores information about investors
  • FeeSettings, which enable the platform to collect fees from the companies

The “company” (blue) in this example is called Gemütlichkeit GmbH and manages:

  • The token representing the rights to a company share
  • Investment contracts: ContinuousFundraising and PersonalInvite

A currency such as USDC can be used, which is usually controlled by the issuer (purple). For example, USDC is issued by Circle.

AllowList

Investor registry, holding the attributes that are later used to check if an address may use a token.

  • Stores attributes for each address, with 1 address representing 1 investor.
  • These attributes can be used to determine the eligibility of an address to transact with specific tokens, which also determines if the address can invest in a specific company.
  • The platform (i.e. Tokenize.it) will manage a single AllowList contract, ensuring central control and management of the data stored in the contract.
  • Examples of attributes stored in the AllowList contract include “Passed KYC”, “German resident”, and “of age in country of residence”.
  • Provides a valuable service for companies, as they don’t need to know and vet their individual investors. They can simply choose an appropriate set of requirements in their token contract, and the Token and AllowList contracts will ensure that tokens can only be transferred to and from addresses that meet these requirements.
  • The Token stores the address of the AllowList it uses. The company can switch to another AllowList managed by itself or any other entity at any time.
  • The company can also set the requirements for transactions in the token contract to zero, which effectively means that everyone can send and receive the token regardless of their status in the AllowList.

FeeSettings

As a service provider and for-profit company, Tokenize.it needs revenue streams to operate sustainably. Technically it can charge a fee whenever

  1. one of the investment contracts processes a payment.
    This fee is charged in the payment currency.
  2. new tokens are minted
    This fee is charged in company tokens, thus aligning us with the founders and giving us a big incentive to help them realize their potential.

To realize this, the FeeSettings contract is implemented with the following attributes:

  • Three fees can be controlled separately:
  • investment fee for ContinuousFundraising (public offer)
  • investment fee for PersonalInvite (private offer)
  • token minting fee
  • Fees can be set between 0% and 5%.
  • Fee increases can only be executed 12 weeks after being announced.
  • Fee decreases can be done immediately.
  • ERC165 implementation, which verifies the interface of the contract and prevents a potential malfunction in the Token contract if a switch to an incorrect contract is made.
  • A feeCollector address that must be used for all fee payments is stored.

However, the construct of a self-sovereign company having control over their token and investment contracts, while Tokenize.it still requires them to pay fees, presents some distinctive challenges. Although the company can switch to a different AllowList whenever they desire, the same is not true for FeeSettings. A switch to another FeeSettings contract is only possible through a proposal from Tokenize.it, which needs to be accepted by the company.

Token

  • The token issued by this smart contract gives the owner economic rights, which are similar to being a shareholder, and allows for conversion into actual company shares. Its value and utility are derived from this possibility, which is enshrined in the legal framework.
  • Compliant with the ERC20 standard
  • Extensive role management provides granular access control. This ensures that only authorized individuals can access and manage the investment process.
  • The token is controlled by the company, making it non-custodial with respect to the Tokenize.it platform.
  • We implemented EIP2612 (Permit) and EIP2771 meta-transactions to improve UX. Neither founder nor the investor need to hold ether in their wallet, as all transactions can be executed securely and trustlessly by the platform on their behalf.
  • The company can limit who is able to use the token by setting requirements that are verified for each address using an AllowList. The token holds a reference to a specific AllowList, establishing compliance with legal requirements such as KYC and nationality limitations as needed.
  • Each company needs its own token contract. There will be many (N) deployments for the numerous (N) companies using Tokenize.it.

Fundraising

Currently, two smart contracts enable atomic investments, meaning that payment transfer and minting of company tokens are completed within the same transaction. This eliminates the risk of funds being transferred without tokens being issued, or tokens being issued without payment. (We know this is an expected feature of blockchain technology, but we’re still excited about it!)

One of the smart contracts enables a large audience to participate in a funding round, while the other represents a single investment deal between a company and a specific investor.

Both contracts use the token’s mint function. Without the company granting the smart contracts a sufficient minting allowance, all investments will fail. This two-layered approach enhances security. All fundraising contracts are controlled by the company.

Public ContinuousFundraising

The ContinuousFundraising smart contract enables a company to raise funds through token sales in a secure and streamlined manner.

  • Enables the company to update the price, token sale amount, payment currency, and other settings as needed. This allows the company to adapt to changing market conditions, investment demands, company valuation, and internal needs.
  • The contract is owned by the company, giving it complete control over the investment process.
  • It can be paused (deactivated) if necessary. This allows the company to suspend fundraising.
  • The contract must be paused in order to change settings, and it can only be unpaused 24 hours after the last change at the earliest. This protects investors from malicious activity, such as a company trying to front-run their investment with a sudden price increase. The same contract can be used again and again, so one company will likely only deploy one ContinuousFundraising contract.

PersonalInvite

This is the very first feature Tokenize.it will support when launching the platform. It will be called “Private Offer” in the frontend, a term that is more meaningful to investors and founders.

  • Offers a customized investment deal with custom payment currency, price, and deadline, which can be drafted by the company for a specific investor, or vice versa. This allows for fundraising without open rounds or special conditions for special investors.
  • The investment is executed by the constructor during deployment, meaning that allowances must be granted by both parties before deployment. These allowances signal the commitment of both parties to the investment deal.
  • Makes use of CREATE2, which enables the calculation of the contract address before deployment. This allows for the details of the investment deal to remain off-chain and confidential until the deal is executed.
  • Each deal means one contract deployment, so one company will likely deploy several contracts.

Employee Participation (company)

Employee participation, e.g. vesting a set amount of tokens with a cliff, is possible through our variant of the dssVest contract. It was forked from the existing dssVest contract by MakerDAO to add ERC2771 support for an improved user experience.

It lives in a different repository and is not the main focus of this post.

Class diagram

Walkthrough

Enough of the basics! Let’s invest and see the magic. In this example, “Gemütlichkeit GmbH”, a cuckoo-clock company, has already deployed its Token and ContinuousFundraising contracts through the Tokenize.it web app. Here are the steps Alice would take to invest:

  1. Alice finds the investment offer and reviews the details, such as the pitch deck, cap table and price per token.
  2. She accepts the terms and approves the payment.
  3. She receives tokens from the company, which gives her the same economic rights as a shareholder and the ability to convert to actual shares.

However, behind the scenes, there’s more going on. Let’s take a closer look at the sequence of events, and start with a visualization:

Here is a more detailed description of the sequence above, which focuses on the smart contracts, but adds some other information, too.

  1. Alice clicks the “Invest now” button on Gemütlichkeit GmbH’s website, which takes her to Tokenize.it. She signs up and completes the KYC process.
  2. She logs in with her wallet address.
  3. She provides minimal relevant information.
  4. She is forwarded to the KYC provider, who approves her.
  5. Her wallet address is added to the AllowList contract, setting bits according to what is known about her: she is a German citizen, she is of age, and she passed KYC.
  6. Alice is taken to the investment view, where she can see the current price for the shares and how much she can buy. She also sees the current cap table of the company, and how big a share she will acquire through a given investment. She decides to buy 300 tokens at 3 USDC/token, which will cost her 900 USDC.
  7. The Token and ContinuousFundraising contracts for Gemütlichkeit GmbH were released long before.
  8. Luckily, she holds USDC in her wallet. After signing two messages with Metamask, her investment is displayed as pending.
  9. The first Metamask interaction signs a permit() meta-transaction on the currency, USDC in this case. It allows the ContinuousFundraising contract to spend 900 USDC of Alice’s funds.
  10. The second time Metamask comes up, it asks for a signature on the buy() function of the ContinuousFundraising contract, which will be used to execute the investment through an EIP2771 meta-transaction.
  11. Both signatures are collected by the backend, which first executes the permit.
  12. The investment itself is executed next. We will skip the EIP2771 part of the execution but have a deeper look into the relevant proceedings in our smart contracts.
  13. After checking the bounds of the amount of tokens Alice wants to buy (not too few, not too many), the investment cost is calculated.
  14. Then, ContinuousFundraising asks its token for the token’s FeeSettings. It uses this FeeSettings contract to determine how much currency (USDC) it has to pay, and transfers this fee of 9 USDC (1%) to the feeCollector address.
  15. Next, the remaining payment of 891 USDC (total cost — fee) is transferred to the company’s currencyReceiver address.
  16. Afterward, the Token’s mint function is called.
  17. Within this function, the Token contract checks that the ContinuousFundraising contract has sufficient minting allowance to mint the requested amount of tokens.
  18. It then ensures that Alice meets the token’s requirements, such as passing KYC and being of age. These are compared to Alice’s record in the AllowList, which satisfies the requirements.
  19. 300 tokens are minted to Alice’s address.
  20. The token contract queries the FeeSettings contract on how many tokens to pay as a fee when minting 300 tokens. As the token fee is currently set to 0.5%, the FeeSettings contract requests a fee of 1.5 tokens.
  21. An additional 1.5 tokens are minted to the feeCollector address.
  22. A few moments later, the state changed to finalized. Alice has just invested in Gemütlichkeit GmbH.
  23. Alice can see the corresponding tokens in the web application, the block explorer, and her wallet.
  24. The company’s currencyReceiver wallet has received the payment.
  25. The company’s cap table is updated in real-time with accurate information for all investors and the founder.

An investment such as the one described above results in a transaction like this one.

Wrap up

We developed these smart contracts to streamline investments and company ownership. We have open-sourced them because we believe in transparency and encourage others to build innovative projects using these contracts.

In this post, we have introduced each contract and presented one example of their inner workings.

We appreciate your feedback on the project, the contracts, and our implementation!

Thank you for taking the time to learn about our smart contracts for streamlined investments and ownership. If you found this post interesting and want to stay up-to-date on our latest developments, follow us on Twitter or LinkedIn. If you wish to learn more about our smart contracts and how they can benefit your company or investments, please contact us to schedule a demo.

Authors: Christoph Jentzsch and Malteish

--

--