Skip to content

Commit

Permalink
Merge pull request #166 from zama-ai/fixTest
Browse files Browse the repository at this point in the history
Fix test
  • Loading branch information
jatZama authored Dec 2, 2024
2 parents d7b9822 + 72cc11d commit ca7e849
Show file tree
Hide file tree
Showing 13 changed files with 298 additions and 16 deletions.
1 change: 1 addition & 0 deletions contracts/addresses/.env.gateway
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GATEWAY_CONTRACT_PREDEPLOY_ADDRESS=0x33347831500F1e73f0ccCBb95c9f86B94d7b1123
5 changes: 5 additions & 0 deletions contracts/addresses/GatewayContractAddress.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear

pragma solidity ^0.8.24;

address constant GATEWAY_CONTRACT_PREDEPLOY_ADDRESS = 0x33347831500F1e73f0ccCBb95c9f86B94d7b1123;
2 changes: 1 addition & 1 deletion contracts/examples/BlindAuction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity ^0.8.24;
import "../lib/TFHE.sol";
import "./EncryptedERC20.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "../gateway/GatewayCaller.sol";
import "../gatewayLib/GatewayCaller.sol";

/// @notice Main contract for the blind auction
contract BlindAuction is Ownable2Step, GatewayCaller {
Expand Down
2 changes: 1 addition & 1 deletion contracts/examples/TestAsyncDecrypt.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity ^0.8.24;

import "../lib/TFHE.sol";
import "../gateway/GatewayCaller.sol";
import "../gatewayLib/GatewayCaller.sol";

/// @notice Contract for testing asynchronous decryption using the Gateway
contract TestAsyncDecrypt is GatewayCaller {
Expand Down
107 changes: 107 additions & 0 deletions contracts/gatewayLib/GatewayCaller.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear

pragma solidity ^0.8.24;

import "../lib/TFHE.sol";
import "./lib/Gateway.sol";

abstract contract GatewayCaller {
modifier onlyGateway() {
require(msg.sender == Gateway.gatewayContractAddress());
_;
}
mapping(uint256 => ebool[]) private paramsEBool;
mapping(uint256 => euint4[]) private paramsEUint4;
mapping(uint256 => euint8[]) private paramsEUint8;
mapping(uint256 => euint16[]) private paramsEUint16;
mapping(uint256 => euint32[]) private paramsEUint32;
mapping(uint256 => euint64[]) private paramsEUint64;
mapping(uint256 => eaddress[]) private paramsEAddress;
mapping(uint256 => address[]) private paramsAddress;
mapping(uint256 => uint256[]) private paramsUint256;
mapping(uint256 => uint256[]) private requestedHandles;

constructor() {}

function addParamsEBool(uint256 requestID, ebool _ebool) internal {
paramsEBool[requestID].push(_ebool);
}

function addParamsEUint4(uint256 requestID, euint4 _euint4) internal {
paramsEUint4[requestID].push(_euint4);
}

function addParamsEUint8(uint256 requestID, euint8 _euint8) internal {
paramsEUint8[requestID].push(_euint8);
}

function addParamsEUint16(uint256 requestID, euint16 _euint16) internal {
paramsEUint16[requestID].push(_euint16);
}

function addParamsEUint32(uint256 requestID, euint32 _euint32) internal {
paramsEUint32[requestID].push(_euint32);
}

function addParamsEUint64(uint256 requestID, euint64 _euint64) internal {
paramsEUint64[requestID].push(_euint64);
}

function addParamsEAddress(uint256 requestID, eaddress _eaddress) internal {
paramsEAddress[requestID].push(_eaddress);
}

function addParamsAddress(uint256 requestID, address _address) internal {
paramsAddress[requestID].push(_address);
}

function addParamsUint256(uint256 requestID, uint256 _uint) internal {
paramsUint256[requestID].push(_uint);
}

function saveRequestedHandles(uint256 requestID, uint256[] memory handlesList) internal {
require(requestedHandles[requestID].length == 0, "requested handles already saved");
requestedHandles[requestID] = handlesList;
}

function loadRequestedHandles(uint256 requestID) internal view returns (uint256[] memory) {
require(requestedHandles[requestID].length != 0, "requested handles were not saved for this requestID");
return requestedHandles[requestID];
}

function getParamsEBool(uint256 requestID) internal view returns (ebool[] memory) {
return paramsEBool[requestID];
}

function getParamsEUint4(uint256 requestID) internal view returns (euint4[] memory) {
return paramsEUint4[requestID];
}

function getParamsEUint8(uint256 requestID) internal view returns (euint8[] memory) {
return paramsEUint8[requestID];
}

function getParamsEUint16(uint256 requestID) internal view returns (euint16[] memory) {
return paramsEUint16[requestID];
}

function getParamsEUint32(uint256 requestID) internal view returns (euint32[] memory) {
return paramsEUint32[requestID];
}

function getParamsEUint64(uint256 requestID) internal view returns (euint64[] memory) {
return paramsEUint64[requestID];
}

function getParamsEAddress(uint256 requestID) internal view returns (eaddress[] memory) {
return paramsEAddress[requestID];
}

function getParamsAddress(uint256 requestID) internal view returns (address[] memory) {
return paramsAddress[requestID];
}

function getParamsUint256(uint256 requestID) internal view returns (uint256[] memory) {
return paramsUint256[requestID];
}
}
166 changes: 166 additions & 0 deletions contracts/gatewayLib/lib/Gateway.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear

pragma solidity ^0.8.24;

import "../../addresses/GatewayContractAddress.sol";
import "../../lib/Impl.sol";
import "../../addresses/ACLAddress.sol";

interface IKMSVerifier {
function verifyDecryptionEIP712KMSSignatures(
address aclAddress,
uint256[] memory handlesList,
bytes memory decryptedResult,
bytes[] memory signatures
) external returns (bool);
}

interface IGatewayContract {
function requestDecryption(
uint256[] calldata ctsHandles,
bytes4 callbackSelector,
uint256 msgValue,
uint256 maxTimestamp,
bool passSignaturesToCaller
) external returns (uint256);
}

library Gateway {
struct GatewayConfigStruct {
address GatewayContractAddress;
}

// keccak256(abi.encode(uint256(keccak256("fhevm.storage.GatewayConfig")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant GatewayLocation = 0x93ab6e17f2c461cce6ea5d4ec117e51dda77a64affc2b2c05f8cd440def0e700;

function defaultGatewayAddress() internal pure returns (address) {
return GATEWAY_CONTRACT_PREDEPLOY_ADDRESS;
}

function getGetwayConfig() internal pure returns (GatewayConfigStruct storage $) {
assembly {
$.slot := GatewayLocation
}
}

function setGateway(address gatewayAddress) internal {
GatewayConfigStruct storage $ = getGetwayConfig();
$.GatewayContractAddress = gatewayAddress;
}

function gatewayContractAddress() internal view returns (address) {
GatewayConfigStruct storage $ = getGetwayConfig();
return $.GatewayContractAddress;
}

function toUint256(ebool newCT) internal pure returns (uint256 ct) {
ct = ebool.unwrap(newCT);
}

function toUint256(euint4 newCT) internal pure returns (uint256 ct) {
ct = euint4.unwrap(newCT);
}

function toUint256(euint8 newCT) internal pure returns (uint256 ct) {
ct = euint8.unwrap(newCT);
}

function toUint256(euint16 newCT) internal pure returns (uint256 ct) {
ct = euint16.unwrap(newCT);
}

function toUint256(euint32 newCT) internal pure returns (uint256 ct) {
ct = euint32.unwrap(newCT);
}

function toUint256(euint64 newCT) internal pure returns (uint256 ct) {
ct = euint64.unwrap(newCT);
}

function toUint256(euint128 newCT) internal pure returns (uint256 ct) {
ct = euint128.unwrap(newCT);
}

function toUint256(eaddress newCT) internal pure returns (uint256 ct) {
ct = eaddress.unwrap(newCT);
}

function toUint256(euint256 newCT) internal pure returns (uint256 ct) {
ct = euint256.unwrap(newCT);
}

function toUint256(ebytes64 newCT) internal pure returns (uint256 ct) {
ct = ebytes64.unwrap(newCT);
}

function toUint256(ebytes128 newCT) internal pure returns (uint256 ct) {
ct = ebytes128.unwrap(newCT);
}

function toUint256(ebytes256 newCT) internal pure returns (uint256 ct) {
ct = ebytes256.unwrap(newCT);
}

function requestDecryption(
uint256[] memory ctsHandles,
bytes4 callbackSelector,
uint256 msgValue,
uint256 maxTimestamp,
bool passSignaturesToCaller
) internal returns (uint256 requestID) {
FHEVMConfig.FHEVMConfigStruct storage $ = Impl.getFHEVMConfig();
IACL($.ACLAddress).allowForDecryption(ctsHandles);
GatewayConfigStruct storage $$ = getGetwayConfig();
requestID = IGatewayContract($$.GatewayContractAddress).requestDecryption(
ctsHandles,
callbackSelector,
msgValue,
maxTimestamp,
passSignaturesToCaller
);
}

/// @dev this function is supposed to be called inside the callback function if the dev wants the dApp contract to verify the signatures
/// @dev this is useful to give dev the choice not to rely on trusting the GatewayContract.
/// @notice this could be used only when signatures are made available to the callback, i.e when `passSignaturesToCaller` is set to true during request
function verifySignatures(uint256[] memory handlesList, bytes[] memory signatures) internal returns (bool) {
uint256 start = 4 + 32; // start position after skipping the selector (4 bytes) and the first argument (index, 32 bytes)
uint256 length = getSignedDataLength(handlesList);
bytes memory decryptedResult = new bytes(length);
assembly {
calldatacopy(add(decryptedResult, 0x20), start, length) // Copy the relevant part of calldata to decryptedResult memory
}
FHEVMConfig.FHEVMConfigStruct storage $ = Impl.getFHEVMConfig();
return
IKMSVerifier($.KMSVerifierAddress).verifyDecryptionEIP712KMSSignatures(
aclAdd,
handlesList,
decryptedResult,
signatures
);
}

function getSignedDataLength(uint256[] memory handlesList) private pure returns (uint256) {
uint256 handlesListlen = handlesList.length;
uint256 signedDataLength;
for (uint256 i = 0; i < handlesListlen; i++) {
uint8 typeCt = uint8(handlesList[i] >> 8);
if (typeCt < 9) {
signedDataLength += 32;
} else if (typeCt == 9) {
//ebytes64
signedDataLength += 128;
} else if (typeCt == 10) {
//ebytes128
signedDataLength += 192;
} else if (typeCt == 11) {
//ebytes256
signedDataLength += 320;
} else {
revert("Unsupported handle type");
}
}
signedDataLength += 32; // for the signatures offset
return signedDataLength;
}
}
4 changes: 2 additions & 2 deletions contracts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fhevm-core-contracts",
"version": "0.6.0-4",
"version": "0.6.0-5",
"description": "fhEVM contracts",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion contracts/tasks/etherscanVerify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ task('task:verifyFHEPayment').setAction(async function (taskArguments, { upgrade
});

task('task:verifyGatewayContract').setAction(async function (taskArguments, { upgrades, run }) {
const parsedEnvGateway = dotenv.parse(fs.readFileSync('gateway/.env.gateway'));
const parsedEnvGateway = dotenv.parse(fs.readFileSync('addresses/.env.gateway'));
const proxyGateway = parsedEnvGateway.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS;
const implementationGatewayAddress = await upgrades.erc1967.getImplementationAddress(proxyGateway);
await run('verify:verify', {
Expand Down
2 changes: 1 addition & 1 deletion contracts/tasks/taskDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ task('task:deployGateway')
});
await Gateway.waitForDeployment();
const GatewayContractAddress = await Gateway.getAddress();
const envConfig = dotenv.parse(fs.readFileSync('gateway/.env.gateway'));
const envConfig = dotenv.parse(fs.readFileSync('addresses/.env.gateway'));
if (GatewayContractAddress !== envConfig.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS) {
throw new Error(
`The nonce of the deployer account is not null. Please use another deployer private key or relaunch a clean instance of the fhEVM`,
Expand Down
17 changes: 10 additions & 7 deletions contracts/tasks/taskGatewayRelayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ task('task:computeGatewayAddress')
from: deployerAddress,
nonce: 1, // deployer is supposed to have nonce 0 when deploying GatewayContract (0 nonce for implementation, +1 for UUPS)
});
const envFilePath = path.join(__dirname, '../gateway/.env.gateway');
const envFilePath = path.join(__dirname, '../addresses/.env.gateway');
const content = `GATEWAY_CONTRACT_PREDEPLOY_ADDRESS=${gatewayContractAddressPrecomputed}`;
try {
fs.writeFileSync(envFilePath, content, { flag: 'w' });
console.log('gatewayContractAddress written to gateway/.env.gateway successfully!');
console.log('gatewayContractAddress written to addresses/.env.gateway successfully!');
} catch (err) {
console.error('Failed to write to gateway/.env.gateway:', err);
console.error('Failed to write to addresses/.env.gateway:', err);
}

const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear
Expand All @@ -40,10 +40,13 @@ address constant GATEWAY_CONTRACT_PREDEPLOY_ADDRESS = ${gatewayContractAddressPr
`;

try {
fs.writeFileSync('./gateway/lib/GatewayContractAddress.sol', solidityTemplate, { encoding: 'utf8', flag: 'w' });
console.log('gateway/lib/GatewayContractAddress.sol file has been generated successfully.');
fs.writeFileSync('./addresses/GatewayContractAddress.sol', solidityTemplate, {
encoding: 'utf8',
flag: 'w',
});
console.log('addresses/GatewayContractAddress.sol file has been generated successfully.');
} catch (error) {
console.error('Failed to write gateway/lib/GatewayContractAddress.sol', error);
console.error('Failed to write addresses/GatewayContractAddress.sol', error);
}
});

Expand Down Expand Up @@ -115,7 +118,7 @@ task('task:launchFhevm')
}
await hre.run('task:deployGateway', { privateKey: privKeyDeployer, ownerAddress: deployerAddress });

const parsedEnv = dotenv.parse(fs.readFileSync('gateway/.env.gateway'));
const parsedEnv = dotenv.parse(fs.readFileSync('addresses/.env.gateway'));
const gatewayContractAddress = parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS;

await hre.run('task:addRelayer', {
Expand Down
2 changes: 1 addition & 1 deletion contracts/tasks/upgradeProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ task('task:upgradeGatewayContract')
types.boolean,
)
.setAction(async function (taskArguments: TaskArguments, { ethers, upgrades, run }) {
const parsedEnv = dotenv.parse(fs.readFileSync('gateway/.env.gateway'));
const parsedEnv = dotenv.parse(fs.readFileSync('addresses/.env.gateway'));
const proxyAddress = parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS;
await upgradeCurrentToNew(
taskArguments.privateKey,
Expand Down
Loading

0 comments on commit ca7e849

Please sign in to comment.