-
Notifications
You must be signed in to change notification settings - Fork 38
Change template #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change template #34
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Here some comments, please take it as a reflection on the template we want to propose. Today I think the code implementation is a bit too complex to understand and visualize how users can use FHEVM directly in their dapp. It would be nice to use on the frontend some hooks for reading and writing on the contract by using viem library for that. Same with chain management, I have the feeling for each action we need to fetch and specify it. I would be in favor of having viem managing that directly and delegate this part. In all the cases, we truly need to simplify it. New users might have some knowledge of web3 but today I do not see/understand how we are interacting with the FHE through the demo in the code. I would also be in favor to organize the code in a way that it is simple for a user to create a new component folder to directly work on their use cases by having the counter as an example, or for experiment developers to delete the counter example and write directly their own implementation. But in all the cases it has to be simple, multiple component if needed to illustrate and understand the different process. For the demo, I would maybe increase the refresh, to avoid the light on/off effect. And add a delay when we display the decryption of the counter, which in my case is a bit too fast for me to read the value. Do not hesitate if some of my points are not clear or if I misunderstand something. |
// Wagmi-specific values | ||
chainId, | ||
accounts, | ||
isConnected, | ||
ethersSigner, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to pass those value here? Could we not dissociate the contract process (fhecounter) and the wallet connection?
I think it would be nice if we could simplify this code example to simplify the on-boarding of new users. To let them pass less time trying to understand the code, but more on the interaction process.
I am just thinking of people who could have some experience in React/wagmi but nothing in FHE, it has to be easy and simple.
export const useFHEDecrypt = (params: { | ||
instance: FhevmInstance | undefined; | ||
ethersSigner: ethers.JsonRpcSigner | undefined; | ||
fhevmDecryptionSignatureStorage: GenericStringStorage; | ||
chainId: number | undefined; | ||
requests: readonly FHEDecryptRequest[] | undefined; | ||
}) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we not parse the result value here? I might know where I get the handle from (user balance, result of a poll) then decide to have the parsing done here directly?
const encryptWith = useCallback( | ||
async (buildFn: (builder: RelayerEncryptedInput) => void): Promise<EncryptResult | undefined> => { | ||
if (!instance || !ethersSigner || !contractAddress) return undefined; | ||
|
||
const userAddress = await ethersSigner.getAddress(); | ||
const input = instance.createEncryptedInput(contractAddress, userAddress) as RelayerEncryptedInput; | ||
buildFn(input); | ||
const enc = await input.encrypt(); | ||
return enc; | ||
}, | ||
[instance, ethersSigner, contractAddress], | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the code example I can see
const firstInput = functionAbi.inputs[0]!;
const method = getEncryptionMethod(firstInput.internalType);
const enc = await encryptWith(builder => {
(builder as any)[method](valueAbs);
});
if (!enc) return setMessage("Encryption failed");
I apologize but I do not understand what it is doing? How can I encrypt multiple elements? Can I stack them? I am afraid than trying to abstract too much here, we are completely losing what we are trying to do here.
In some of our implementation we have try to be exhaustive, maybe not the best approach
Defined types
export enum SUPPORTED_TYPES {
'ebool',
'euint4',
'euint8',
'euint16',
'euint32',
'euint64',
'euint128',
'euint160',
'euint256',
'address',
'bytes64',
'bytes128',
'bytes256'
}
const SUPPORTED_TYPES_MAP: Record<SUPPORTED_TYPES, number> = {
[SUPPORTED_TYPES.ebool]: 0,
[SUPPORTED_TYPES.euint4]: 1,
[SUPPORTED_TYPES.euint8]: 2,
[SUPPORTED_TYPES.euint16]: 3,
[SUPPORTED_TYPES.euint32]: 4,
[SUPPORTED_TYPES.euint64]: 5,
[SUPPORTED_TYPES.euint128]: 6,
[SUPPORTED_TYPES.euint160]: 7, // @dev It is the one for eaddresses.
[SUPPORTED_TYPES.euint256]: 8,
[SUPPORTED_TYPES.address]: 7, // @dev It is the one for eaddresses.
[SUPPORTED_TYPES.bytes64]: 9,
[SUPPORTED_TYPES.bytes128]: 10,
[SUPPORTED_TYPES.bytes256]: 11
}
const EXPECTED_TYPE_TO_RESULT_MAP: Record<SUPPORTED_TYPES, 'boolean' | 'bigint' | 'string'> = {
[SUPPORTED_TYPES.ebool]: 'boolean',
[SUPPORTED_TYPES.euint4]: 'bigint',
[SUPPORTED_TYPES.euint8]: 'bigint',
[SUPPORTED_TYPES.euint16]: 'bigint',
[SUPPORTED_TYPES.euint32]: 'bigint',
[SUPPORTED_TYPES.euint64]: 'bigint',
[SUPPORTED_TYPES.euint128]: 'bigint',
[SUPPORTED_TYPES.euint160]: 'string', // @dev It is the one for eaddresses.
[SUPPORTED_TYPES.euint256]: 'bigint',
[SUPPORTED_TYPES.address]: 'string', // @dev It is the one for eaddresses.
[SUPPORTED_TYPES.bytes64]: 'bigint',
[SUPPORTED_TYPES.bytes128]: 'bigint',
[SUPPORTED_TYPES.bytes256]: 'bigint'
}
But this allow us to simply defined the handle logic
const decryptionHandle = {
value: hexHandleToBigInt(bid.eAmount),
type: SUPPORTED_TYPES.euint64,
contractAddress: NEXT_PUBLIC_AUCTION_CONTRACT
}
const { decryptedValues, isDecrypting, decrypt } = useDecrypt([decryptionHandle])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently it looks at the abi defined internal method to check what kind of type it should be, so it's automated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand that you are reading the ABI to determined the exact type needed for your function. But here how do you handle multiple encrypted parameters? Do you need to stacked them as follow?
const enc = await encryptWith(builder => {
(builder as any)["add64"](10)["add64"](20);
});
if (!enc) return setMessage("Encryption failed");
IMO, I think we should simplify this process. Maybe a topic to set in an issue.
export const useFHEDecrypt = (params: { | ||
instance: FhevmInstance | undefined; | ||
ethersSigner: ethers.JsonRpcSigner | undefined; | ||
fhevmDecryptionSignatureStorage: GenericStringStorage; | ||
chainId: number | undefined; | ||
requests: readonly FHEDecryptRequest[] | undefined; | ||
}) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see some parameter that we need to redefined each time as
instance: FhevmInstance | undefined;
ethersSigner: ethers.JsonRpcSigner | undefined;
fhevmDecryptionSignatureStorage: GenericStringStorage;
chainId: number | undefined;
Would it be not possible to abtract them? Cannot we retrieve the instance
using the useFhevm()
hook if we already initialize before?
This is a naive question and I maybe missed some stuff, but was wondering if a Singleton pattern could not help us here, instead of distributing in our code the instance.
Same with the chainId, is it not something we could retrieve?
And for the storage, we would definitively need a way to store the handles. Could we not defined on by default using a configuration system? As some defined in scaffold.config.ts
? Again, not a statement but more a design reflection here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I have the rights to approve this PR.
Nevertheless, I do not know how you want to organized on this project, but please keep track of the discussion. I truly believe we need to simplify the nextjs project as currently, I think, it is really hard to appropriate this template to build your own dapp.
And I do not want to leave it as it is as I think it can be helpful to have a good starter. Let's discuss about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got this message after pnpm install
Run "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.
May be we could add an instruction in the README to help the user handle this situation, What do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved this :)
Screen.Recording.2025-09-23.at.17.47.47.mov