Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions gateway-contracts/contracts/Decryption.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ contract Decryption is
*/
uint16 internal constant MAX_USER_DECRYPT_DURATION_DAYS = 365;

/**
* @notice The maximum allowed tolerance (in seconds) for the start timestamp of a user decryption
* request. This accounts for potential lag between the RPC node's block.timestamp during
* gas estimation and the actual wall-clock time.
*/
uint256 internal constant TIMESTAMP_TOLERANCE = 120;

/**
* @notice The maximum number of contracts that can request for user decryption at once.
*/
Expand Down Expand Up @@ -200,7 +207,7 @@ contract Decryption is
*/
string private constant CONTRACT_NAME = "Decryption";
uint256 private constant MAJOR_VERSION = 0;
uint256 private constant MINOR_VERSION = 4;
uint256 private constant MINOR_VERSION = 5;
uint256 private constant PATCH_VERSION = 0;

/**
Expand All @@ -209,7 +216,7 @@ contract Decryption is
* This constant does not represent the number of time a specific contract have been upgraded,
* as a contract deployed from version VX will have a REINITIALIZER_VERSION > 2.
*/
uint64 private constant REINITIALIZER_VERSION = 5;
uint64 private constant REINITIALIZER_VERSION = 6;

/**
* @notice The contract's variable storage struct (@dev see ERC-7201)
Expand Down Expand Up @@ -289,11 +296,11 @@ contract Decryption is
}

/**
* @notice Re-initializes the contract from V3.
* @notice Re-initializes the contract from V4.
*/
/// @custom:oz-upgrades-unsafe-allow missing-initializer-call
/// @custom:oz-upgrades-validate-as-initializer
function reinitializeV4() public virtual reinitializer(REINITIALIZER_VERSION) {}
function reinitializeV5() public virtual reinitializer(REINITIALIZER_VERSION) {}

/**
* @notice See {IDecryption-publicDecryptionRequest}.
Expand Down Expand Up @@ -1112,10 +1119,11 @@ contract Decryption is
revert MaxDurationDaysExceeded(MAX_USER_DECRYPT_DURATION_DAYS, requestValidity.durationDays);
}

// Check the start timestamp is not set in the future. This is to prevent a user
// Check the start timestamp is not set too far in the future. This is to prevent a user
// from bypassing the durationDays limit of 365 days by setting a start timestamp
// far in the future.
if (requestValidity.startTimestamp > block.timestamp) {
// far in the future. A small tolerance is allowed to account for RPC node block.timestamp
// lag during gas estimation.
if (requestValidity.startTimestamp > block.timestamp + TIMESTAMP_TOLERANCE) {
revert StartTimestampInFuture(block.timestamp, requestValidity.startTimestamp);
}

Expand Down
116 changes: 58 additions & 58 deletions gateway-contracts/rust_bindings/src/decryption.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions gateway-contracts/selectors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Decryption
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | publicDecryptionResponse(uint256,bytes,bytes,bytes) | 0x6f8913bc |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | reinitializeV4() | 0x123abb28 |
| Function | reinitializeV5() | 0x6292d95e |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | unpause() | 0x3f4ba83a |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
Expand Down Expand Up @@ -998,7 +998,7 @@ DecryptionV2Example
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | publicDecryptionResponse(uint256,bytes,bytes,bytes) | 0x6f8913bc |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | reinitializeV4() | 0x123abb28 |
| Function | reinitializeV5() | 0x6292d95e |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
| Function | unpause() | 0x3f4ba83a |
|----------+-------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------|
Expand Down
45 changes: 45 additions & 0 deletions gateway-contracts/test/Decryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
const MAX_USER_DECRYPT_DURATION_DAYS = 365;
const MAX_USER_DECRYPT_CONTRACT_ADDRESSES = 10;
const MAX_DECRYPTION_REQUEST_BITS = 2048;
const TIMESTAMP_TOLERANCE = 120;

// Get the current date in seconds. This is needed because Solidity works with seconds, not milliseconds
// See https://docs.soliditylang.org/en/develop/units-and-global-variables.html#time-units
Expand Down Expand Up @@ -1025,6 +1026,28 @@ describe("Decryption", function () {
).to.be.revertedWithCustomError(decryption, "StartTimestampInFuture");
});

it("Should not revert with StartTimestampInFuture when start timestamp is within tolerance", async function () {
// A start timestamp within the tolerance should pass the timestamp check
const toleratedRequestValidity: IDecryption.RequestValidityStruct = {
startTimestamp: startTimestamp + TIMESTAMP_TOLERANCE - 1,
durationDays,
};

await expect(
decryption
.connect(tokenFundedTxSender)
.userDecryptionRequest(
ctHandleContractPairs,
toleratedRequestValidity,
contractsInfo,
user.address,
publicKey,
userSignature,
extraDataV0,
),
).to.not.be.revertedWithCustomError(decryption, "StartTimestampInFuture");
});

it("Should revert because the user decryption request has expired", async function () {
// Create a expired validity request.
// Note that we currently allow a past start timestamp. Here, we set it 10 days in the past,
Expand Down Expand Up @@ -2002,6 +2025,28 @@ describe("Decryption", function () {
).to.be.revertedWithCustomError(decryption, "StartTimestampInFuture");
});

it("Should not revert with StartTimestampInFuture when start timestamp is within tolerance", async function () {
// A start timestamp within the tolerance should pass the timestamp check
const toleratedRequestValidity: IDecryption.RequestValidityStruct = {
startTimestamp: startTimestamp + TIMESTAMP_TOLERANCE - 1,
durationDays,
};

await expect(
decryption
.connect(tokenFundedTxSender)
.delegatedUserDecryptionRequest(
ctHandleContractPairs,
toleratedRequestValidity,
delegationAccounts,
contractsInfo,
publicKey,
delegateSignature,
extraDataV0,
),
).to.not.be.revertedWithCustomError(decryption, "StartTimestampInFuture");
});

it("Should revert because the delegated user decryption request has expired", async function () {
// Create a expired request validity.
// Note that we currently allow a past start timestamp. Here, we set it 10 days in the past,
Expand Down
Loading