solidity - “错误:返回错误:处理事务时出现 VM 异常:还原”
问题描述
我是区块链技术的新手。我正在关注 Dapp University 教程,当我尝试测试 sellTokens 函数时,它给了我“错误:返回错误:处理事务时 VM 异常:恢复”。我想我已经成功实现了批准功能,为什么它会显示以下错误以下是审查项目 Ethswap.sol所需的文件
pragma solidity ^0.5.0;
import "./Token.sol";
contract Ethswap {
string public name = "Ethswap Instant Exchange";
Token public token;
uint public rate = 100;
event TokenPurchased(
address account,
address token,
uint amount,
uint rate
);
event TokenSold(
address account,
address token,
uint amount,
uint rate
);
constructor(Token _token) public {
token = _token;
}
function buytokens() public payable {
// Calculate the no of tokens to buy
uint tokenAmount = msg.value * rate;
// require Ethswap has enough balance to perform transfer of tokens
require(token.balanceOf(address(this)) >= tokenAmount);
token.transfer(msg.sender, tokenAmount);
// Emit an event
emit TokenPurchased(msg.sender, address(token), tokenAmount, rate);
}
function sellTokens(uint256 _amount) public payable {
//Calculate amoutn of ether to redeem
uint etherAmount = _amount / rate;
// require Ethswap has enough ether to perform transfer
require(address(this).balance >= etherAmount);
//Perform Sale
token.transferFrom(msg.sender, address(this), _amount);
msg.sender.transfer(etherAmount);
//Emit an event
emit TokenSold(msg.sender, address(token), _amount, rate);
}
}
以下是 Dapp Token Token.sol的智能合约代码
pragma solidity ^0.5.0;
contract Token {
string public name = "DApp Token";
string public symbol = "DAPP";
uint256 public totalSupply = 1000000000000000000000000; // 1 million tokens
uint8 public decimals = 18;
event Transfer(
address indexed _from,
address indexed _to,
uint256 _value
);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
constructor() public {
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
}
以下是测试智能合约 Ethswap.test.js的测试 JavaScript 代码
- 项目清单
const { assert } = require("chai")
const { default: Web3 } = require("web3")
const Token = artifacts.require("Token")
const Ethswap = artifacts.require("Ethswap")
require("chai")
.use(require("chai-as-promised"))
.should()
function tokens(n) {
return web3.utils.toWei(n, "ether")
}
contract("Ethswap", ([deployer, investor]) => {
let token
let ethSwap
before(async () => {
token = await Token.new()
ethSwap = await Ethswap.new(token.address)
await token.transfer(ethSwap.address, tokens("1000000"))
})
describe("Token Deployment", async () => {
it("contract has a name", async () => {
let token = await Token.new()
const name = await token.name()
assert.equal(name, "DApp Token")
})
})
describe("EthSwap Deployment", async () => {
it("contract has a name", async () => {
let ethSwap = await Ethswap.new(token.address)
const name = await ethSwap.name()
assert.equal(name, "Ethswap Instant Exchange")
})
it("contract has tokens", async () => {
let balance = await token.balanceOf(ethSwap.address)
assert.equal(balance.toString(), tokens("1000000"))
})
})
describe("TokenPurchased", async () => {
it("Details of the investor", async () => {
let result
before(async () => {
result = await ethSwap.buytokens({from: investor, value: web3.utils.toWei("1", "ether"),
})
//Check investor token balance after purchase
let investorBalance = await token.balanceOf(investor)
assert.equal(investorBalance.toString(), token("100"))
//Check ethswap balance after purchase
let ethSwapBalance;
ethSwapBalance = await token.balanceOf(ethSwap.address)
assert.equal(ethSwapBalance.toString(), tokens("999900"))
ethSwapBalance = await web3.eth.getBalance(ethSwap.address)
assert.equal(ethSwapBalance.toString(), web3.utils.toWei("1", "Ether"))
const event = result.logs[0].args
assert.equal(event.account, investor)
assert.equal(event.token, token.address)
assert.equal(event.amount.toString(), tokens("100").toString())
assert.equal(event.rate.toString(), "100")
})
})
})
describe("SellTokens()", async () => {
let result
before(async () => {
//Investor must approve token before purchase
await token.approve(ethSwap.address, tokens('100'))
// Investor sells token
result = await ethSwap.sellTokens(tokens('100'), { from : investor })
})
it("Allows user to instantly sell tokens", async () => {})
})
})
解决方案
推荐阅读
- f# - 如何在 Visual Studio Code 中启用 F# Interactive?
- sparql - 使用光学 API (MarkLogic) 进行地理空间查询
- linux - 当有人连接到特定数据库时如何获得弹出窗口
- r - 计算每行中不同列的 rowMeans
- java - Spring-kafka-test 使用自定义反序列化测试 JSON 消息
- html - 使用 ajax 提交一个表单时,选项卡索引在第二个表单上不起作用
- python-2.7 - 如何将列表中的元素与另一个嵌套列表连接起来?
- android - 在路径上找不到类“android.support.design.internal.NavigationMenuItemView”:DexPathList
- openssl - 当我在生成 PFX 文件时不包含 .cert 文件的所有层次结构时会发生什么
- android - 当设备被锁定和休眠时,Android 上的 React Native App 停止执行