These smart contracts implement tokenize.it's tokenized cap table management. They are released under the GNU General Public License version 3 (GPL-3.0).
- clone repository:
git clone --recurse-submodules git@github.com:corpus-ventures/tokenize.it-smart-contracts.git - enter project root folder:
cd tokenize.it-smart-contracts - if repository was cloned without submodules, init submodules now (not necessary if cloning command above was used):
git submodule update --init --recursive - init project:
yarn install - run tests:
forge test --no-match-test Mainnet
If you are missing dependencies:
- node/npm:
- install nvm
nvm install 18nvm use 18
- yarn:
npm install yarn - foundry: install guide
For information regarding testing, please go to testing.
For information regarding deployment, please go to deployment.
- All shares of a company are tokenized using the Token.sol contract
- Funds are raised through selling of these tokens:
- a customized deal to a specific investor can be realized through the PersonalInvite.sol contract
- continuous fundraising, which is open to everyone meeting the requirements, is done through the ContinuousFundraising.sol contract
- Employee participation is easy:
- direct distribution of tokens (does not need another smart contract)
- vesting can be realized using the DssVest.sol contract by MakerDao
The requirements for an address to send or receive tokens are checked against the AllowList.sol contract. Fees are collected according to the settings in FeeSettings.sol. Tokenize.it will deploy and manage at least one AllowList and one FeeSettings contract.
The smart contracts can be found in the contracts/ folder.
All contracts are based on the well documented and tested OpenZeppelin smart contract suite.
It is possible to directly use all smart contracts in this project, without going through the platform's frontend at all. In order to improve UX, though, a frontend will be offered. In order to improve UX even more, the user will not have to pay gas when using this frontend. This is achieved through three approaches:
- the platform executes transactions like contract deployments that do not require the user's signature
- actions concerning our own contracts that require the user's approval are executed as meta-transactions, using EIP-2711
- granting allowances on external currencies is possible through EIP-2612 (ERC20Permit), which is widely adopted. This is not in the scope of this documentation though.
Two contracts implement EIP-2771, and therefore use a trusted forwarder. The forwarder will be set in the constructor and there is no way to change it after deployment. The forwarder used will be the openGSN v2 forwarder deployed on mainnet. Some information about this contract:
- Documentation and addresses
- Audit reports
- Was deployed 2022-04-21
- It's address is 0xAa3E82b4c4093b4bA13Cb5714382C99ADBf750cA
- Visit on etherscan (see transactions here)
- This dashboard lists the forwarder as second most active forwarder contract with over 2000 transactions executed
- it is also used in our tests.
The platform will maintain a hot wallet (EOA) in order to send transactions to the forwarder contract. This results in the following flow:
- contract A supports EIP-2771 and uses
forwarderas its (one and only immutable) trusted forwarder - user (investor or founder) wants to use function
a(...)of contractAand uses the platform for this - platform (tokenize.it) prepares meta transaction payload and asks user for signature
- user signs the payload with their own key (using metamask or similar)
- platform now has payload and signature and uses its hot wallet to call
forwarder.execute(payload, signature, ...) - forwarder verifies signature and payload on-chain
- forwarder executes
A.a(...)with parameters according to payload - contract
Aonly verifies it is being called by the ONE forwarder it trusts. It does not verify any signatures. This is why the forwarder is called trusted forwarder: it is trusted to do the verification. - contract
Aexecutes functiona(...)in the name of user
This is a trustless process, because:
- the forwarder contract can not be updated
- the trusted forwarder setting in contract A is immutable
- signature verification is executed on-chain
Open gas station network provides tools to execute meta transactions without involving a third party hot wallet. Tokenize.it does not plan on using these tools though. Exclusively using a hot wallet for transaction execution does not harm security at all.
The hot wallet approach might reduce availability, which is not a major concern for this use case (the hot wallet being available whenever the frontend is available is good enough). Keep in mind that EIP-2771 is purely offered for UX reasons. All smart contracts can be used directly, too, further reducing concerns about hot wallet availability.
An Openzeppelin Defender Relay may be used as hot wallet.
The currencies used for payments must conform to the ERC20 standard. This standard is not very strict though. It can be implemented in many ways, including incompatible and even malicious contracts. Therefore, tokenize.it will limit the currencies supported in the web frontend to this list:
- WETH: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
- WBTC: 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599
- USDC: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
- EUROC: 0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c
These four implementations have been checked and tested to work well with the tokenize.it smart contracts. The use of any other currencies is HIGHLY DISCOURAGED and might lead to:
- loss of funds due to various attacks
- partial payments due to the currency deducting a transfer fee
- other issues
The following resources are available regarding the contracts:
- Basic high level overview
- Basic dev overview
- More detailed walkthrough
- In-depth explanation: please read the contracts
- Specification
- Price format explainer
- Fee Collection
- Deployment
- Remaining questions: please get in touch at hi@tokenize.it