如何使tx.origin不等于msg.sender?Alchemy挑战报错求助
解决ProviderError: execution reverted: msg.sender is equal to tx.origin问题
问题原因
合约的attempt函数包含校验逻辑,要求msg.sender不能等于tx.origin。当你用外部账户(比如addr1)直接调用合约的attempt时:
tx.origin是发起交易的外部账户地址(即addr1)msg.sender同样是addr1,因为是外部账户直接发起调用
两者相等,触发了合约的revert逻辑。
解决方法
必须通过中间合约间接调用目标合约的attempt函数,这样msg.sender会变为中间合约的地址,而tx.origin仍然是发起交易的外部账户,两者不再相等。
步骤1:编写中间调用合约
新建CallerContract.sol文件:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IContract { function attempt() external; } contract CallerContract { function callAttempt(address targetContract) external { // 调用目标合约的attempt函数 IContract(targetContract).attempt(); } }
步骤2:修改Hardhat脚本
更新部署脚本,部署中间合约并通过它间接调用attempt:
const hre = require("hardhat"); require("dotenv").config(); async function main() { // 部署目标合约 const Contract = await hre.ethers.getContractFactory("Contract"); const contract = await Contract.deploy(); await contract.waitForDeployment(); console.log(`Contract was deployed to ${contract.target}`); // 部署中间调用合约 const CallerContract = await hre.ethers.getContractFactory("CallerContract"); const callerContract = await CallerContract.deploy(); await callerContract.waitForDeployment(); console.log(`CallerContract was deployed to ${callerContract.target}`); const [owner, addr1] = await ethers.getSigners(); // 用addr1发起交易,通过中间合约调用目标合约的attempt await callerContract.connect(addr1).callAttempt(contract.target); console.log("Attempt function executed successfully"); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); });
原理说明
当addr1发起交易调用中间合约的callAttempt时:
tx.origin= addr1(发起交易的外部账户)- 中间合约调用目标合约的
attempt时,msg.sender= 中间合约的地址
此时两者不相等,合约的校验逻辑会通过,不会触发revert。
内容的提问来源于stack exchange,提问作者0xDev
相关产品推荐
相关产品推荐

