Tgrade Contracts Exposed
Proof of Engagement is now open sourced, revealing advanced smart contract composition
In my previous article, I talked about how Proof of Engagement was built as a complex network of smart contracts that harness the functions provided in Tgrade. Today, we are excited to announce that we are opening up the source code for our PoE Contracts. They are one of the most complex network of CosmWasm contracts (that we are aware of), with extensible test coverage. They also represent the most ambitious consensus changes in Cosmos (since the Cosmos Hub launched in March 2019).
So let’s cut to the chase, how does it work?
How does it work?
If you haven’t heard of Proof of Engagement before, please read an overview of the goals and design first. For the technically minded, it can be viewed as a mix of PoA (trust in the community) and PoS (skin in the game) along with anti-centralization mechanisms and multi-level governance. Quite a mouthful, but take a look at this diagram of the basic protocol design, with governance elements removed:
The voting power starts in two modules: Engagement, which tracks the user’s engagement in the community as a metric of trust, and Staking, which holds TGD (Tgrade) tokens in escrow with a 21-day unbonding period. Each time an account is updated on either one, it triggers a hook on the Mixing contract. This will recalculate the account’s overall weight by multiplying stake and engagement and normalizing it with a sigmoid function that serves as an anti-whale mechanism. (This was long wished on the Cosmos Hub, but engagement points provide the needed Sybil resistance to implement it properly).
The validator contract registers for EndBlock callbacks, and makes payments and updates the validator set once per epoch. The contract has a maximum number of validators (100) and a minimum allowed voting power (mix of stake and engagement). It then queries the Mixer contract to get the top 100 that fit that criteria, which is already stored with proper indexes. It calculates the difference from the last validator set and, being a privileged contract, sends the Validator diff to Tendermint to update the consensus validator set. It also uses the diff to update a final contract (labelled Distribution here), which stores the validators individually, enabling payments and voting.
Block Rewards
We were inspired by the gradually reducing inflation curves for Bitcoin and Osmosis. The idea is that over time, more fees come in, and the token value rises, reducing the need to mint extra tokens for block rewards. Rather than try to define a fixed schedule, we decided to make it responsive to the actual usage of the network.
We define a maximum inflation rate of 6 million TGD / year. As transaction fees are collected, we deduct half the amount from the rewards being minted. As fees are collected, the rewards do go up and the inflation goes down, as we only could half the collected fees. If we get 4 million TGD in fees, we would mint an additional 4 million TGD in rewards to make 8 million TGD distributed. Until 12 million TGD of fees in a year, which would lead to 0 inflation and 12 million TGD in block rewards (twice the base rate).
These rewards are calculated every epoch and can easily be directed to multiple contracts, each implementing the CW2222 interface. CW2222 allows distributing tokens to the current weights/balances of the members without iterating over them all (you need to explicitly withdraw, like in Cosmos’ staking). As a basis, we split rewards between the validators (remember, there are no delegators), the engagement point holders, and the community pool. We also can send smaller percentages to other governance committees (like the Oversight Community) to fund their work.
Ensuring Correctness
By splitting the work into clear units with well-defined APIs, we can cover much of the functionality with detailed unit tests: proper token distribution over a changing membership, a proper mixing function, etc. However, as with any complex system, the degrees of freedom (and potential for errors) grow exponentially with the complexity.
In order to tame this complexity, we build complex, multi-contract test cases in pure Rust code. These can isolate a section of the system and enable us to test configurable sub-sets of the behavior. For example, we could replace the mixer with simply the staking contract and test the validator set is properly updated or check block rewards are properly distributed to engagement. With another initial config, we can test simply the mixer, engagement, and stake and ensure all updates are properly propagated and slashing is working properly.
We found this much more flexible than testing the Cosmos SDK, where you must wire up the application in app.go. All tests that refer to multiple modules import the same BaseApp to do the tests. The “suites” we sue with CosmWasm make it super easy to define various configurations of contracts with different settings, so you can test functionality at the appropriate level of complexity and remove the unnecessary contracts for each test case.
Once the code all passes, we integrate it with the Tgrade application and do some high-level automatic testing to ensure everything works, from CLI staking updating validator power to proper handling when engagement points are slashed. These tests are very high-level system tests that ensure everything is wired together properly and generally works. We do not need to look at all the details or edge cases at this level, just proper configuration and connections.
Multi-Level Governance
After pulling apart the staking, slashing, and distribution modules, and providing a robust, well-tested consensus engine that met the needs of our chain, we went to customize on-chain governance to our needs. One governance to rule them all, based only on validators does make sense for critical items, like upgrading the blockchain or setting Tendermint consensus parameters. However, most designs have been going towards multiple, empowered committees that can take quicker and focused action on one area of interest.
CosmWasm already comes with a very flexible voting contract that can be mapped on top of any other contract that provides a cw4/group interface (membership weights with historical snapshots). And we have many groups that already provide such an interface: engagement, staking, and the validators themselves. As well as Tgrade Trusted Circles. Each one of them can have an appropriate voting contract and we can devolve some of the decision-making to them. In the end, we ended up with a 3 level governance system.
The validators are in charge of base security and can change out the binary when they agree to, so all proposals on that level are handled by the validator-voting contract: chain upgrade, pinning contracts, and migrating the PoE contracts themselves. These are the experts on security and no change can be applied without the approval of a supermajority of them.
On the other hand, we have a community pool that collects 5% of the block rewards and can only take one action — sending its funds to an address. We made a special-purpose voting contract for this one and point it to the set of engagement holders. These are the people who are making the chain great, they are also the most likely to know what else needs to be funded to keep improving.
Tgrade also defines an Oversight Community (OC), which is kind of like the shepherds to keep the blockchain moving in a good direction early on. They run inside a Trusted Circle and are vetted supporters, aligned with Tgrade’s vision. They are responsible for setting the engagement points, as well as slashing validators who are misbehaving in some way that doesn’t involve double-signing (eg. refusing transactions, obvious MEV, minimal uptime, etc). Rather than codify rules and provide loopholes, we leave it to the discretion of the OC to judge misbehavior. They do not participate in the day-to-day processes, but rather shape those processes.
In the future, one could imagine devolving the ability to reward engagement points to the engagement point holders themselves. Or provide some voting power to people who have staked tokens. All of this is possible and doesn’t require a large redesign, simply deploying another contract and wiring it up properly.
Try it Out
The UI for all this governance is still in progress and improving every week, but you can check out the current state of Oversight Community voting and engagement points on our current testnet.
We also invite you to join our latest testnet and participate in some of the upcoming challenges.
And of course, you can now check out our GitHub repo and leave some nice comments there if you feel like.
We’re also hanging out on Discord and Twitter if you want to say hi.