#javascript #blockchain #ethereum #solidity #truffle
Вопрос:
Я следовал этому учебнику, чтобы узнать о программировании NFS и Ethereum. Это немного устарело, но все шло довольно гладко, пока я не попробовал чеканить с консоли truffle, что дало мне следующую ошибку :
Uncaught Error: Returned error: VM Exception while processing transaction: revert
Я использую truffle
, ganache
, node
, web3
amp; openzeppelin
.
Вот как я получаю ошибку :
truffle console
> global = globalThis
если я этого не сделаю, я получу «глобальный не определен».
> contract = await Color.deployed()
> await contract.mint('#fefefe')
Вот где я получаю ошибку вместо квитанции TX.
Я, очевидно, довольно новичок в разработке блокчейна (и тоже не очень экспериментировал с программированием), и я изо всех сил старался преодолеть эту проблему, но пока тщетно.
Чего я не понимаю, так это почему чеканка работает из тестового файла, а не из консоли. Я покопался в подробных журналах ганаша, но не нашел ничего, кроме сообщения об ошибке (что может означать многое из того, что я прочитал в Интернете).
Вот смарт-контракт :
// contracts/Color.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6; // updated from video to match Sol compiler
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Color is ERC721Enumerable { // updated from video to match latest openzeppelin updates
string[] public colors; // array of colors available from outside
mapping(string => bool) _colorExists; // hash of colors with minted status (true/false)
constructor() ERC721("Color", "CLR") {}
function mint(string memory _color) public {
require(!_colorExists[_color]); // color can only be minted once
colors.push(_color);
uint256 _id = colors.length - 1;
_mint(msg.sender, _id); // calling the mint function from openzeppelin contract
_colorExists[_color] = true;
}
}
И файл теста :
const { assert } = require('chai');
/* eslint-disable no-undef */
const Color = artifacts.require('../contracts/Color.sol');
require('chai')
.use(require('chai-as-promised'))
.should();
contract('Color', (accounts) => {
before(async () => {
contract = await Color.deployed();
});
describe('deployment', async () => {
it('deployed successfully', async () => {
const address = contract.address;
console.log('address is:', address);
assert.notEqual(address, '');
assert.notEqual(address, 0x0);
assert.notEqual(address, null);
assert.notEqual(address, undefined);
});
it('has a name', async () => {
const name = await contract.name();
assert.equal(name, 'Color');
});
it('has the right symbol', async () => {
const symbol = await contract.symbol();
assert.equal(symbol, 'CLR');
});
});
describe('minting', async () => {
it('creates a new token', async () => {
const result = await contract.mint('#dc143c');
const totalSupply = await contract.totalSupply();
// SUCCESS
const event = result.logs[0].args;
assert.equal(totalSupply, 1, 'supply is OK');
assert.equal(event.tokenId.toNumber(), totalSupply - 1, 'token id is OK');
assert.equal(
event.from,
'0x0000000000000000000000000000000000000000',
'from address is OK'
);
assert.equal(event.to, accounts[0], 'to address is OK');
// FAILURE : cannot mint same color twice
await contract.mint('#dc143c').should.be.rejected;
});
});
describe('indexing', async () => {
it('lists colors', async () => {
await contract.mint('#6495ed');
await contract.mint('#000000');
await contract.mint('#8fbc8f');
const totalSupply = await contract.totalSupply();
assert.equal(totalSupply, 4, 'total supply is ok');
let result = [];
const expected = ['#dc143c', '#6495ed', '#000000', '#8fbc8f'];
for (let i = 1; i <= totalSupply; i ) {
let color = await contract.colors(i - 1);
result.push(color);
}
assert.equal(
result.join(','),
expected.join(','),
'listing colors is ok'
);
});
});
});
У меня все есть в репо, если кто-то захочет копнуть еще глубже.
Большое спасибо!
Комментарии:
1. У меня противоположная проблема: чеканка работает в консоли, и она не работает в тесте трюфелей (но я использую тесты на прочность). Если вы еще не нашли причину, одна вещь, которую я попытался лучше понять, — это использовать другой адрес вместо msg.sender. В моем случае я обнаружил, что он не работает с этим, но он работает с любыми другими жестко закодированными адресами.