在信任我的 Solidity 智能合约时遇到问题(with/Truffle)
Having a Problem Testing my Solidity Smart Contract (w/ Truffle)
所以我正在构建一个基本的 NF 令牌。创建了一个基本的铸币函数和映射。我用松露测试应用程序,尝试了可靠性测试和 JS 测试。出现以下错误。
Using network 'development'.
Compiling ./contracts/NFCertificate.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/AddressUtils.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/ERC165.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/SupportsInterfaceWithLookup.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Basic.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Receiver.sol...
Compiling ./test/TestCertificate.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
Compilation warnings encountered:
/Users/aditya/Desktop/Work & Hobbies/Ideas/Blockchain/Blockchain Development/Ethereum:dApp/CertificateContract/contracts/NFCertificate.sol:26:35: Warning: This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data.
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
^---------------------------------------------------^
TestCertificate
1) testNumber
> No events were emitted
Contract: NFCertificate
2) It should return the same number
> No events were emitted
0 passing (1s)
2 failing
1) TestCertificate
testNumber:
Error: VM Exception while processing transaction: revert
at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
2) Contract: NFCertificate
It should return the same number:
TypeError: instance.returnNumbers is not a function
at Context.<anonymous> (test/TestCertificate.js:9:31)
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/testing/testrunner.js:135:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/property.js:119:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:89:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
测试脚本是运行合约中的一个简单内部函数,它returns一个int = 1000并将其与测试中声明的预期变量(让预期= 1000)进行比较。这是 JS 测试脚本
import assertRevert from "zeppelin-
solidity/test/helpers/assertRevert";
const NFCertificate = artifacts.require("NFCertificate");
contract("NFCertificate", () => {
it("It should return the same number", function() {
let instance = NFCertificate.deployed();
let expected = 1000;
assert.equal(instance.returnNumber(), expected);
});
});
这是 Solidity 测试脚本:
pragma solidity ^0.4.20;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/NFCertificate.sol";
contract TestCertificate {
function testNumber() public {
NFCertificate cert = NFCertificate(DeployedAddresses.NFCertificate());
uint expected = 1000;
Assert.equal(cert.returnNumber(), expected, "Numbers should be equal");
}
}
我还尝试测试铸造的令牌 ID,以及基于我声明的映射的令牌所有者,我遇到了同样的问题。 在javascript中编写测试合约时无法识别原始NFT合约中的功能。当用 solidity 编写测试合约时,它几乎总是说 "Error: VM Exception while processing transaction: revert" 而没有别的。
最后是我正在尝试测试的合同。感谢所有帮助,我对编码和以太坊还很陌生,所以我可能犯了很多错误。
pragma solidity ^0.4.24;
import '../node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol';
import '../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol';
contract NFCertificate is ERC721BasicToken, Ownable {
struct Certificate {
uint certNum;
uint256 tokenId;
bytes32 title;
bytes32 message;
address owner;
}
mapping (uint256 => address) tokenToOwner;
mapping (address => uint256) ownerToToken;
mapping (uint256 => string) tokenIdToName;
event returnNumbers(uint number);
Certificate[] public certificates;
function createCert(bytes32 title, bytes32 message) public returns (bytes32){
uint certificateNum = certificates.length - 1;
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
certificates.push(Certificate(certificateNum++, tokenId, title, message, msg.sender));
tokenToOwner[tokenId] = msg.sender;
ownerToToken[msg.sender] = tokenId;
_mint(msg.sender, tokenId);
}
function returnNumber() public returns(uint) {
uint number = 1000;
returnNumbers(number);
return number;
}
function whatTokensDoYouOwn(address owner) public view returns(uint256) {
return ownerToToken[owner];
}
}
NFCertificate.deployed()
returns 承诺,instance.returnNumber()
也是如此。所以JS应该是:
contract("NFCertificate", () => {
it("It should return the same number", async function() {
let instance = await NFCertificate.deployed();
let expected = 1000;
assert.equal(await instance.returnNumber(), expected);
});
});
由于 returnNumbers
是一个事件,因此应该使用 emit
关键字发出。以大写开头的事件样式也很好,否则它可能看起来像一个函数。所以event ReturnNumbers(uint number);
function returnNumber() public returns(uint) {
uint number = 1000;
emit ReturnNumbers(number);
return number;
}
添加 async/await 行应该可以修复您的 JavaScript 测试。如果您稍后想要断言您的 ReturnNumbers
事件已正确发出,我建议使用我的 truffle-assertions
库,其中包含断言事件已发出或未发出的函数。它还包括以直接的方式断言恢复和其他失败的函数。
所以我正在构建一个基本的 NF 令牌。创建了一个基本的铸币函数和映射。我用松露测试应用程序,尝试了可靠性测试和 JS 测试。出现以下错误。
Using network 'development'.
Compiling ./contracts/NFCertificate.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/AddressUtils.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/ERC165.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/introspection/SupportsInterfaceWithLookup.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Basic.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol...
Compiling ./node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721Receiver.sol...
Compiling ./test/TestCertificate.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
Compilation warnings encountered:
/Users/aditya/Desktop/Work & Hobbies/Ideas/Blockchain/Blockchain Development/Ethereum:dApp/CertificateContract/contracts/NFCertificate.sol:26:35: Warning: This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data.
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
^---------------------------------------------------^
TestCertificate
1) testNumber
> No events were emitted
Contract: NFCertificate
2) It should return the same number
> No events were emitted
0 passing (1s)
2 failing
1) TestCertificate
testNumber:
Error: VM Exception while processing transaction: revert
at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
2) Contract: NFCertificate
It should return the same number:
TypeError: instance.returnNumbers is not a function
at Context.<anonymous> (test/TestCertificate.js:9:31)
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/testing/testrunner.js:135:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/property.js:119:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:89:1
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
at endReadableNT (_stream_readable.js:1081:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
测试脚本是运行合约中的一个简单内部函数,它returns一个int = 1000并将其与测试中声明的预期变量(让预期= 1000)进行比较。这是 JS 测试脚本
import assertRevert from "zeppelin-
solidity/test/helpers/assertRevert";
const NFCertificate = artifacts.require("NFCertificate");
contract("NFCertificate", () => {
it("It should return the same number", function() {
let instance = NFCertificate.deployed();
let expected = 1000;
assert.equal(instance.returnNumber(), expected);
});
});
这是 Solidity 测试脚本:
pragma solidity ^0.4.20;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/NFCertificate.sol";
contract TestCertificate {
function testNumber() public {
NFCertificate cert = NFCertificate(DeployedAddresses.NFCertificate());
uint expected = 1000;
Assert.equal(cert.returnNumber(), expected, "Numbers should be equal");
}
}
我还尝试测试铸造的令牌 ID,以及基于我声明的映射的令牌所有者,我遇到了同样的问题。 在javascript中编写测试合约时无法识别原始NFT合约中的功能。当用 solidity 编写测试合约时,它几乎总是说 "Error: VM Exception while processing transaction: revert" 而没有别的。
最后是我正在尝试测试的合同。感谢所有帮助,我对编码和以太坊还很陌生,所以我可能犯了很多错误。
pragma solidity ^0.4.24;
import '../node_modules/openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol';
import '../node_modules/openzeppelin-solidity/contracts/ownership/Ownable.sol';
contract NFCertificate is ERC721BasicToken, Ownable {
struct Certificate {
uint certNum;
uint256 tokenId;
bytes32 title;
bytes32 message;
address owner;
}
mapping (uint256 => address) tokenToOwner;
mapping (address => uint256) ownerToToken;
mapping (uint256 => string) tokenIdToName;
event returnNumbers(uint number);
Certificate[] public certificates;
function createCert(bytes32 title, bytes32 message) public returns (bytes32){
uint certificateNum = certificates.length - 1;
uint256 tokenId = uint256(keccak256(certificateNum, msg.sender, title, message));
certificates.push(Certificate(certificateNum++, tokenId, title, message, msg.sender));
tokenToOwner[tokenId] = msg.sender;
ownerToToken[msg.sender] = tokenId;
_mint(msg.sender, tokenId);
}
function returnNumber() public returns(uint) {
uint number = 1000;
returnNumbers(number);
return number;
}
function whatTokensDoYouOwn(address owner) public view returns(uint256) {
return ownerToToken[owner];
}
}
NFCertificate.deployed()
returns 承诺,instance.returnNumber()
也是如此。所以JS应该是:
contract("NFCertificate", () => {
it("It should return the same number", async function() {
let instance = await NFCertificate.deployed();
let expected = 1000;
assert.equal(await instance.returnNumber(), expected);
});
});
由于 returnNumbers
是一个事件,因此应该使用 emit
关键字发出。以大写开头的事件样式也很好,否则它可能看起来像一个函数。所以event ReturnNumbers(uint number);
function returnNumber() public returns(uint) {
uint number = 1000;
emit ReturnNumbers(number);
return number;
}
添加 async/await 行应该可以修复您的 JavaScript 测试。如果您稍后想要断言您的 ReturnNumbers
事件已正确发出,我建议使用我的 truffle-assertions
库,其中包含断言事件已发出或未发出的函数。它还包括以直接的方式断言恢复和其他失败的函数。