Skip to main content

· 6 min read


This summer, our UniRep group took part in the well-known IC3 conference. It's a great event for those interested in the subject of cryptography. You can learn more about IC3 from their website. We were lucky enough to show off the UniRep protocol during the event. Working with some PSE colleagues and two contributors from outside the group, we took part in a week-long project challenge.


Our group of seven brainstormed ideas for the project. We thought about creating an app similar to Stack Overflow where users could earn reputation points by asking and answering questions. However, we knew from past experience that this could be a complicated task. Then, while chatting about the hackathon itself, we had a new idea.

We thought about creating a voting app for hackathons. It could be driven by the community, and hackers could earn reputation points through it. Usually, a panel of judges decides which projects are the best. But what if we made the voting anonymous and fair, and let the hackers themselves vote for the projects they like the most? This way, hackers could start building their reputation from one hackathon to the next.

We've come up with just such an app, which we're calling voteathon.


Idea to action

This application can better illustrate the ownership of data of UniRep protocol. We want to showcase the good use cases to demonstrate the proof of reputation. In this project, hackers can choose to prove how many votes they have to claim the award. The idea of the application is that the user can use the first epoch key to join a project and receive votes. Then the second epoch key is used to prove membership in the hackathon and also is regarded as a nullifier to record the user has voted. After the judge finishes, the user can start claiming their votes. The smart contract will calculate the third highest scores of a project, then set the winnerScore to that number. If a user can generate a proof that the score is higher than winnerScore, the user can mint an NFT (or any other award the hackathon provides) to a specified address. Of course, the user will emit a nullifier as well to notice that the user has already claimed the prize.

Let’s get started

To efficiently build a UniRep app, we use npx create-unirep-app to create all packages we need: circuits, contracts, relay and frontend. Then we modify the smart contracts to have the functions that are required in Voteathon: joinProject, vote, claimPrize. Then the router and frontend should also change how a ZK proof is generated and how the smart contract would be called.

See: Getting Started with create-unirep-app to learn more about how to use unirep related packages.


To achieve the idea that we use the first and second epoch key in Voteathon, we need to customize the smart contract and the client.

In joinProject function in the smart contract, it uses decodeEpochKeySignals to decode the information in the public signals.

