본문 바로가기
블록체인교육/솔리디티

다중 서명(multi-sig) 기업 지갑 샘플 코드

by Danny_Kim 2026. 10. 9.

다중서명 기업 지갑 샘플 코드입니다.

교육용이니 참고하시기 바랍니다.

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

// 4-Eyes Principle 기반 다중 서명(Multi-Sig) 기업 지갑
contract CorporateMultiSig {
    
    // 기업 자금 관리 권한을 가진 임원(Owner)들의 지갑 주소 목록
    address[] public owners;
    mapping(address => bool) public isOwner;
    
    // 자금 이체를 위해 필요한 최소 서명(결재) 개수 (예: 3명 중 2명)
    uint256 public requiredApprovals;

    // 결재를 위해 상신된 자금 이체(트랜잭션) 구조체
    struct Transaction {
        address to;           // 돈을 받을 대상
        uint256 amount;       // 보낼 금액(ETH)
        bool executed;        // 실제 집행(송금) 완료 여부
        uint256 approvalCount;// 현재까지 받은 결재(서명) 개수
    }

    // 상신된 전체 트랜잭션 목록 (인덱스 번호가 결재 문서 번호가 됨)
    Transaction[] public transactions;

    // 특정 결재 문서(트랜잭션 인덱스)에 특정 임원이 서명했는지 기록하는 장부
    mapping(uint256 => mapping(address => bool)) public approved;

    // 이벤트 로그 (감사 기록용)
    event Deposit(address indexed sender, uint256 amount, uint256 balance);
    event SubmitTransaction(address indexed owner, uint256 indexed txIndex, address indexed to, uint256 amount);
    event ApproveTransaction(address indexed owner, uint256 indexed txIndex);
    event ExecuteTransaction(address indexed owner, uint256 indexed txIndex);

    // 오직 임원(Owner)만 실행할 수 있도록 통제하는 접근 제어자
    modifier onlyOwner() {
        require(isOwner[msg.sender], "Not an authorized owner");
        _;
    }

    // 배포 시 임원 주소 목록과 최소 결재 필요 인원수를 설정합니다.
    constructor(address[] memory _owners, uint256 _requiredApprovals) {
        require(_owners.length > 0, "Owners required");
        require(_requiredApprovals > 0 && _requiredApprovals <= _owners.length, "Invalid required number of approvals");

        for (uint256 i = 0; i < _owners.length; i++) {
            address owner = _owners[i];
            require(owner != address(0), "Invalid owner address");
            require(!isOwner[owner], "Owner not unique"); // 중복 등록 방지
            
            isOwner[owner] = true;
            owners.push(owner);
        }
        requiredApprovals = _requiredApprovals;
    }

    // [자금 수신] 법인 지갑으로 이더리움을 입금받는 함수 (누구나 입금 가능)
    receive() external payable {
        emit Deposit(msg.sender, msg.value, address(this).balance);
    }

    // 1. [Maker] 자금 이체 기안 올리기 (트랜잭션 상신)
    function submitTransaction(address _to, uint256 _amount) public onlyOwner {
        uint256 txIndex = transactions.length;
        
        transactions.push(Transaction({
            to: _to,
            amount: _amount,
            executed: false,
            approvalCount: 0
        }));

        emit SubmitTransaction(msg.sender, txIndex, _to, _amount);
    }

    // 2. [Checker] 상신된 결재 문서(트랜잭션)에 서명하기 (승인)
    function approveTransaction(uint256 _txIndex) public onlyOwner {
        require(_txIndex < transactions.length, "Transaction does not exist");
        require(!transactions[_txIndex].executed, "Transaction already executed");
        require(!approved[_txIndex][msg.sender], "Transaction already approved by you");

        approved[_txIndex][msg.sender] = true;
        transactions[_txIndex].approvalCount += 1;

        emit ApproveTransaction(msg.sender, _txIndex);
    }

    // 3. [Execution] 서명 요건이 충족되면 자금 이체 실행 (집행)
    function executeTransaction(uint256 _txIndex) public onlyOwner {
        require(_txIndex < transactions.length, "Transaction does not exist");
        require(!transactions[_txIndex].executed, "Transaction already executed");
        
        Transaction storage txn = transactions[_txIndex];
        
        // 최소 서명(결재) 개수를 채웠는지 확인
        require(txn.approvalCount >= requiredApprovals, "Not enough approvals");

        txn.executed = true; // 중복 집행을 막기 위해 상태 먼저 변경 (Reentrancy 방지)

        // 실제 이더리움 송금
        (bool success, ) = txn.to.call{value: txn.amount}("");
        require(success, "Transaction execution failed");

        emit ExecuteTransaction(msg.sender, _txIndex);
    }

    // 법인 지갑 잔액 확인
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

🔑🔑🔑 추천 링크 🔑🔑🔑

  1. 쉽게 이해하고 따라하는 블록체인 마스터 과정
  2. 알트코인 투자 정석 및 2026 암호화폐 시장 주목할 섹터

댓글