It is true that the hybrid approach cannot be ignored in the design of web3 applications.
While on-chain smart contracts are great for verifying things as a single source of truth, it is not so good for data manipulation.
That’s where hybrids come into play.
We typically do some computation off chain on top of a database synced with on-chain storage, and then reflect the result to smart contracts as soon as we’re sure it’s valid.
And yet, this verification is not that easy and it is the weakest point in the whole application, as malicious actors can always try to pretend to be a legitimate user.
Of course there are several methods for this, as you know, the most famous being Merkle proofs and signature verification.
Today, I’m going to go in depth about signature verification in hybrid applications.
I will focus more on the overall architecture of how we use signature verification.
If you are not familiar with Signature and EIP712, better you read this first,
Here the basic diagram about the flow is given below.
As you can see there are 3 steps to go through in the context of a frontend application, I think it would make more sense for you to observe it from the perspective of the frontend as it is actually the entry point of the application to the users Is.
Step1, Once the user triggers the actions on the frontend, he/she will need to sign a message.
And then it will make an API request to the backend to be signed by the private wallet.
Example request body would be like this
When it comes to the request body, it will vary depending on what the user is doing and the application you are building.
For example, this would include the collection address, token ID, price if the user is trying to list their NFTs on the market.
Step 2, Once the frontend gets the signature from the backend side, now it’s time to do the transaction, just for your note here, the user is actually doing the transaction through the UI.
The very basic voucher structure would be something like this
In the smart contract, there must be some assumptions about the signature, such as if the signature is signed by the private wallet, the user transaction matches the sender, is non-correct, and finally the voucher has not expired by checking the expiration. .
You are free to add more validations for your specific needs.
FYI, doing an update on the signature mapping is obvious and once the signature is valid and you are about to move your update on the states.
mapping(address => uint256) public nonces; mapping(bytes => bool) public signatures; nonces[_voucher.user]++; signatures[_voucher.signature] = true;
step 3. There must be a result from the transaction, right? whether it succeeds or undoes.
Only if the transaction is successful and there are state variables updated on the chain, are we now ready to update the database to sync with the chain.
You will call the API for this with the request body
UserSignature: String, // Signature by User
txSignature: String, //signed by private wallet
For this, you need to verify if the transaction is successful and the states have been updated, this signature mapping can be a good way to check whether txSingature is valid or not.
And you might want to update something on your DB and then return the result to the user.
Finally the user will get the result of his action on the UI.
Thanks for your attention, I tried to make it as concise as possible but at the same time, I tried to understand you more.)))
I’m going to walk through the Tablelands implementation for dynamic metadata which is a must in P2E games.
so stay tuned.