Unirep.EpochKeySignals memory signals = unirep.decodeEpochKeySignals(

Note: in version v2.0.0-alpha-3, Unirep provides this decoder, but in the later version, developers have to deploy a helper first. See: epoch-key-verifier-helper

Then we can check if the user reveals nonce and which nonce it is. For example

require(signals.revealNonce == 1, 'Voteathon: should reveal nonce');
require(signals.nonce == 0, 'Voteathon: invalid nonce');

If the user chooses not to reveal nonce, it will all be zero.

And in vote function, it checks that

require(signals.revealNonce == 1, 'Voteathon: should reveal nonce');
require(signals.nonce == 1, 'Voteathon: invalid nonce');

to make sure the user uses two different epoch keys in different actions.

Then in the client, the users are required to generate an epoch key proof with revealing nonces.

const epochKeyProof = await this.userState.genEpochKeyProof({
nonce: 0,
revealNonce: true,

The options can be set to make sure the user generates the proofs with public nonces. By default the revealNonce is set to false.


Then we found out the circuits should be changed as well because we need a nullifier to limit how users claim prizes. Therefore, our external contributor, Joy, helps us build the nullifier circuits and the circuits for users cannot vote themselves projects. Which was a big effort because we need to compile circuits with yarn circuits buildsnark and generate a new verifier (with yarn contracts build). Then it should be imported in the smart contract, and we need to customize how users generate circuit inputs. And it is also hard to use circom to identify which public signal means which variable. We realized that building an additional circuit is not so friendly to create-unirep-app developers. It is neither documented nor automatically built. It was such a good lesson for us to improve the DX in the future.

Then there are many improvements we can make for Voteathon in the future. For example, the signup and joinProject could be merged to reduce the signup time. The idea is that we use manualSignup in Unirep.sol, and generate a proof that includes signup proof and epoch key proof. So it can not only sign up the user but also prove his epoch key. The second improvement that can be made is the durability. How could Voteathon smart contract be an infrastructure for every hackathon event and how the contract can be reused. It could be a challenging issue.


Future plan

This was a fun exercise for us all. There is a few things we need to continue iterating before a production release. We definitely would love this to be used in various hackathons.
Try app here:
See all projects:

Special thanks to:


· 3 min read
Alt Text

UniRep Travels to Turkey

In April, the UniRep Protocol was presented to a group of software engineers interested in privacy-related technology at the ETHPrivacy conference for a privacy hackathon in Istanbul, Turkey.

The location for the event was relevant as Turkey is one of the fastest-growing countries for the adoption of blockchain-related products. More importantly, there are concerns within Turkey about freedom of speech and other human rights where privacy can help, so it made sense to have a privacy conference there.

UniRep allows developers to build applications where a user's data is always in control of the user. A higher-level description is that the data is on a blockchain, and a user submits a zero-knowledge proof proving ownership over an epoch key that had data attested to it. Examples will follow if that does not make sense quite yet (checkout our docs if you want to dive in immediately).

One idea a hacker had at the hackathon was creating a completely anonymous GitHub. In 2023, this seems germane because of the arrest of Tornado Cash developer Alexey Pertsev, who was arrested for simply writing code (which is speech). The question, though, is how could UniRep be used to create this anonymous GitHub? Or another good question: how can we know who should be pushing to the main branch, for example, if the developer is anonymous and we are not sure of their credibility or experience?

The term "reputation" in UniRep's name might be confusing at first. Some may first think about reputation being what a certain social group may think about them. In the context of UniRep, though, reputation is data. With this in mind, we can start to imagine what data can be associated with an anonymous developer that can build their "reputation" so they can push to main.

To illustrate, let's assume you have specific criteria for selecting developers who can push to the main branch, such as requiring a certain number of stars on their projects, a minimum of 5 personal projects, and/or X amount of commits on a project on branches that are not the main branch. UniRep has the capacity to do all of that. Check out the hackathon project here, which was bootstrapped with create-unirep-app. All the mentioned GitHub data can be linked to their anonymous identity, lending credibility to their anon identities.

Simplistically, what UniRep allows developers to do is associate data with anonymous users; UniRep is acting as storage for zk-applications in this regard.

Another example from the hackathon was from the ODTU group in Istanbul, associated with Middle East Technical University. Their project was a zero-knowledge DAO where anonymous developers can create and vote on proposals anonymously with the support of an anonymous transfer of ERC-20 tokens! You can check out their source here.

UniRep is a generalized protocol and can be used to build any application you can dream of. We are currently reviewing our version 2 audit and making fixes to tidy up any loose ends and prepare for a full release of version 2 of the protocol! Exciting times ahead for the protocol and the zk-ecosystem as interest keeps rising.


· 6 min read


Time to Reimagine!

In this post, we'll review our lessons learned and why we decided to sunset The post is written collaboratively by Chiali, Vivian, Doris with the help of Kichong and a touch of ChatGPT. was our first-generation prototype, and we built it to learn how to build and leverage the protocol. It was an exciting journey and we're still going.

The journey so far is our first experimental social app in the Privacy & Scaling Explorations Team. We wanted it to be familiar, so we took inspiration from popular social media platforms like Reddit, Facebook, and Twitter. In the early design phase, we considered limiting characters in posts, but eventually decided to let users post however they want. We also wanted to protect users' privacy by giving them three epoch keys in each epoch transition, so that it's impossible to identify someone by their traits.

We wanted to balance freedom of speech with empowering users to form communities and gamifying parts of the experience. At first, was just a simple platform for posting, voting, and commenting. But as development continued, we realized it would be better to show how users earned and spent points (rep). To do this, we had to make changes to our synchronizer and backend database.

We found that users sometimes didn't know what they were waiting for, so they would take actions they weren't ready for (such as spending too many points). To prevent these mistakes, we added a queue that stored users' actions and processed them one by one, along with a progress bar to show their recent progress.

Later, we realized that some users might want to be recognized instead of staying anonymous. So, we added a username feature that worked in our circuits, backend, and frontend. This was another big change, and there were still some issues to work out, but the main functions worked well. To make the app more like a general-use social media, we added Topics to posts so users can publish posts under specific topics, and find only the posts that interest them.

Finally, we noticed that there was often confusion between the social media platform "Unirep Social" and the protocol "Unirep". To address this, we decided to rebrand the social media platform and redesign the website to better align with our target audience, based on lessons learned from our experience with

Lesson Learned #1: Invite-Only Exclusivity

When we released the pre-alpha, we used an invite-only exclusivity strategy, thinking people would be eager to try it out. However, it only worked 20% of the time, with some attention brought to the application due to Vitalik's promotion. The invite-only exclusivity mechanism only works well when invites can easily be shared. We failed to build a sustainable invite interaction, as the invitation codes were sent manually by email, causing a delay from when a user requested the code to when they received the six-character code, dampening the user's excitement.

Takeaways & next steps:

Instead of invite-only, the team revisited this strategy and decided that should be open to the public, with everyone free to join. We redesigned and built the sign-up flow using Github and Twitter OAuth to have an anti-Sybil mechanism. To avoid overwhelming users with a heavy brain dump during sign-up, we did not show the private key, which is a long text that mixes numbers and characters that is hard to remember. This iteration has made it easier for us to grow our user base, but challenges remain regarding requesting users to download and save their private key.

Lesson Learned #2: Airdrop

During the initial protocol and pre-alpha, we wanted to give users rep so they could interact in the app per epoch, so we automatically airdropped 30 rep to users. While this was an easy way to get the system started, we soon realized it caused the reputation score to be inaccurate and meaningless because if a user never created a post or interacted in the system, their rep score would still go up. This also caused unfairness to users who joined the system later, as they wouldn't be able to catch up with the rep score compared to users who joined earlier and had piled up for a long time.

Takeaways & next steps:

Our core contributor, Chance, realized this issue and proposed building a "subsidy" within We built this in the attester, not on the protocol level. The subsidy act like free allowance that system hand out to the users every epoch just for app interactions. It can not be accumulated over time, but in each epoch user get the fair subsidy of 30 points. This does opens the more open interaction, because user is spending the allowance instead of the reputation they have earned hard. Although this does boost more user interaction within the system, but the proving gets a little complex, not only we need to proof the real reputation, there is another set of logic to proof about the allowance, and the allowance that user gives to another users in order to help other earn.

Lesson Learned #3: Synchronizer

The Unirep protocol originally queried events using queryFilter functions in Ethers.js, which generated all events since deployment and had no storage configuration in the old synchronizer. This led to frequent slow queries of on-chain data and difficulty for applications like Unirep Social to inherit the Unirep synchronizer object.

Takeaways & next steps:

The team rewrote the synchronizer for Unirep protocol, which makes it easier to build the synchronizer for Unirep Social and other apps built on top of the protocol. Before, the synchronizer for Unirep Social needed to handle events for both the protocol and the application. Now, events can be separated and the Unirep protocol synchronizer can be extended to applications, which makes it more efficient and easier to manage.

Users can also customize storage configuration by specifying the database that stores the data history in each event. Synchronization happens only once and storage can be reused to avoid querying on-chain data frequently.

Today, we thank you for your support over the past year.

Thank you for trying our app, finding issues, and pushing us to have a bigger impact. We hope you'll stay tuned for our next project launch, and we look forward to building projects that help our open society.

· 3 min read

It's the year's end, and let's talk about what UniRep has accomplished in 2022.

2022 is an exciting year for us, and we had our first highlight moments in April during Devconnect, and we were finally able to show the public what we have been building in the past months. Although it was exciting, we quickly realized that our synchronizer could have been more optimal. It broke on 2nd day of the event, which caused the user state transition to fail. It was also challenging to debug such an event. That was the first lesson learned for us in 2022.

Tips from Chiali: It's essential to test out your concept as soon as possible.


Right after the Devconnect, we took a step back to visit all the core components. The action of refracting is about time. Before April 2022, it was the exploring phase, we weren't entirely sure how to approach...etc. There were many to-do lists on the table.

One of the fascinating learning was on the demo app (attester), we realized that if we automatically airdrop Rep to anyone who signs up, it would cause infiltration and un-equality, but every attester has different needs. We went a long way in debating on how this attester should be experienced and came up with the solution of "subsidy."

We head down 100% between April and October to make it happen. During this time, we also iterated on how to work as a team and started using GitHub issues to manage our workflow and set up a two weeks sprint.

Right now, the team is focused on protocol v2. We have been releasing small pieces since December, along with create-unirep-app, the idea is to enable everyone to build their own app (attester) easily. Protocol v2 comes with many optimizations, and we also break up the packages to be easily imported, etc.

We hope that we will be able to test this developer experience with you soon. Please keep an eye on our updates.


Here is the run-down list if you interested to learn more:

Unirep and Unirep Social, Applied ZK

Building a Unirep ecosystem by Chance Hudson | Devcon Bogotá

Unirep Social: A demo application of Unirep protocol

ZK HACK III - Build a ZKDAO with UniRep Protocol

How to build a simple app with UniRep protocol - Taiwan/Chinese lang.

Lastly, if you are thinking of playing create-unirep-app, although it's not fully completed:

If you are interested in contributing with us, drop us message in our discord!

· One min read

Welcome to the UniRep blog. We'll have stuff here soon.