Solidity
“返回的值不是可轉換的字元串”(web3js & React 前端)
編輯:要清楚, 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
上的
mustBeMember
修飾符getMessage()
會與此有關嗎?我發現基於權限的修飾符與視圖函式一起使用的方式可能有點奇怪。正如你不會看到拋出但你會得到一些其他數據。
在這種情況下……合約可能期望返回一個字元串,因為它是一個視圖函式,而實際上它由於不滿足修飾符權限要求而正在拋出……這意味著它將返回一個拋出而不是細繩。