We set out a while ago to build a token contract for TRST, WeTrust’s app token. Though it is 2017 and one might expect that this would be a pretty straightforward exercise, it turned out there was enough maneuvering room left for the team to make development of the token contract interesting and fun.

We defined our most important requirements to be 1) that the contract conforms to the ERC20 standard, 2) that we make its code as simple as possible, 3) that the contract itself be upgradable because, well, knowing exactly what the future holds is not a big part of our skillset, and last but certainly not least 4) that the contract be secure.

1. Enabling ERC20

ERC20 is a standard that allows wallet providers to easily manage tokens — allowing them to be transferred between users, and approving their transfer by other users (this is mostly used to transfer money to contracts). This sounds pretty straightforward but it turns out there is more than one flavor of ERC20. As an example, some implementations throw when an action (e.g. transfer) is unsuccessful, whereas others simply return false. Being the standards geeks that we are, we read the standard to the letter to decide on the best course of action.

The standard explicitly mentions a return value for some of the methods. Take for example:

function transfer(address _to, uint256 _value) returns (bool success)

Our thinking about this is that callers of this function would likely expect it to return false, not throw, in the case of failure, as otherwise there’s no meaning to the return value — and yes, we have a valid underlying assumption that the ERC20 authors are smart chaps. Note that the ERC20 webpage has a lively conversation on the throw vs. return issue, but so far it seems the “return” option remains intact.

2. Satisfying Simplicity

We all know the heavy penalties that may arise due to bugs in contracts. While some contracts represent pretty complex business logic, and this complexity must be manifested in the code (e.g. our Trusted Lending Circle contract), others, like token contracts, can maintain their simplicity without losing any essential functionality.

As much as we love great ideas (like Giveth’s MiniMe clonable token), we preferred to keep our creativity to our (mutable) frontend, while our (immutable) contracts should simply get the job done while reducing the attack surface and the likelihood of any unforeseen bugs.

3. Upholding Upgradability

Simplicity is truly what we aspire to. However, we understood that while this contract should remain viable for years to come, the ERC20 standard and the users’ expectations may change over such long periods of time. Therefore, we decided that an upgrade mechanism has to be added to the contract.

In a domain that aspires to generate trust between strangers like the Ethereum ecosystem, we thought it would set a good example to make sure that contract deployers like ourselves be restricted from doing anything that might hurt users even in the long term.

In the case of Token Contract upgrades, one can think of a scenario in which the contract deployer is malicious. Suppose the deployer decides down the road to implement a malicious 2nd-generation token contract that hurts the users in one way or another — in the extreme case it would allow the deployer to “steal” tokens from other users, but a more moderate example would be generating an emission policy that many users may object to. Therefore the first constraint we wanted to add is an opt-in upgrade. The TRST Token contract will not force users to migrate to any new version, so our users will always be able to remain protected using the older contract.

Here we arrive at a twist in the plot. Originally we were planning to describe the fancy migration mechanism we planned and implemented. It implemented an OutgoingMigration interface and required the future contract to implement an IncomingMigration one. It also protected the users with a minimum migration period. It really *was* fun to design and implement all of this. However, Dmitry and Mikhail, our auditors, identified that all of this was not needed.

Instead, when the time comes and we want to migrate to a new contract, we can write an “exchange contract”. To migrate, a user would approve() their tokens to the exchange contract, and call a method on the exchange contract. The exchange contract will try to transferFrom() tokens from the user and if it succeeds, it will tell the new token contract to create tokens for that user. Much simpler, and much cleaner.

So we decided to go with a Trustcoin that is a simple, easy to use, ERC20 contract.

Solidifying Security

All the above considerations get their worth only if the contract is sufficiently secure. Aside from keeping it simple, we had multiple great engineers look at the code, and added tests to cover any dark areas. If you’re into Solidity, you’re more than welcome to take a look at our repo and review the contract.

As an interesting anecdote, a very interesting security vulnerability in ERC20 was found a few months ago by Mikhail Vladimirov and Dmitry Khovratovich from ABDK consulting (original google doc):

Imagine Alice approving an allowance of 100 ETH for Bob. After a while Alice decides to cut the allowance down to 50 ETH by calling approve(). If Bob sees Alice’s transaction before it gets mined, he can issue a transaction to transferFrom() 100 ETH from Alice and hope to get it mined before Alice’s transaction. If he’s successful, not only will he get 100 ETH (that would’ve been ok), but he would be able to follow that with another transferFrom of 50 ETH.

We could not drop or alter the approve method, in order to support existing wallets, so we instead added another method called compareAndApprove (similar to MV & DK’s suggestions) that will only change one’s allowance to some newAllowance argument if another, oldAllowance argument, passed to it, matches the current allowance. Smarter, newer clients should use this method if possible to avoid the scenario described above.

Actually, after reading Mikhail and Dmitry’s analysis, we decided to hire them to do our security audit. As mentioned above, they helped us significantly simplify the contract and we’re grateful for that. You can find the final security audit here.

Afterword

The smart contract for TRST is only the beginning of a journey for both the team and the community. It is a joint effort to build blockchain-based products that increase financial inclusion worldwide.

Here’s to the financial empowerment of every community out there!

Keep your feedback coming, hit us on our slack channel!