Finance

This directory includes primitives for on-chain confidential financial systems:

For convenience, this directory also includes:

Contracts

VestingWalletConfidential

import "@openzeppelin/confidential-contracts/finance/VestingWalletConfidential.sol";

A vesting wallet is an ownable contract that can receive ConfidentialFungibleTokens, and release these assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule.

Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning. Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly) be immediately releasable.

By setting the duration to 0, one can configure this contract to behave like an asset timelock that holds tokens for a beneficiary until a specified time.

Since the wallet is Ownable, and ownership can be transferred, it is possible to sell unvested tokens.
When using this contract with any token whose balance is adjusted automatically (i.e. a rebase token), make sure to account the supply/balance adjustment in the vesting schedule to ensure the vested amount is as intended.
Functions
  • start()

  • duration()

  • end()

  • released(token)

  • releasable(token)

  • release(token)

  • vestedAmount(token, timestamp)

  • __VestingWalletConfidential_init(beneficiary, startTimestamp, durationSeconds)

  • _vestingSchedule(totalAllocation, timestamp)

ReentrancyGuardTransient
  • _reentrancyGuardEntered()

OwnableUpgradeable
  • __Ownable_init(initialOwner)

  • __Ownable_init_unchained(initialOwner)

  • owner()

  • _checkOwner()

  • renounceOwnership()

  • transferOwnership(newOwner)

  • _transferOwnership(newOwner)

ContextUpgradeable
  • __Context_init()

  • __Context_init_unchained()

  • _msgSender()

  • _msgData()

  • _contextSuffixLength()

Initializable
  • _checkInitializing()

  • _disableInitializers()

  • _getInitializedVersion()

  • _isInitializing()

  • _initializableStorageSlot()

Events
  • VestingWalletConfidentialTokenReleased(token, amount)

OwnableUpgradeable
  • OwnershipTransferred(previousOwner, newOwner)

Initializable
  • Initialized(version)

Errors
ReentrancyGuardTransient
  • ReentrancyGuardReentrantCall()

OwnableUpgradeable
  • OwnableUnauthorizedAccount(account)

  • OwnableInvalidOwner(owner)

Initializable
  • InvalidInitialization()

  • NotInitializing()

start() → uint64 public

Timestamp at which the vesting starts.

duration() → uint64 public

Duration of the vesting in seconds.

end() → uint64 public

Timestamp at which the vesting ends.

released(address token) → euint64 public

Amount of token already released

releasable(address token) → euint64 public

Getter for the amount of releasable token tokens. token should be the address of an IConfidentialFungibleToken contract.

release(address token) public

Release the tokens that have already vested.

vestedAmount(address token, uint64 timestamp) → euint128 public

Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.

__VestingWalletConfidential_init(address beneficiary, uint48 startTimestamp, uint48 durationSeconds) internal

Initializes the vesting wallet for a given beneficiary with a start time of startTimestamp and an end time of startTimestamp + durationSeconds.

_vestingSchedule(euint128 totalAllocation, uint64 timestamp) → euint128 internal

This returns the amount vested, as a function of time, for an asset given its total historical allocation.

VestingWalletConfidentialTokenReleased(address indexed token, euint64 amount) event

VestingWalletCliffConfidential

import "@openzeppelin/confidential-contracts/finance/VestingWalletCliffConfidential.sol";

An extension of VestingWalletConfidential that adds a cliff to the vesting schedule. The cliff is cliffSeconds long and starts at the vesting start timestamp (see VestingWalletConfidential).

Functions
  • cliff()

  • __VestingWalletCliffConfidential_init(cliffSeconds)

  • _vestingSchedule(totalAllocation, timestamp)

VestingWalletConfidential
  • start()

  • duration()

  • end()

  • released(token)

  • releasable(token)

  • release(token)

  • vestedAmount(token, timestamp)

  • __VestingWalletConfidential_init(beneficiary, startTimestamp, durationSeconds)

ReentrancyGuardTransient
  • _reentrancyGuardEntered()

OwnableUpgradeable
  • __Ownable_init(initialOwner)

  • __Ownable_init_unchained(initialOwner)

  • owner()

  • _checkOwner()

  • renounceOwnership()

  • transferOwnership(newOwner)

  • _transferOwnership(newOwner)

