mirror of
https://github.com/zama-ai/fhevm-solidity.git
synced 2026-05-09 03:00:27 -04:00
* feat: use latest core contracts, updated lib API, renamed to fhevm and fhe chore: add dummy addresses for CI test: add tests for makePubliclyDecryptable method * chore: update package-lock.json for linux * chore: update package-lock.json * fix: solidity comments (#746) * chore: update oracle version * chore: update fhevm core-contracts version * feat: update fhevm sdk and mocked userDecrypt * chore: fix coverage
169 lines
4.9 KiB
TypeScript
169 lines
4.9 KiB
TypeScript
import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers';
|
|
import { toBufferBE } from 'bigint-buffer';
|
|
import { ContractMethodArgs, Typed } from 'ethers';
|
|
import { Signer } from 'ethers';
|
|
import { ethers, network } from 'hardhat';
|
|
|
|
import type { Counter } from '../types';
|
|
import { TypedContractMethod } from '../types/common';
|
|
import { getSigners } from './signers';
|
|
|
|
const hre = require('hardhat');
|
|
|
|
export async function checkIsHardhatSigner(signer: HardhatEthersSigner) {
|
|
const signers = await hre.ethers.getSigners();
|
|
if (signers.findIndex((s) => s.address === signer.address) === -1) {
|
|
throw new Error(
|
|
`The provided address (${signer.address}) is not the address of a valid hardhat signer.
|
|
Please use addresses listed via the 'npx hardhat get-accounts --network hardhat' command.`,
|
|
);
|
|
}
|
|
}
|
|
|
|
export const waitForBlock = (blockNumber: bigint | number) => {
|
|
if (network.name === 'hardhat') {
|
|
return new Promise((resolve, reject) => {
|
|
const intervalId = setInterval(async () => {
|
|
try {
|
|
const currentBlock = await ethers.provider.getBlockNumber();
|
|
if (BigInt(currentBlock) >= blockNumber) {
|
|
clearInterval(intervalId);
|
|
resolve(currentBlock);
|
|
}
|
|
} catch (error) {
|
|
clearInterval(intervalId);
|
|
reject(error);
|
|
}
|
|
}, 50); // Check every 50 milliseconds
|
|
});
|
|
} else {
|
|
return new Promise((resolve, reject) => {
|
|
const waitBlock = async (currentBlock: number) => {
|
|
if (blockNumber <= BigInt(currentBlock)) {
|
|
await ethers.provider.off('block', waitBlock);
|
|
resolve(blockNumber);
|
|
}
|
|
};
|
|
ethers.provider.on('block', waitBlock).catch((err) => {
|
|
reject(err);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
export const waitNBlocks = async (Nblocks: number) => {
|
|
const currentBlock = await ethers.provider.getBlockNumber();
|
|
if (network.name === 'hardhat') {
|
|
await produceDummyTransactions(Nblocks);
|
|
}
|
|
await waitForBlock(currentBlock + Nblocks);
|
|
};
|
|
|
|
export const waitForBalance = async (address: string): Promise<void> => {
|
|
return new Promise((resolve, reject) => {
|
|
const checkBalance = async () => {
|
|
const balance = await ethers.provider.getBalance(address);
|
|
if (balance > 0) {
|
|
await ethers.provider.off('block', checkBalance);
|
|
resolve();
|
|
}
|
|
};
|
|
ethers.provider.on('block', checkBalance).catch((err) => {
|
|
reject(err);
|
|
});
|
|
});
|
|
};
|
|
|
|
export const createTransaction = async <A extends [...{ [I in keyof A]-?: A[I] | Typed }]>(
|
|
method: TypedContractMethod<A>,
|
|
...params: A
|
|
) => {
|
|
const gasLimit = await method.estimateGas(...params);
|
|
const updatedParams: ContractMethodArgs<A> = [
|
|
...params,
|
|
{ gasLimit: Math.min(Math.round(+gasLimit.toString() * 1.2), 10000000) },
|
|
];
|
|
return method(...updatedParams);
|
|
};
|
|
|
|
export const produceDummyTransactions = async (blockCount: number) => {
|
|
const contract = await deployCounterContract();
|
|
let counter = blockCount;
|
|
while (counter > 0) {
|
|
counter--;
|
|
const tx = await contract.increment();
|
|
const _ = await tx.wait();
|
|
}
|
|
};
|
|
|
|
async function deployCounterContract(): Promise<Counter> {
|
|
const signers = await getSigners();
|
|
|
|
const contractFactory = await ethers.getContractFactory('Counter');
|
|
const contract = await contractFactory.connect(signers.dave).deploy();
|
|
await contract.waitForDeployment();
|
|
|
|
return contract;
|
|
}
|
|
|
|
export const mineNBlocks = async (n: number) => {
|
|
for (let index = 0; index < n; index++) {
|
|
await ethers.provider.send('evm_mine');
|
|
}
|
|
};
|
|
|
|
export const bigIntToBytes64 = (value: bigint) => {
|
|
return new Uint8Array(toBufferBE(value, 64));
|
|
};
|
|
|
|
export const bigIntToBytes128 = (value: bigint) => {
|
|
return new Uint8Array(toBufferBE(value, 128));
|
|
};
|
|
|
|
export const bigIntToBytes256 = (value: bigint) => {
|
|
return new Uint8Array(toBufferBE(value, 256));
|
|
};
|
|
|
|
export const userDecryptSingleHandle = async (
|
|
handle: string,
|
|
contractAddress: string,
|
|
instance: any,
|
|
signer: Signer,
|
|
privateKey: string,
|
|
publicKey: string,
|
|
): Promise<bigint> => {
|
|
const ctHandleContractPairs = [
|
|
{
|
|
ctHandle: handle,
|
|
contractAddress: contractAddress,
|
|
},
|
|
];
|
|
const startTimeStamp = Math.floor(Date.now() / 1000).toString();
|
|
const durationDays = '10'; // String for consistency
|
|
const contractAddresses = [contractAddress];
|
|
|
|
// Use the new createEIP712 function
|
|
const eip712 = instance.createEIP712(publicKey, contractAddresses, startTimeStamp, durationDays);
|
|
|
|
// Update the signing to match the new primaryType
|
|
const signature = await signer.signTypedData(
|
|
eip712.domain,
|
|
{ UserDecryptRequestVerification: eip712.types.UserDecryptRequestVerification },
|
|
eip712.message,
|
|
);
|
|
|
|
const decryptedValue = (
|
|
await instance.userDecrypt(
|
|
ctHandleContractPairs,
|
|
privateKey,
|
|
publicKey,
|
|
signature.replace('0x', ''),
|
|
contractAddresses,
|
|
signer.address,
|
|
startTimeStamp,
|
|
durationDays,
|
|
)
|
|
)[0];
|
|
return decryptedValue;
|
|
};
|