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

跨合约调用时T1合约Mapping数组大小未更新问题求助

问题核心原因

你遇到的问题是**msg.sender的上下文混淆**:当通过t2合约调用t1的addNewVal时,t1里的msg.sender是t2合约的地址,而不是触发t2.callandAdd的用户地址。所以你添加的_tokenId实际上存在了t2合约地址对应的数组条目里,用自己的地址调用findSize自然看不到长度变化。

解决方案

推荐两种直接的修正方式,优先选第一种:

方案一:传递用户地址参数(安全直观)

修改t1的addNewVal函数,让它接收一个用户地址参数,明确指定要往哪个地址的数组里添加元素;同时t2调用时把当前用户的地址传过去。

修改后的t1合约:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract t1{
    mapping(address => uint256[]) AllSpecialNFT;
    
    // 新增address参数,指定要操作的用户地址
    function addNewVal(address user, uint _tokenId) public {
        AllSpecialNFT[user].push(_tokenId);
    }
    
    function findSize() public view returns(uint){
        return AllSpecialNFT[msg.sender].length;
    }
}

修改后的t2合约:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import './t1.sol';
contract t2 {
    t1 _t1;
    constructor(t1 t1_){
        _t1 = t1_;
    }
    
    // 调用t1.addNewVal时,传入当前用户的msg.sender
    function callandAdd(uint _tokenId) public{
        _t1.addNewVal(msg.sender, _tokenId);
    }
}

操作后,调用t2.callandAdd时,_tokenId会被添加到你自己地址对应的数组里,再调用t1.findSize就能看到数组长度正确增加。

方案二:使用tx.origin(不推荐,有安全风险)

可以在t1的addNewVal里用tx.origin替代msg.sender,tx.origin指整个交易的发起者地址。但这种方式存在钓鱼攻击风险,仅作了解:

function addNewVal(uint _tokenId) public {
    AllSpecialNFT[tx.origin].push(_tokenId);
}
验证补充

可以给t1加一个查询指定地址数组长度的函数,方便验证:

function findSizeOfAddress(address user) public view returns(uint){
    return AllSpecialNFT[user].length;
}

传入t2合约地址就能看到之前错误添加的元素数量,传入自己的地址则能看到修正后的正确长度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 10:13:30