Vault
Vault2 Contract Documentation
The Vault2 contract is a secure smart contract designed for storing and managing ERC20 tokens and ERC721 NFTs. It provides functionalities such as depositing assets, setting withdrawal limits, multi-signature transaction approvals, and a recovery mechanism. The contract is upgradeable through a proxy pattern and is intended to be used in conjunction with the VaultFactory2
and SimpleProxy
contracts.
Overview
The Vault2 contract serves as a secure vault for storing and managing ERC20 tokens and ERC721 NFTs. It allows the owner to deposit assets, set customizable withdrawal limits, and require multiple confirmations for transactions exceeding daily limits. The contract also includes a recovery address and a freeze mechanism to enhance security in case of compromised access.
Key Components
Interfaces and Libraries
IERC20: Interface for interacting with ERC20 tokens.
IERC721: Interface for interacting with ERC721 NFTs.
IERC721Receiver: Interface for contracts that can handle safe transfers of ERC721 tokens.
Data Structures
Transaction
to: The recipient address of the transaction.
data: The call data for the transaction.
timestamp: The time when the transaction was queued.
executed: Indicates if the transaction has been executed.
confirmations: The number of confirmations received.
amount: The Ether amount to be transferred.
TokenLimit
fixedLimit: A fixed amount limit for withdrawals; takes precedence over percentage limits if set.
percentageLimit: A withdrawal limit based on a percentage of the total balance.
useBaseLimit:
0
: No limit.1
: Use base daily limit.2
: Limit is zero (withdrawals disallowed).
Events
TokenDeposited
Emitted when tokens are deposited into the vault.
NFTDeposited
Emitted when an NFT is deposited into the vault.
TokenWithdrawn
Emitted when tokens are withdrawn from the vault.
TransactionQueued
Emitted when a transaction is queued for later execution.
TransactionExecuted
Emitted when a queued transaction is executed.
TransactionConfirmed
Emitted when a transaction is confirmed by an authorized address.
Contract Variables
Ownership and Access Control
address public owner
: The owner of the vault.string public name
: The name of the vault.address public recoveryAddress
: The address designated for recovery operations.address[] public whitelistedAddresses
: Addresses authorized to perform certain actions.mapping(address => bool) public isWhitelisted
: Mapping to check if an address is whitelisted.
Limits and Thresholds
uint256 public dailyLimit
: The base daily withdrawal limit (in percentage).uint256 public threshold
: The number of confirmations required to execute a queued transaction.uint256 public delay
: The time delay (in seconds) before a transaction can be executed.mapping(address => TokenLimit) public tokenLimits
: Specific withdrawal limits for individual tokens.
Transactions and State
Transaction[] public queuedTransactions
: An array of queued transactions awaiting execution.uint public queuedTxs
: The total number of queued transactions.uint public freeze
: Indicator for the freeze status of the vault (e.g., 0 for active, higher values for different freeze levels).uint public version
: The version of the vault contract.mapping(uint256 => mapping(address => bool)) public confirmed
: Tracks confirmations for each transaction by address.
Withdrawal Tracking
mapping(address => uint256) public dailyWithdrawnAmount
: Tracks the amount withdrawn per token in the current day.mapping(address => uint256) public lastWithdrawTimestamp
: Records the timestamp of the last withdrawal per token.
Modifiers
onlyOwner
Restricts the function to be called only by the owner.
onlyWhitelisted
Restricts the function to be called only by whitelisted addresses.
onlyRecoveryAddress
Restricts the function to be called only by the recovery address.
Functions
Initialization
init
Initializes the vault with the necessary parameters. This function must be called only once.
Parameters:
_owner
: The address of the vault owner._name
: The name of the vault._recoveryAddress
: The address designated for recovery operations._whitelistedAddresses
: An array of addresses to be whitelisted._dailyLimit
: The base daily withdrawal limit (in percentage)._threshold
: The number of confirmations required for transaction execution._delay
: The delay before a transaction can be executed.
Requirements:
The function can only be called once (owner must be
address(0)
before initialization).
Deposit Functions
depositToken
Allows depositing ERC20 tokens or Ether into the vault.
Parameters:
token
: The address of the ERC20 token contract. Useaddress(0)
for Ether.amount
: The amount of tokens or Ether to deposit.
Logic:
For Ether (
token == address(0)
), ensures the sent value matches theamount
.For ERC20 tokens, transfers the
amount
from the sender to the vault.
Emits:
TokenDeposited
depositNFT
Allows depositing an ERC721 NFT into the vault.
Parameters:
nft
: The address of the ERC721 contract.tokenId
: The ID of the NFT token to deposit.
Logic:
Uses
safeTransferFrom
to transfer the NFT to the vault.
Emits:
NFTDeposited
Withdrawal Functions
withdrawToken
Allows the owner to withdraw tokens or Ether from the vault, subject to withdrawal limits and freeze status.
Parameters:
to
: The recipient address.token
: The address of the ERC20 token contract. Useaddress(0)
for Ether.amount
: The amount to withdraw.
Logic:
Checks if the vault has sufficient balance.
Verifies that the vault is not frozen (
freeze == 0
).Calculates the remaining withdrawal limit.
If the amount exceeds the remaining limit, queues the withdrawal.
Otherwise, updates the withdrawal tracking and executes the withdrawal.
Emits:
TokenWithdrawn
(if withdrawal is executed immediately).TransactionQueued
(if withdrawal is queued).
executeWithdrawal
Executes an immediate withdrawal of tokens or Ether.
Parameters:
to
: The recipient address.token
: The address of the ERC20 token contract. Useaddress(0)
for Ether.amount
: The amount to withdraw.
Logic:
Transfers the specified amount to the recipient.
Emits
TokenWithdrawn
.Creates and executes a placeholder transaction for record-keeping.
Transaction Management
queueTransaction
Queues a transaction to be executed later, subject to confirmations and delays.
Parameters:
to
: The address to which the transaction is directed.data
: The call data for the transaction.amount
: The amount of Ether to transfer (if any).
Logic:
Verifies that the vault is not frozen.
Adds a new transaction to the
queuedTransactions
array.Increments
queuedTxs
.Emits
TransactionQueued
.
confirmTransaction
Allows the owner or whitelisted addresses to confirm a queued transaction.
Parameters:
txIndex
: The index of the transaction in thequeuedTransactions
array.
Logic:
Checks if the caller is authorized.
Verifies the transaction exists and is not already executed.
Records the confirmation.
If the confirmation threshold is met, executes the transaction.
Emits:
TransactionConfirmed
TransactionExecuted
(if executed)
executeTransaction
Executes a queued transaction that has met the required confirmations.
Parameters:
txIndex
: The index of the transaction in thequeuedTransactions
array.
Logic:
Ensures the transaction has enough confirmations and is not executed.
Performs the call to the target address with the specified data and amount.
Marks the transaction as executed.
Emits
TransactionExecuted
.
cancelTransaction
Allows the owner or recovery address to cancel a queued transaction.
Parameters:
txIndex
: The index of the transaction in thequeuedTransactions
array.
Logic:
Checks if the caller is authorized.
Verifies the transaction exists and is not already executed.
Marks the transaction as executed and sets confirmations to
404
to indicate cancellation.
Settings and Configuration
setTokenLimit
Sets specific withdrawal limits for a token.
Parameters:
token
: The address of the ERC20 token contract.fixedLimit
: A fixed withdrawal limit amount.percentageLimit
: A withdrawal limit based on a percentage of the total balance.useBaseLimit
: Indicator for base limit usage (0
,1
, or2
).
Requirements:
Can only be called by the contract itself.
updateSettings
Allows updating multiple settings at once, such as the recovery address, whitelisted addresses, daily limits, etc.
Parameters:
newRecoveryAddress
: The new recovery address.newWhitelistedAddresses
: An array of new whitelisted addresses.newDailyLimit
: The new base daily withdrawal limit.newThreshold
: The new confirmation threshold.newDelay
: The new execution delay.tokens
: An array of token addresses for which limits are being set.fixedLimits
: Corresponding fixed limits for the tokens.percentageLimits
: Corresponding percentage limits for the tokens.useBaseLimits
: Indicators for base limit usage for the tokens.
Requirements:
Can only be called by the contract itself or the recovery address.
Recovery and Freeze Mechanism
recover
Allows the recovery address to recover tokens or Ether from the vault and set the freeze status.
Parameters:
token
: The address of the ERC20 token contract. Useaddress(0)
for Ether.to
: The recipient address.amount
: The amount to recover.data
: Additional data for the transaction.freezeL
: The new freeze level to set.
Logic:
Transfers the specified amount to the recipient.
Updates the
freeze
status.Emits
TokenWithdrawn
.
freezeLock
Allows authorized addresses to set the freeze status of the vault.
Parameters:
freezeL
: The new freeze level to set.
Requirements:
Can be called by the contract itself, the owner, the recovery address, or whitelisted addresses.
If called by someone other than the recovery address, the freeze level can only be increased.
Utility Functions
getLimitAmount
Calculates the current withdrawal limit amount for a token.
Parameters:
token
: The address of the ERC20 token contract.
Returns:
The calculated limit amount based on token-specific or base limits.
getLimit
Determines the allowable immediate withdrawal amount based on limits and previous withdrawals.
Parameters:
to
: The recipient address.token
: The address of the ERC20 token contract.amount
: The desired withdrawal amount.
Returns:
The amount that can be withdrawn immediately without queuing.
onERC721Received
Handles the receipt of an ERC721 NFT.
Returns:
The selector indicating successful receipt.
receive
Fallback function to accept Ether deposits.
Logic:
Allows the contract to receive Ether without data.
Usage Examples
Depositing Ether
Deposits
amount
of Ether into the vault.
Depositing ERC20 Tokens
Before calling, ensure the vault has approval to transfer the tokens.
Depositing an NFT
Transfers the specified NFT into the vault.
Withdrawing Tokens Within Limits
If
amount
is within the immediate withdrawal limit, the transfer occurs immediately.
Queuing a Withdrawal Exceeding Limits
If
largeAmount
exceeds the immediate withdrawal limit, the withdrawal is queued.
Confirming a Queued Transaction
Called by the owner or whitelisted addresses to confirm a queued transaction.
Canceling a Queued Transaction
Cancels a transaction in the queue.
Setting Token Limits via the Contract Itself
First, queue a transaction to call setTokenLimit
on the vault:
Then, confirm and execute the transaction as per the confirmation process.
Important Notes
Ownership and Access Control: The owner has special privileges but cannot bypass certain security mechanisms like the freeze status or confirmation thresholds.
Withdrawal Limits: The vault enforces withdrawal limits to enhance security. Exceeding the limit requires transaction queuing and confirmations.
Freeze Mechanism: The freeze status can be set to prevent unauthorized transactions. Only the recovery address can decrease the freeze level.
Recovery Address: The recovery address has elevated privileges, including the ability to recover assets and modify critical settings.
Security Considerations: The contract is designed with security in mind, incorporating multi-signature approvals, delayed executions, and restricted access to sensitive functions.
Upgradeable Contract: The vault uses a proxy pattern for upgradeability, allowing the implementation to be updated via the
SimpleProxy
contract.
SimpleProxy Contract Documentation
The SimpleProxy contract is a minimal proxy that delegates all calls to an implementation contract using the delegatecall
mechanism. This pattern allows for upgradeable contracts by separating the logic (implementation) from the storage (proxy).
Key Components
Variables
address public immutable implementation
: The address of the implementation contract to which calls are delegated.
Constructor
Parameters:
_implementation
: The address of the implementation contract.
Requirements:
_implementation
must not be the zero address.
Functions
_delegate
Internal function to delegate calls to the implementation contract.
Parameters:
impl
: The address of the implementation contract.
Logic:
Uses inline assembly to perform a
delegatecall
, forwarding all call data and returning any received data.
fallback
Fallback function that delegates all calls to the implementation contract.
receive
Receive function to handle plain Ether transfers.
VaultFactory2 Contract Documentation
The VaultFactory2 contract is responsible for deploying new instances of the Vault2
contract using the SimpleProxy
. It allows users to create their own vaults with customizable settings and keeps track of deployed vaults.
Key Components
Variables
address public owner
: The owner of the factory contract.uint256 public totalVaults
: The total number of vaults created.address public vaultImplementation
: The address of the current vault implementation contract.mapping(string => address) public vaultNames
: Maps vault names to their corresponding vault addresses.mapping(address => address[]) public ownerToVaults
: Maps owner addresses to their vaults.
Events
VaultCreated
Emitted when a new vault is created.
Modifiers
onlyOwner
Restricts the function to be called only by the owner.
Functions
Constructor
Parameters:
_vaultImplementation
: The address of the vault implementation contract.
Logic:
Sets the factory owner (in this code, a hardcoded address is used).
Sets the vault implementation address.
createVault
Allows users to create a new vault with specified settings.
Parameters:
_name
: The name of the new vault._recoveryAddress
: The recovery address for the vault._whitelistedAddresses
: Addresses to be whitelisted in the vault._dailyLimit
: The base daily withdrawal limit (in percentage)._threshold
: The number of confirmations required for transaction execution._delay
: The delay before a transaction can be executed.
Logic:
Ensures the vault name is unique.
Generates a unique salt based on the sender and their vault count.
Deploys a new
SimpleProxy
pointing to the current vault implementation.Initializes the vault via the proxy.
Updates mappings and counters.
Emits
VaultCreated
.
updateVaultImplementation
Allows the factory owner to update the vault implementation contract.
Parameters:
_vaultImplementation
: The new vault implementation address.
getVaultsByOwner
Retrieves all vaults associated with a specific owner.
Parameters:
_owner
: The address of the vault owner.
Returns:
An array of vault addresses owned by the specified owner.
Usage Flow
Deploy the Factory: The
VaultFactory2
contract is deployed with the address of theVault2
implementation contract.Create a Vault:
A user calls
createVault
on the factory with their desired settings.The factory deploys a new
SimpleProxy
contract.The new vault is initialized via the proxy, pointing to the
Vault2
implementation.
Interact with the Vault:
Users can deposit tokens and NFTs into their vault.
The owner can withdraw assets, subject to the vault's withdrawal limits and security mechanisms.
Transactions that exceed limits are queued and require confirmations.
Manage Transactions:
Queued transactions can be confirmed by the owner and whitelisted addresses.
Transactions are executed once they meet the required confirmations and delay.
Update Settings:
The owner or recovery address can update vault settings by queuing and executing transactions that call the vault's update functions.
Recovery and Security:
In case of compromised access, the recovery address can recover assets and set the freeze status to protect the vault.
Important Notes
Factory Owner: The factory owner can update the vault implementation, affecting future vaults. Existing vaults are not affected unless they choose to upgrade.
Proxy Pattern: The use of the
SimpleProxy
allows for upgradeable contracts. Users should be aware of the implementation address their vault proxy is pointing to.Security Considerations:
Users should ensure the vault implementation is secure and audited.
Proper key management is essential to maintain control over vault assets.
The recovery address should be secured, as it has significant control over the vault.
Vault Names: Vault names must be unique across the factory to prevent naming collisions.
Conclusion
The Vault2
, SimpleProxy
, and VaultFactory2
contracts provide a comprehensive solution for secure asset management on the Ethereum blockchain. They offer customizable security features, including withdrawal limits, multi-signature transaction confirmations, and recovery mechanisms.
Users and developers should thoroughly understand the contract functionalities and ensure secure practices when deploying and interacting with these contracts. Regular audits and adherence to security best practices are recommended to safeguard assets managed by the vault.
Last updated