编辑:为了清楚起见,getMessage()函数在混合中工作得很好。只是我的前端似乎不起作用。
我正在尝试为我的合同设置一个前端,但是当试图调用某个返回字符串的函数时,我会在我的web控制台中得到以下错误:
Error: ERROR: The returned value is not a convertible string: formatters.js:261
当我在这里调用getMessage
函数(在App.js中)时,似乎会发生错误:
async componentDidMount() {
const host = await chatroom.methods.host().call();
const members = await chatroom.methods.getMembers().call();
const chatLoglength = await chatroom.methods.getMessagesLength().call();
const chatLog = [];
for (let i = 0; i < chatLoglength; i++) {
const newMessage = await chatroom.methods.getMessage(i+1).call();
chatLog.push(newMessage);
}
this.setState({ host, members, chatLog });
}
我使用的是web3版本1.0.0-beta.35。我已经确认我用正确的字节码和ABI实例化了合同。我不知道为什么我能够从其他函数返回字符串,但不能返回这个函数。任何帮助都将不胜感激。下面的代码。
合同:
pragma solidity ^0.4.25;
contract Chatroom {
address public host;
string private password;
address[] public members;
Message[] public chatLog;
mapping(uint => Message) msgIDPair;
mapping(address => bool) isMember;
struct Message {
address author;
string content;
}
// @notice Creates the chat-room. Host role is given to the address of the sender
// @dev The password could be inferred from the constructor argument, not strong security
// @param _password The password the host wishes to set for the chat-room
constructor(string _password) public {
host = msg.sender;
addMember(host); // adds host address to members array
password = _password;
}
// @notice Send a message `(_message)` to the chat-room (must be a member)
// @param _message The content of the message to be sent
function sendMessage(string _message) external mustBeMember {
uint msgID = chatLog.length + 1;
msgIDPair[msgID] = Message(msg.sender, _message); // pairs message ID with Message struct object
chatLog.push(msgIDPair[msgID]); // adds Message object to chatLog array
}
// @notice Retrieve a message via ID `(_ID)`
// @dev Returns struct of Message, use front-end to get specific properties
// @param _ID The ID assigned to the desired message
// @return The target message
function getMessage(uint _ID) public view mustBeMember returns(string) {
return(msgIDPair[_ID].content);
}
// @notice Check if an address is a member
// @param _target The address to be checked
// @return true if the target address is a member, false otherwise
function checkMember(address _target) public view returns(bool) {
if (isMember[_target] == true) { // returns true if address has a "true" value assigned in isMember mapping table
return(true);
}
else { // returns false if address does not have a "true" value assigned in isMember mapping table
return(false);
}
}
modifier mustBeMember() {
require(checkMember(msg.sender) == true);
_;
}
// @notice Become a member the chat-room (requires `(password)`)
// @param _password The password to evaluate
function joinChat(string _password) public requirePassword(_password) {
addMember(msg.sender);
}
// @notice Leave the chat-room (must be a member)
function leaveChat() public mustBeMember {
require(msg.sender != host); // host cannot leave, must transfer role first
for (uint i = 0; i < members.length; i++) { // loops through entire members array, deletes matching address
if (members[i] == msg.sender) {
swapReduceIndex(members, i);
}
}
isMember[msg.sender] = false;
}
// @notice Add a new member address that is not already a member
// @dev This is a helper function
// @param _newMember The address to be granted membership
function addMember(address _newMember) private {
if (isMember[_newMember] == true) { // does nothing if address is already a member
return();
}
else { // adds address to isMember mapping table and pushes the address to the members array
isMember[_newMember] = true;
members.push(msg.sender);
}
}
// @notice Retrieve a list of all members
// @return A list of all member addresses
function getMembers() public view returns(address[]) {
return(members);
}
modifier requirePassword(string _password) {
require(keccak256(password) == keccak256(_password));
_;
}
modifier onlyHost {
require(msg.sender == host);
_;
}
// @notice Remove a member (requires 'host' status)
// @param _member Address of the member to be removed
function kickMember(address _member) external onlyHost {
require(msg.sender != _member); // host cannot kick himself
for (uint i = 0; i < members.length; i++) { // loops through entire members array, deletes matching address
if (members[i] == _member) {
swapReduceIndex(members, i);
}
}
isMember[_member] = false;
}
// @notice Transfer 'Host' role to another member (requires 'host' status)
// @param newHost The address of the member to be granted the 'host' role.
function switchHost(address newHost) external onlyHost {
require(checkMember(newHost));
host = newHost;
}
// @notice Delete index of array, swap last index with deleted, remove last index
// @dev Only works with address arrays, inteded to be used as a helper function with removing member addresses
// @param array The array in which to modify
// @param _blankIndex The number of the index to be deleted
function swapReduceIndex(address[] storage array, uint _blankIndex) internal {
delete array[_blankIndex];
uint lastIndex = array.length-1;
array[_blankIndex] = array[lastIndex];
array.length--;
}
// @notice Get length of chatLog array
// @dev Useful for displaying messages on front-end
function getMessagesLength() external view returns (uint) {
return(chatLog.length);
}
}
App.js (格式化问题,必须使用github链接):https://github.com/PresidentPorpoise/chatroom-react/blob/master/src/App.js
发布于 2018-10-21 08:26:54
mustBeMember
修饰符在getMessage()
上是否与此有关?
我发现基于权限的修饰符与视图函数的工作方式可能有点奇怪。如图所示,您将不会看到抛出,但您将得到一些其他数据。
在这种情况下..。契约可能期望返回一个字符串,因为它是一个视图函数,而实际上由于不满足修饰符权限要求而抛出.这意味着它将返回一个抛出而不是一个字符串。
https://ethereum.stackexchange.com/questions/60905
复制相似问题