1. 初始化多签钱包合约

初始化多签钱包合约 学习卡片

任务说明

本案例要求编写一个基础的多签钱包合约,核心功能为:在构造函数中初始化owner列表和required确认数,并对外提供查询接口。合约部署时需传入所有owner地址及所需确认数,部署后owner列表与required值不可修改(无setter函数)。

合约实现

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

contract MultiSigWallet {
    address[] public owners;
    uint256 public required;
    mapping(address => bool) public isOwner;

    event OwnerAdded(address indexed owner);
    event RequiredChanged(uint256 required);

    constructor(address[] memory _owners, uint256 _required) {
        require(_owners.length > 0, "owners required");
        require(
            _required > 0 && _required <= _owners.length,
            "invalid required count"
        );

        for (uint256 i = 0; i < _owners.length; i++) {
            address owner = _owners[i];
            require(owner != address(0), "invalid owner");
            require(!isOwner[owner], "duplicate owner");

            isOwner[owner] = true;
            owners.push(owner);
        }

        required = _required;
        emit OwnerAdded(_owners[0]);
        emit RequiredChanged(_required);
    }

    function getOwners() external view returns (address[] memory) {
        return owners;
    }

    function getRequired() external view returns (uint256) {
        return required;
    }
}

关键设计说明

构造函数接收两个参数:_owners地址数组和_required确认数。校验逻辑包括:owner列表非空、required在1到owner总数之间、owner地址非零且不重复。合约使用owners动态数组保存有序owner列表,同时用isOwner映射实现O(1)成员查询。合约部署后,owner列表和required值均不可修改,符合多签钱包初始化后配置固定的安全要求。

SVG:合约初始化状态与数据布局

多签钱包合约初始化数据流 部署者 传入参数 _owners: [0xAb...1, 0xCd...2, 0xEf...3] constructor 校验: 非空/范围/重复 写入状态变量 emit 事件 状态变量 owners[]: 3个地址 required: 2 isOwner: mapping 查询函数 getOwners() getRequired() 验证观测点 owners长度 = 3 required = 2 部署后配置不可变:无setter函数,owner列表与required值永久固定 验证方式:调用getOwners()与getRequired()检查返回值

部署与验证

部署参数示例:

_owners = ["0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
           "0xCd5801a7D398351b8bE11C439e05C5B3259aeC9C",
           "0xEf5801a7D398351b8bE11C439e05C5B3259aeC9D"]
_required = 2

部署方式:使用Remix IDE或Hardhat部署,构造函数传入上述参数。

验证步骤:

  1. 调用getOwners(),确认返回数组长度为3且元素与部署参数一致;
  2. 调用getRequired(),确认返回值为2;
  3. 调用isOwner(0xAb...),确认返回true;调用非owner地址确认返回false;
  4. 尝试调用不存在的setter函数(编译期即不存在),确认合约无修改配置入口。

判定标准:上述查询返回值与部署参数完全一致,且合约无任何可修改owner或required的函数,即视为初始化成功。