Skip to content

Commit b4a11e2

Browse files
authored
feat(gateway-contracts): introduce EmptyProxyUpgradeable for deployment behind empty proxies
* feat(gateway-contracts): introduce EmptyProxyUpgradeable for deployment behind empty proxies * refactor(gateway-contracts): rename UUPSUpgradeableEmptyProxy abstract contract
1 parent 5a2e329 commit b4a11e2

22 files changed

+3142
-53
lines changed

gateway-contracts/contracts/CiphertextCommits.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol";
44
import { kmsManagementAddress } from "../addresses/KmsManagementAddress.sol";
55
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
66
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
7-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
87
import "./interfaces/ICiphertextCommits.sol";
98
import "./interfaces/IGatewayConfig.sol";
109
import "./interfaces/IKmsManagement.sol";
10+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
1111
import "./shared/GatewayConfigChecks.sol";
1212
import "./shared/Pausable.sol";
1313
import "./libraries/HandleOps.sol";
@@ -19,7 +19,7 @@ import "./libraries/HandleOps.sol";
1919
contract CiphertextCommits is
2020
ICiphertextCommits,
2121
Ownable2StepUpgradeable,
22-
UUPSUpgradeable,
22+
UUPSUpgradeableEmptyProxy,
2323
GatewayConfigChecks,
2424
Pausable
2525
{
@@ -77,7 +77,7 @@ contract CiphertextCommits is
7777
* @dev This function needs to be public in order to be called by the UUPS proxy.
7878
*/
7979
/// @custom:oz-upgrades-validate-as-initializer
80-
function initializeFromEmptyProxy() public virtual reinitializer(2) {
80+
function initializeFromEmptyProxy() public virtual onlyFromEmptyProxy reinitializer(2) {
8181
__Ownable_init(owner());
8282
__Pausable_init();
8383
}

gateway-contracts/contracts/Decryption.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol";
77
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
88
import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
99
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
10-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
1110
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
1211
import "./interfaces/IGatewayConfig.sol";
1312
import "./interfaces/IMultichainAcl.sol";
1413
import "./interfaces/ICiphertextCommits.sol";
14+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
1515
import "./shared/GatewayConfigChecks.sol";
1616
import "./shared/FheType.sol";
1717
import "./shared/Pausable.sol";
@@ -23,7 +23,7 @@ contract Decryption is
2323
IDecryption,
2424
EIP712Upgradeable,
2525
Ownable2StepUpgradeable,
26-
UUPSUpgradeable,
26+
UUPSUpgradeableEmptyProxy,
2727
GatewayConfigChecks,
2828
Pausable
2929
{
@@ -200,7 +200,7 @@ contract Decryption is
200200
/// @dev Contract name and version for EIP712 signature validation are defined here
201201
/// @dev This function needs to be public in order to be called by the UUPS proxy.
202202
/// @custom:oz-upgrades-validate-as-initializer
203-
function initializeFromEmptyProxy() public virtual reinitializer(2) {
203+
function initializeFromEmptyProxy() public virtual onlyFromEmptyProxy reinitializer(2) {
204204
__EIP712_init(CONTRACT_NAME, "1");
205205
__Ownable_init(owner());
206206
__Pausable_init();

gateway-contracts/contracts/GatewayConfig.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// SPDX-License-Identifier: BSD-3-Clause-Clear
22
pragma solidity ^0.8.24;
33

4-
import "./interfaces/IGatewayConfig.sol";
54
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
6-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
75
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
6+
import "./interfaces/IGatewayConfig.sol";
7+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
88
import "./shared/Pausable.sol";
99

1010
/**
@@ -13,7 +13,7 @@ import "./shared/Pausable.sol";
1313
* @dev Add/remove methods will be added in the future for KMS nodes, coprocessors and host chains.
1414
* @dev See https://github.com/zama-ai/fhevm-gateway/issues/98 for more details.
1515
*/
16-
contract GatewayConfig is IGatewayConfig, Ownable2StepUpgradeable, UUPSUpgradeable, Pausable {
16+
contract GatewayConfig is IGatewayConfig, Ownable2StepUpgradeable, UUPSUpgradeableEmptyProxy, Pausable {
1717
/// @notice The maximum chain ID.
1818
uint256 internal constant MAX_CHAIN_ID = type(uint64).max;
1919

@@ -93,7 +93,7 @@ contract GatewayConfig is IGatewayConfig, Ownable2StepUpgradeable, UUPSUpgradeab
9393
uint256 initialUserDecryptionThreshold,
9494
KmsNode[] memory initialKmsNodes,
9595
Coprocessor[] memory initialCoprocessors
96-
) public virtual reinitializer(2) {
96+
) public virtual onlyFromEmptyProxy reinitializer(2) {
9797
__Ownable_init(owner());
9898
__Pausable_init();
9999

gateway-contracts/contracts/InputVerification.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol";
55
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
66
import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
77
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
8-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
98
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
109
import "./interfaces/IInputVerification.sol";
1110
import "./interfaces/IGatewayConfig.sol";
11+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
1212
import "./shared/GatewayConfigChecks.sol";
1313
import "./shared/Pausable.sol";
1414

@@ -20,7 +20,7 @@ contract InputVerification is
2020
IInputVerification,
2121
EIP712Upgradeable,
2222
Ownable2StepUpgradeable,
23-
UUPSUpgradeable,
23+
UUPSUpgradeableEmptyProxy,
2424
GatewayConfigChecks,
2525
Pausable
2626
{
@@ -104,7 +104,7 @@ contract InputVerification is
104104
/// @dev Contract name and version for EIP712 signature validation are defined here
105105
/// @dev This function needs to be public in order to be called by the UUPS proxy.
106106
/// @custom:oz-upgrades-validate-as-initializer
107-
function initializeFromEmptyProxy() public virtual reinitializer(2) {
107+
function initializeFromEmptyProxy() public virtual onlyFromEmptyProxy reinitializer(2) {
108108
__EIP712_init(CONTRACT_NAME, "1");
109109
__Ownable_init(owner());
110110
__Pausable_init();

gateway-contracts/contracts/KmsManagement.sol

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@ import "./interfaces/IKmsManagement.sol";
55
import "./interfaces/IGatewayConfig.sol";
66
import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol";
77
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
8-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
98
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
9+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
1010
import "./shared/GatewayConfigChecks.sol";
1111
import "./shared/Pausable.sol";
1212

1313
/// @title KMS Management contract
1414
/// @dev TODO: This contract is neither used nor up-to-date. It will be reworked in the future.
1515
/// @dev See https://github.com/zama-ai/fhevm-gateway/issues/108
1616
/// @dev See {IKmsManagement}.
17-
contract KmsManagement is IKmsManagement, Ownable2StepUpgradeable, UUPSUpgradeable, GatewayConfigChecks, Pausable {
17+
contract KmsManagement is
18+
IKmsManagement,
19+
Ownable2StepUpgradeable,
20+
UUPSUpgradeableEmptyProxy,
21+
GatewayConfigChecks,
22+
Pausable
23+
{
1824
/// @notice The address of the GatewayConfig contract for protocol state calls.
1925
IGatewayConfig private constant GATEWAY_CONFIG = IGatewayConfig(gatewayConfigAddress);
2026

@@ -125,7 +131,7 @@ contract KmsManagement is IKmsManagement, Ownable2StepUpgradeable, UUPSUpgradeab
125131
function initializeFromEmptyProxy(
126132
string memory fheParamsName,
127133
bytes32 fheParamsDigest
128-
) public virtual reinitializer(2) {
134+
) public virtual onlyFromEmptyProxy reinitializer(2) {
129135
__Ownable_init(owner());
130136
__Pausable_init();
131137

gateway-contracts/contracts/MultichainAcl.sol

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@ pragma solidity ^0.8.24;
44
import { gatewayConfigAddress } from "../addresses/GatewayConfigAddress.sol";
55
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
66
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
7-
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
87
import "./interfaces/IMultichainAcl.sol";
98
import "./interfaces/ICiphertextCommits.sol";
109
import "./interfaces/IGatewayConfig.sol";
10+
import "./shared/UUPSUpgradeableEmptyProxy.sol";
1111
import "./shared/GatewayConfigChecks.sol";
1212
import "./shared/Pausable.sol";
1313

1414
/// @title MultichainAcl smart contract
1515
/// @dev See {IMultichainAcl}
16-
contract MultichainAcl is IMultichainAcl, Ownable2StepUpgradeable, UUPSUpgradeable, GatewayConfigChecks, Pausable {
16+
contract MultichainAcl is
17+
IMultichainAcl,
18+
Ownable2StepUpgradeable,
19+
UUPSUpgradeableEmptyProxy,
20+
GatewayConfigChecks,
21+
Pausable
22+
{
1723
/// @notice The address of the GatewayConfig contract for protocol state calls.
1824
IGatewayConfig private constant GATEWAY_CONFIG = IGatewayConfig(gatewayConfigAddress);
1925

@@ -78,7 +84,7 @@ contract MultichainAcl is IMultichainAcl, Ownable2StepUpgradeable, UUPSUpgradeab
7884
/// @notice Initializes the contract.
7985
/// @dev This function needs to be public in order to be called by the UUPS proxy.
8086
/// @custom:oz-upgrades-validate-as-initializer
81-
function initializeFromEmptyProxy() public virtual reinitializer(2) {
87+
function initializeFromEmptyProxy() public virtual onlyFromEmptyProxy reinitializer(2) {
8288
__Ownable_init(owner());
8389
__Pausable_init();
8490
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: BSD-3-Clause-Clear
2+
pragma solidity ^0.8.24;
3+
4+
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
5+
6+
/**
7+
* @title UUPSUpgradeableEmptyProxy
8+
* @dev Abstract base contract for upgradeable contracts that are intended to be deployed behind
9+
* empty proxies. This contract provides a modifier that ensures functions can only be called
10+
* during the first initialization phase (i.e., when initialized version is 1), enforcing
11+
* correct deployment from an empty proxy using the UUPSUpgradeable pattern.
12+
*
13+
* Inheriting contracts should use the `onlyFromEmptyProxy` modifier to protect initialization logic
14+
* that must not run on upgrades or reinitializations.
15+
*/
16+
abstract contract UUPSUpgradeableEmptyProxy is UUPSUpgradeable {
17+
error NotInitializingFromEmptyProxy();
18+
19+
modifier onlyFromEmptyProxy() {
20+
if (_getInitializedVersion() != 1) {
21+
revert NotInitializingFromEmptyProxy();
22+
}
23+
_;
24+
}
25+
}

gateway-contracts/rust_bindings/src/ciphertextcommits.rs

Lines changed: 109 additions & 5 deletions
Large diffs are not rendered by default.

gateway-contracts/rust_bindings/src/decryption.rs

Lines changed: 109 additions & 5 deletions
Large diffs are not rendered by default.

gateway-contracts/rust_bindings/src/gatewayconfig.rs

Lines changed: 109 additions & 5 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)