能否在Matchstick测试框架中无需模拟即可调用balanceOf方法?
Matchstick测试中处理AMM合约balanceOf调用的方案
在Matchstick这类合约测试框架中,必须模拟balanceOf函数调用,无法直接通过"预先注入代币"的方式让balanceOf返回预期值——因为Matchstick的核心是mock合约交互,而非维护完整的链上存储状态(比如代币余额的映射关系)。
具体实现步骤
针对你代码中用到的两个AMM池合约,在测试代码执行tokenPrice函数之前,提前用Matchstick的mockFunction方法模拟balanceOf的返回逻辑:
// 模拟GLMR-DOT池的balanceOf调用 const glmrDotPoolAddr = Address.fromString(GLMR_DOT); mockFunction( glmrDotPoolAddr, "balanceOf", "balanceOf(address):(uint256)", (args) => { const targetAddr = args[0]; // 返回WGLMR在池中的余额,示例为1000 GLMR(18位小数) if (targetAddr.equals(Address.fromString(WGLMR))) { return [new Uint8Array(toBigInt(1000n * 10n**18n).toBytes())]; } // 返回DOT在池中的余额,示例为500 DOT(10位小数) else if (targetAddr.equals(Address.fromString(DOT))) { return [new Uint8Array(toBigInt(500n * 10n**10n).toBytes())]; } // 默认返回0 return [new Uint8Array(BigInt.zero().toBytes())]; } ); // 模拟GLMR-USDC池的balanceOf调用 const glmrUsdcPoolAddr = Address.fromString(GLMR_USDC); mockFunction( glmrUsdcPoolAddr, "balanceOf", "balanceOf(address):(uint256)", (args) => { const targetAddr = args[0]; // 返回WGLMR在池中的余额,示例为2000 GLMR if (targetAddr.equals(Address.fromString(WGLMR))) { return [new Uint8Array(toBigInt(2000n * 10n**18n).toBytes())]; } // 返回USDC在池中的余额,示例为1000000 USDC(6位小数) else if (targetAddr.equals(Address.fromString(USDC))) { return [new Uint8Array(toBigInt(1000000n * 10n**6n).toBytes())]; } return [new Uint8Array(BigInt.zero().toBytes())]; } ); // 同时需要模拟priceOfGlmr()函数的返回值(如果它依赖外部调用) // 示例:假设priceOfGlmr返回1 GLMR = 100 USDC,模拟对应储备金调用 mockFunction( Address.fromString(GLMR_USDC), "getReserves", "getReserves():(uint112,uint112,uint32)", () => { return [ new Uint8Array(toBigInt(1000n * 10n**18n).toBytes()), new Uint8Array(toBigInt(100000n * 10n**6n).toBytes()), new Uint8Array(BigInt.zero().toBytes()) ]; } );
关键说明
- Matchstick不会自动维护合约的存储状态,所有外部合约的函数调用都需要提前mock,否则会抛出你遇到的"找不到模拟函数"错误。
- 模拟时要确保函数签名、目标地址和参数完全匹配,这样测试代码执行
tokenPrice时,就能获取到你预设的池内代币余额,完成价格计算。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

