一种非常简单的模拟Solidity智能合约交易的方法
Posted MateZero
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一种非常简单的模拟Solidity智能合约交易的方法相关的知识,希望对你有一定的参考价值。
一种非常简单的模拟Solidity智能合约交易的方法
我们知道,在MetaMask调用合约时,会模拟执行一次,如果调用失败,会提前显示失败并问你是否要强制执行。这个功能很有用的,那么我们自己能不能实现类似的功能呢?
答案是肯定的,并且也相当简单。
示例合约
我们先看测试合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MockTest
uint public x = 5;
address public owner;
constructor()
owner = msg.sender;
modifier onlyOwner
require(msg.sender == owner, "only owner");
_;
function changeX(uint _x) external onlyOwner returns(uint value, address sender)
x = _x;
return (_x * _x,msg.sender);
合约很简单,只有管理员能改变x的值并且进行相关计算(操作)。这里只是简单计算了x
的平方来模拟合约中复杂的操作过程。
那我们有时候想自己模拟运行一下,并得到相应的操作结果,能否实现呢?
答案就在下方 -_- !
模拟方法
请看下面的单元测试文件:
const expect,assert = require("chai");
const ethers = require("hardhat");
describe("Mock test", function ()
let instance;
beforeEach(async () =>
const MockTest = await ethers.getContractFactory("MockTest");
instance = await MockTest.deploy();
);
it("Call without owner will be failed" , async () =>
let data = instance.interface.encodeFunctionData("changeX",[9]);
let AddressOne = ethers.utils.getAddress("0x" + "0".repeat(39) + "1");
let transaction =
from:AddressOne,
to:instance.address,
data
;
try
await ethers.provider.call(transaction);
catch(e)
assert.equal(e.message,"VM Exception while processing transaction: reverted with reason string 'only owner'");
return;
throw("Test Failed");
);
it("Call with owner will be successful", async () =>
let data = instance.interface.encodeFunctionData("changeX",[9]);
let owner = await instance.owner();
let transaction =
from:owner,
to:instance.address,
data
;
let result = await ethers.provider.call(transaction);
const value,sender = instance.interface.decodeFunctionResult("changeX",result);
expect(value).to.be.equal(81);
expect(sender).to.be.equal(owner);
expect(await instance.x()).to.be.equal(5);
);
);
运行单元测试的结果为:
Mock test
✔ Call without owner will be failed (40ms)
✔ Call with owner will be successful
2 passing (619ms)
那么,有的小伙伴要问了,如果别人把这个owner
设置为私有变量,我怎么去获取这个owner
呢?
记住,私有变量只是对链上合约不可见,对链下是没有办法隐藏的。以太坊一切可是公开透明的。
例如我们可以通过观察合约部署者,平常具有管理员权限的函数的调用,直接读取相应插槽等方法来获取这个owner
。
以上是关于一种非常简单的模拟Solidity智能合约交易的方法的主要内容,如果未能解决你的问题,请参考以下文章
使用 Browser-solidity 在 Go-Ethereum 上进行简单的智能合约部署
我们可以在智能合约中使用 Solidity 获取过去区块中记录的交易信息吗?