ChronoBank dev team explaining how they decrease expenses for poll actions and deploying the voting contracts
ChronoMint, as part of its functionality, provides an ability to organize polls — necessary tool for the ecosystem core strategic decisions.
Voting that is designed on blockchain should fulfil the following requirements:
- Price for poll manipulations (creation, vote making, closing)
First step towards the ideal voting subsystem was by designing a couple of contracts (we will call them managers) that would absorb all the work with polls and their management. It’s worth mentioning that keeping data in storage for all kinds of managers uses a special contract StorageManager.
📌 StorageManager could allow or deny access to the storage area.
Going back to the voting, we say these contracts will share common storage space and will have access to the shared variables. On the one hand, this allows to separate the voting process into several functional contracts (getting details, voting itself, manipulating poll’s data) and break down massive sized code into smaller contracts, but on the other hand, this trick binds all contracts and shares state between them. It becomes hard to make changes in a right way. Besides the aforementioned disadvantage, this implementation had huge pricing for making votes and supposed to store a lot of statistical data. All that is not what we have expected from our votings — we want users to be a part of an ecosystem with ease and full participation in its life.
Gas price for some actions that we had with previous votings implementation:
- Сreate a poll — 787111
- Vote — 411641
- End poll — 482976
- Delete poll — 95073
As you might see this is not an excellent numbers and there is a lot of room for improvement…
So we decided to use another approach on the way to new voting. As it was previously we leave one contract (VotingsManager) for manipulating, creating polls in the system and getting general information — it will remain the entry point for any users that will decide to use votings.
But the next will be the most exciting part: instead of storing polls as a set of properties in the shared scope we will create a brand new contract for each poll.
📌 This move will allow us to refactor a lot of logic into separate contract, simplify contracts and make our intentions clearer.
The one thing which confused us was that every time we create a new contract to start a poll that would require more gas for deploying contract than the previous implementation (because of quite a lot of logic and code inside this brand new contract).
Our decision about this concern was to relocate all this logic into a single-instance contract (we call it a backend) that will be deployed once, and also during a poll creation make a new proxy contract instead of fully functional poll contract.
Created proxy contract will have a backend contract address and will redirect all calls to that instance. Proxy contract could be easily implemented with _delegatecall_ assembly instruction which executes delegated functions inside the context of a caller contract (i.e. proxy) and the read/write operations will associate their value with the context. Despite all these advantages we couldn’t return multiple values from a _delegatecall_ without additional specific and wordy code, so it was like we should implement our multiple-return functions right in a proxy contract. Thanks to Byzantium update there were added very handy and useful assembly instructions — _returndatasize_ and _returndatacopy_. These instructions return size of a return data of delegated function and copy return data into а memory. Now we could find them a good place for their application — use them in our proxy contract and clean up its code from any specifics of backend functions. After that we’ll have a contract which will be created every time a new poll is going to be created and it will take a small amount of gas to deploy almost empty contract.
Gas price for the same actions during these changes:
- Create a poll — 849476
- Vote — 159331
- End poll — 443473
- Delete poll — 56486
As you can see we gain almost thrice fewer expenses while performing vote operations which on a significant scale will save a lot of resources for users.
Yes, we still have some increase in poll creation, but it was an acceptable price for reducing ‘vote’ operation. Other methods like closing and deleting a poll also show a reduction in gas consumption.
Deploying Voting subsystem:
v.1: 3089834 + 3789833 + 2891094 = 9.770.761
v.2: 2440890 + 586243 + 3014376 = 6.041.509
Click “👏” on the left side of the screen if you like this post. Put those hands together as many times as you like.
For all latest updates:
☞ Join us in Telegram
Questions? Email us at firstname.lastname@example.org
Comments? Email us at email@example.com
TIME is trading on the following exchanges: