调用外部合约触发报错:VM处理交易时出现revert异常
排查MyGame合约调用ScoreStore时的VM Revert错误
咱们先从你的ScoreStore合约逻辑入手,看看最可能触发revert的点:你的SetScore函数里写了一个判断——如果目标用户的分数已经大于0,就会执行throw(在Solidity 0.4.x版本里,throw和revert是等价的),这是第一个需要排查的核心点。下面是具体的排查方向和解决方案:
1. 检查是否重复给同一用户调用SetScore
如果你的MyGame合约里,对同一个name值多次调用了SetScore,而且第一次调用已经成功设置了大于0的分数,那第二次调用必然会触发revert。
- 解决思路:
- 在调用
SetScore之前,先调用GetScore检查该用户是否已有有效分数; - 如果业务允许覆盖分数,直接修改ScoreStore的
SetScore逻辑,去掉if(PersonScores[name]>0)的判断即可。
- 在调用
2. 确认MyGame中引用的ScoreStore地址完全正确
很多时候revert是因为合约地址写错了——如果MyGame里初始化ScoreStore实例时用了错误的部署地址,调用肯定会失败。
- 解决思路:
- 重新复制ScoreStore部署后的正确地址,确保MyGame里的引用完全一致;
- 给你一个正确的合约引用示例(适配Solidity 0.4.x):
pragma solidity ^0.4.4; // 先声明ScoreStore的接口 contract ScoreStore { mapping(string => int) PersonScores; function SetScore(string name, int score) public; function GetScore(string name) public returns (int); } contract MyGame { ScoreStore public scoreStore; // 构造函数传入ScoreStore的部署地址 function MyGame(address _scoreStoreAddr) public { scoreStore = ScoreStore(_scoreStoreAddr); } // 调用ScoreStore的示例方法 function setPlayerScore(string name, int score) public { scoreStore.SetScore(name, score); } }
3. 检查函数调用的参数类型与签名是否匹配
Solidity对函数签名(函数名+参数类型)的要求很严格,如果MyGame里调用时参数类型错了(比如把uint当成int传,或者字符串格式出问题),也会触发revert。
- 解决思路:
- 确保调用
SetScore时,score是int类型、name是string类型,和ScoreStore里的定义完全一致; - 注意0.4.x版本中字符串的处理,虽然空字符串不会触发ScoreStore的throw,但也要避免传入不符合业务预期的内容。
- 确保调用
4. 检查调用时的Gas是否充足
虽然测试RPC节点一般不会卡Gas,但如果调用时手动设置的Gas限额太少,也可能导致交易被revert。
- 解决思路:
- 调用时适当提高Gas限额,或者直接使用测试节点的默认Gas设置即可。
建议你按照这个顺序逐步排查,先从重复调用的问题开始,大概率能快速定位到原因。
内容的提问来源于stack exchange,提问作者Fariha Abbasi
相关产品推荐
相关产品推荐

