You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用含结构体数组参数的智能合约工厂触发Revert错误求助

问题:通过CampaignFactory创建Campaign实例时触发Revert错误

调用CampaignFactory的createCampaign方法创建新Campaign实例时,Remix返回以下错误:

[vm]from: 0x5B3...eddC4to: CampaignFactory.createCampaign((uint256,uint256,string)[]) 0xd91...39138value: 0 weidata: 0x6d9...00000logs: 0hash: 0xa4d...ad5fd
transact to CampaignFactory.createCampaign errored: VM error: revert.

原代码

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

struct Reward {
    uint256 contribution;
    uint256 maxNumber;
    string ImageLink;
}

contract CampaignFactory {

    Campaign[] public deployedCampaigns;

    function createCampaign(Reward[] memory _rewards)
        public
    {
        Campaign newCampaign = new Campaign(msg.sender);

        for (uint256 i = 0; i < _rewards.length; i++) {
            newCampaign.createReward(
                _rewards[i].contribution,
                _rewards[i].maxNumber,
                _rewards[i].ImageLink
            );
        }
        deployedCampaigns.push(newCampaign);
    }

    function getDeployedCampaigns()
        public
        view
        returns (Campaign[] memory)
    {
        return deployedCampaigns;
    }
}

contract Campaign {
    Reward[] public rewards;
    address public manager;

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }
    constructor(address creator) {
        manager = creator;
    }

    function createReward(
        uint256 _contribution,
        uint256 _maxNumber,
        string memory _imageLink
    ) public restricted {
        Reward memory newReward = Reward({
            contribution: _contribution,
            maxNumber: _maxNumber,
            ImageLink: _imageLink
        });

        rewards.push(newReward);
    }
}

问题原因

错误根源在于权限校验:

  • 创建Campaign实例时,manager被设置为调用createCampaign的用户地址(msg.sender)。
  • 随后CampaignFactory调用Campaign的createReward方法时,此时的msg.sender是Factory合约地址,而非Campaign的manager地址。
  • createReward方法的restricted修饰器要求调用者必须是manager,因此触发revert。

修复方案

最直接高效的方式是在Campaign的构造函数中直接初始化rewards数组,避免后续跨合约调用的权限问题:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

struct Reward {
    uint256 contribution;
    uint256 maxNumber;
    string ImageLink;
}

contract CampaignFactory {

    Campaign[] public deployedCampaigns;

    function createCampaign(Reward[] memory _rewards)
        public
    {
        // 直接将_rewards传入Campaign构造函数初始化
        Campaign newCampaign = new Campaign(msg.sender, _rewards);
        deployedCampaigns.push(newCampaign);
    }

    function getDeployedCampaigns()
        public
        view
        returns (Campaign[] memory)
    {
        return deployedCampaigns;
    }
}

contract Campaign {
    Reward[] public rewards;
    address public manager;

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }

    // 修改构造函数,接收rewards数组并初始化
    constructor(address creator, Reward[] memory _rewards) {
        manager = creator;
        // 批量添加奖励
        for (uint256 i = 0; i < _rewards.length; i++) {
            rewards.push(_rewards[i]);
        }
    }

    // 保留原方法用于后续添加奖励(可选)
    function createReward(
        uint256 _contribution,
        uint256 _maxNumber,
        string memory _imageLink
    ) public restricted {
        Reward memory newReward = Reward({
            contribution: _contribution,
            maxNumber: _maxNumber,
            ImageLink: _imageLink
        });

        rewards.push(newReward);
    }
}

说明

  • 构造函数初始化rewards数组的方式减少了一次跨合约调用,既避免了权限问题,也降低了gas消耗。
  • 原createReward方法仍可保留,供后续manager添加新奖励使用。

内容的提问来源于stack exchange,提问作者Jeks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:55:13