“Anything worth doing is worth overdoing” — David Letterman
We follow on from the UIP2 that we discussed in part 2 of this series. We modularized the Token contract so that we could separate out the data that allowed us upgradeability to a huge amount.
But we want to make the UIP as perfect and as hassle free as possible. No stone must be left unturned. No limitation should live!
Sack the Token Contract
Some people might call this, ‘taking it too far’, but this approach has its own merits and demerits. Let’s change our viewpoint. Look at the whole upgradeability improvement protocols with the idea of removing code from the token contract. We removed data in the last approach. Now a question, why are we stopping there? What if we also remove the logic? Does this not make sense? Here goes nothing.
UIP2.2 The Skeletal Token
We would modularize the Token Contract even further in this approach. We need some new ‘Centre’ contract here. So, we bring you the ControlCentre!
After the ControlCentre introduction, the token contract is just a skeleton now. We took everything from it. It does have all the required methods, but each contain only one line, which are call forwards to the ControlCentre. And judging by its name, ControlCentre is to be the brains of this token architecture. So the ControlCentre processes all the calls, and thereby writes all storage into the DataCentre(which essentially remains the same as before). Might sound a little complicated in theory, lets get to code.
The ControlCentre basically has all the token functions, but takes one additional parameter for each function because the msg.sender has to be transmitted.
Note the onlyToken modifier. We need to make sure that the trust call was processed from the Token contract.
This is how the token contract would look now.
Except for the constant function, each function passes the msg.sender. Now the token doesn’t know about a DataCentre. It just ‘trusts’ the ControlCentre and sends to and receives information from it. Notice that events will still have to be emitted from the subordinate contracts (to make them own it).
The deployment sequence is as follows. Take a shot at running this on remix using this code–
- Deploy the Token.
- Deploy the DataCentre
- Deploy the ControlCentre with the addresses of Token and DataCentre as constructor parameters.
transferOwnershipof the Token and DataCentre to the ControlCentre.
Again, we use the 2 way linking like in the last UIP, but this time it is between the ControlCentre and either of it’s subordinates.
How does it upgrade?
The upgradeability protocol is very similar to the previous UIP 2, expect for upgrading the ControlCentre instead of the token (because we want the address of the token contract to not change)-
- Deploy the new ControlCentre
killthe old ControlCentre contract and enter the newControlCentre address into the params.
- Deploying a new DataCentre at any point would completely ruin the whole point of this series (keeping your data intact)
- The token contract is merely a Satellite, and transmits data between the user and the ControlCentre.
Advantages of the SkeletalToken-
- Technically, all the limitations to the upgradeAgent are gone now. As all the logic is in the ControlCentre, you can fix it in case you have any bug and still have the same old Token contract.
- A much more controllable architecture than UIP2. The contract owner just needs to own the ControlCentre to have total control. This power is felt when you need to have crowdsales for this token.
- You have a central point of failure. If the ControlCentre is compromised, so is the complete architecture.
- The gas cost shoots up a lot because of the multiple external calls. For a simple token transfer that took 35000, costs about 62000 now.
- Now that the Token contract has to stay on the blockchain, you cannot add/remove/modify code in the Token contract, IF you want the address to not change(This is the core of the 6th limitation of UIP 1).
If you are okay with the Token address changing, you can follow this protocol-
- Deploy the new Token satellite.
- Deploy a new ControlCentre.
killof the old ControlCentre contract and enter the new control centre into the params.
transferOwnershipof the NEW Token to the new ControlCentre contract.
In essence, if we have the old data, we can play around with the other contracts as and when we want.
The implementations till now were the easy ones. We have combined every bit of knowledge we had about smart contracts to come up with UIP3. Continue this path to improve your smart contract prowess with the final part of this series. Feel the Force!