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

如何通过Factory合约调用ERC721的mint函数并修改其状态变量?

解决Factory合约调用ERC721 mint时的状态更新与msg.sender问题

核心问题解析

  • 直接通过Factory调用ERC721的mint函数时,msg.sender会是Factory合约地址,而非发起调用的用户地址。
  • delegatecall无法更新ERC721的状态:因为delegatecall会以调用者(Factory)的存储上下文执行目标合约代码,所有状态修改都会写入Factory的存储,而非ERC721合约,这是delegatecall的固有特性。

可行实现方案

方案1:修改ERC721的mint逻辑,允许Factory调用并传递用户地址

调整ERC721合约的mint函数,添加权限验证(仅允许Factory调用),并接收要 mint 的目标用户地址:

// ERC721合约示例
contract MyERC721 is ERC721 {
    address public factory;
    uint256 public nextTokenId;

    constructor(address _factory) ERC721("MyNFT", "MNFT") {
        factory = _factory;
    }

    modifier onlyFactory() {
        require(msg.sender == factory, "Only factory can call");
        _;
    }

    function mint(address to) external onlyFactory {
        _safeMint(to, nextTokenId);
        nextTokenId++;
    }
}

Factory合约中调用该mint函数时,将发起调用的用户地址(msg.sender)传递进去:

// Factory合约示例
contract NFTFactory {
    MyERC721 public nftContract;

    constructor(address _nftContract) {
        nftContract = MyERC721(_nftContract);
    }

    function createNFT() external {
        // 调用ERC721的mint,将NFT mint给调用Factory的用户
        nftContract.mint(msg.sender);
    }
}

此方案中,ERC721的状态会被直接更新,因为是通过常规合约调用操作目标合约的存储。

方案2:使用EIP-2771元交易实现用户身份传递(无需修改mint逻辑的场景)

如果无法修改ERC721的mint函数(例如mint仅允许msg.sender给自己 mint),可通过EIP-2771元交易让Factory作为中继,传递用户的签名身份:

  1. ERC721合约实现EIP-2771的信任转发逻辑:
contract MyERC721WithMeta is ERC721 {
    address public trustedForwarder;
    uint256 public nextTokenId;

    constructor(address _forwarder) ERC721("MyNFT", "MNFT") {
        trustedForwarder = _forwarder;
    }

    modifier onlyTrustedForwarder() {
        require(msg.sender == trustedForwarder, "Not trusted forwarder");
        _;
    }

    function mint() external onlyTrustedForwarder {
        address user = _msgSender();
        _safeMint(user, nextTokenId);
        nextTokenId++;
    }

    // 获取实际发起交易的用户地址
    function _msgSender() internal view returns (address) {
        if (msg.sender == trustedForwarder && msg.data.length >= 20) {
            assembly {
                return(add(msg.data, 0x14), 0x20)
            }
        }
        return msg.sender;
    }
}
  1. Factory作为中继转发用户的交易请求,传递用户签名与地址,ERC721合约验证后会以实际用户身份执行mint,状态更新正常写入ERC721合约。

内容的提问来源于stack exchange,提问作者Naveen-Arali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:13:08