ContextUpgradeable
  • __Context_init()

  • __Context_init_unchained()

  • _msgSender()

  • _msgData()

  • _contextSuffixLength()

Initializable
  • _checkInitializing()

  • _disableInitializers()

  • _getInitializedVersion()

  • _isInitializing()

  • _initializableStorageSlot()

Events
VestingWalletConfidential
  • VestingWalletConfidentialTokenReleased(token, amount)

OwnableUpgradeable
  • OwnershipTransferred(previousOwner, newOwner)

Initializable
  • Initialized(version)

Errors
  • VestingWalletCliffConfidentialInvalidCliffDuration(cliffSeconds, durationSeconds)

ReentrancyGuardTransient
  • ReentrancyGuardReentrantCall()

OwnableUpgradeable
  • OwnableUnauthorizedAccount(account)

  • OwnableInvalidOwner(owner)

Initializable
  • InvalidInitialization()

  • NotInitializing()

cliff() → uint64 public

The timestamp at which the cliff ends.

__VestingWalletCliffConfidential_init(uint48 cliffSeconds) internal

Set the duration of the cliff, in seconds. The cliff starts at the vesting start timestamp (see VestingWalletConfidential.start) and ends cliffSeconds later.

_vestingSchedule(euint128 totalAllocation, uint64 timestamp) → euint128 internal

This function returns the amount vested, as a function of time, for an asset given its total historical allocation. Returns 0 if the cliff timestamp is not met.

The cliff not only makes the schedule return 0, but it also ignores every possible side effect from calling the inherited implementation (i.e. super._vestingSchedule). Carefully consider this caveat if the overridden implementation of this function has any (e.g. writing to memory or reverting).

VestingWalletCliffConfidentialInvalidCliffDuration(uint64 cliffSeconds, uint64 durationSeconds) error

The specified cliff duration is larger than the vesting duration.

VestingWalletCliffExecutorConfidentialFactory

import "@openzeppelin/confidential-contracts/finance/VestingWalletCliffExecutorConfidentialFactory.sol";

This factory enables creating VestingWalletCliffExecutorConfidential in batch.

Confidential vesting wallets created inherit both VestingWalletCliffConfidential for vesting cliffs and ERC7821WithExecutor to allow for arbitrary calls to be executed from the vesting wallet.

Functions
  • batchFundVestingWalletConfidential(confidentialFungibleToken, vestingPlans, executor, inputProof)

  • createVestingWalletConfidential(beneficiary, startTimestamp, durationSeconds, cliffSeconds, executor)

  • predictVestingWalletConfidential(beneficiary, startTimestamp, durationSeconds, cliffSeconds, executor)

  • _getCreate2VestingWalletConfidentialSalt(beneficiary, startTimestamp, durationSeconds, cliffSeconds, executor)

Events
  • VestingWalletConfidentialFunded(vestingWalletConfidential, beneficiary, confidentialFungibleToken, encryptedAmount, startTimestamp, durationSeconds, cliffSeconds, executor)

  • VestingWalletConfidentialCreated(vestingWalletConfidential, beneficiary, startTimestamp, durationSeconds, cliffSeconds, executor)

batchFundVestingWalletConfidential(address confidentialFungibleToken, struct VestingWalletCliffExecutorConfidentialFactory.VestingPlan[] vestingPlans, address executor, bytes inputProof) public

Batches the funding of multiple confidential vesting wallets.

Funds are sent to deterministic wallet addresses. Wallets can be created either before or after this operation.

Emits a VestingWalletConfidentialFunded event for each funded vesting plan.

createVestingWalletConfidential(address beneficiary, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address executor) → address public

Creates a confidential vesting wallet.

predictVestingWalletConfidential(address beneficiary, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address executor) → address public

Predicts deterministic address for a confidential vesting wallet.

_getCreate2VestingWalletConfidentialSalt(address beneficiary, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address executor) → bytes32 internal

Gets create2 salt for a confidential vesting wallet.

