我是区块链技术的新手。我正在关注 Dapp 大学教程,当我尝试测试 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;
}
}
以下是测试智能合约的测试javascript代码 Ethswap.test.js
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 () => {})
})
})