VestingWalletConfidentialFunded(address indexed vestingWalletConfidential, address indexed beneficiary, address indexed confidentialFungibleToken, euint64 encryptedAmount, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address executor) event

VestingWalletConfidentialCreated(address indexed vestingWalletConfidential, address indexed beneficiary, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address indexed executor) event

VestingWalletCliffExecutorConfidential

import "@openzeppelin/confidential-contracts/finance/VestingWalletCliffExecutorConfidentialFactory.sol";
Functions
  • constructor()

  • initialize(beneficiary, startTimestamp, durationSeconds, cliffSeconds, executor)

ERC7821WithExecutor
  • executor()

  • __ERC7821WithExecutor_init(executor_)

  • _erc7821AuthorizedExecutor(caller, mode, executionData)

ERC7821
  • execute(mode, executionData)

  • supportsExecutionMode(mode)

VestingWalletCliffConfidential
  • cliff()

  • __VestingWalletCliffConfidential_init(cliffSeconds)

  • _vestingSchedule(totalAllocation, timestamp)

VestingWalletConfidential
  • start()

  • duration()

  • end()

  • released(token)

  • releasable(token)

  • release(token)

  • vestedAmount(token, timestamp)

  • __VestingWalletConfidential_init(beneficiary, startTimestamp, durationSeconds)

ReentrancyGuardTransient
  • _reentrancyGuardEntered()

OwnableUpgradeable
  • __Ownable_init(initialOwner)

  • __Ownable_init_unchained(initialOwner)

  • owner()

  • _checkOwner()

  • renounceOwnership()

  • transferOwnership(newOwner)

  • _transferOwnership(newOwner)

ContextUpgradeable
  • __Context_init()

  • __Context_init_unchained()

  • _msgSender()

  • _msgData()

  • _contextSuffixLength()

Initializable
  • _checkInitializing()

  • _disableInitializers()

  • _getInitializedVersion()

  • _isInitializing()

  • _initializableStorageSlot()

Events
VestingWalletConfidential
  • VestingWalletConfidentialTokenReleased(token, amount)

OwnableUpgradeable
  • OwnershipTransferred(previousOwner, newOwner)

Initializable
  • Initialized(version)

Errors
ERC7821
  • UnsupportedExecutionMode()

VestingWalletCliffConfidential
  • VestingWalletCliffConfidentialInvalidCliffDuration(cliffSeconds, durationSeconds)

ReentrancyGuardTransient
  • ReentrancyGuardReentrantCall()

OwnableUpgradeable
  • OwnableUnauthorizedAccount(account)

  • OwnableInvalidOwner(owner)

Initializable
  • InvalidInitialization()

  • NotInitializing()

constructor() public

initialize(address beneficiary, uint48 startTimestamp, uint48 durationSeconds, uint48 cliffSeconds, address executor) public

ERC7821WithExecutor

import "@openzeppelin/confidential-contracts/finance/ERC7821WithExecutor.sol";

Extension of ERC7821 that adds an executor address that is able to execute arbitrary calls via ERC7821.execute.

Functions
  • executor()

  • __ERC7821WithExecutor_init(executor_)

  • _erc7821AuthorizedExecutor(caller, mode, executionData)

ERC7821
  • execute(mode, executionData)

  • supportsExecutionMode(mode)

Initializable
  • _checkInitializing()

  • _disableInitializers()

  • _getInitializedVersion()

  • _isInitializing()

  • _initializableStorageSlot()

Events
Initializable
  • Initialized(version)

Errors
ERC7821
  • UnsupportedExecutionMode()

Initializable
  • InvalidInitialization()

  • NotInitializing()

executor() → address public

Trusted address that is able to execute arbitrary calls from the vesting wallet via ERC7821.execute.

__ERC7821WithExecutor_init(address executor_) internal

_erc7821AuthorizedExecutor(address caller, bytes32 mode, bytes executionData) → bool internal

Access control mechanism for the {execute} function. By default, only the contract itself is allowed to execute.

Override this function to implement custom access control, for example to allow the ERC-4337 entrypoint to execute.

function _erc7821AuthorizedExecutor(
  address caller,
  bytes32 mode,
  bytes calldata executionData
) internal view virtual override returns (bool) {
  return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
}