区块链研究区块链研习社以太坊

智能合约实践—便签墙

2019-04-23  本文已影响3人  六天天天向上

今天试用了一下迅雷链推出的智能合约IDE,支持以太坊的EVM和WASM虚拟机。
今天使用的是EVM合约,整体感觉还不错,支持关键词提示,编译、错误提示,部署等,语法高亮也比较美观,但和Remix比起来没那么强大,不支持debug。
试用地址:https://catalyst.onethingcloud.com/#/catalyst

今天在catalyst上写了一个便签墙的智能合约,合约整体思路是:
便签包括标题和内容,用户可以发布和修改自己便签,管理员可以关闭某些包含敏感词汇的便签,用户可以浏览所有未被关闭的便签。

合约引用了catalyst编译器提供的Ownable权限合约,Ownable代码如下:

pragma solidity >=0.4.22 <0.6.0;

contract Ownable {
    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(address _owner) public {
        owner = _owner;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "only owner operate");
        _;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "new owner address should not be null");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

}

这个权限合约很简单,声明了一个合约所有者的owner全局地址与修改合约所有者的transferOwnership方法。

便签墙主合约代码如下:

pragma solidity >=0.4.22 <0.6.0;

import "./Ownable.sol";

contract NoteWall is Ownable {
    //声明了一个便签结构体
    struct Note {
        string title; //标题
        string content; //内容
        address owner; //便签创建者地址
    }
    //便签数组
    Note[] private notes;
    
    mapping(uint256 => bool) public closedNotes; //被管理员关闭的便签id
    
    //合约是否开启
    bool isopen;
    
    //验证合约是否开启
    modifier onlyOpen() {
        require(isopen == true, "The NoteWall is closed now!");
        _;
    }
    
    //构造函数,传递合约管理员地址,并开启合约
    constructor(address initialAccount) Ownable(initialAccount) public {
        isopen = true;
    }
    
    //修改项目的开启或关闭
    function changeOpen(bool openState) public onlyOwner returns(bool) {
        require(isopen != openState, "Please change the open state");
        isopen = openState;
        return true;
    }
    
    //验证标题长度
    modifier checkTitleLength(string _title) {
        require(bytes(_title).length > 0 && bytes(_title).length <= 60, "Title cannot be empty and less than 20 words");
        _;
    }
    
    //验证内容长度
    modifier checkContentLength(string _content) {
        require(bytes(_content).length > 0 && bytes(_content).length <= 600, "Title cannot be empty and less than 200 words");
        _;
    }
    
    //添加新的便签
    function addNewNote(string _title, string _content) public 
onlyOpen checkTitleLength(_title) checkContentLength(_content) returns(uint256) {
        uint noteid = notes.length++;
        notes[noteid] = Note({
            title : _title,
            content : _content,
            owner : msg.sender
            });
        return noteid;
    }
    
    //修改自己的便签
    function updateNote(uint256 noteid, string _title, string _content) public 
onlyOpen checkTitleLength(_title) checkContentLength(_content) returns(bool) {
        Note storage oneNote = notes[noteid];
        require(oneNote.owner == msg.sender, "this is not your note");
        oneNote.title = _title;
        oneNote.content = _content;
        return true;
    }
    
    //返回便签的长度
    function getNoteLength() public view returns(uint256) {
        return notes.length;
    }
    
    //获取便签信息,这里之所以单独写了一个方法而不是把notes数组设置成public,是要屏蔽查看被关闭的便签
    function getNoteInfo(uint256 noteid) public view returns(string, string) {
        require(notes.length >= noteid && closedNotes[noteid] == false, "this note is invisible");
        return(notes[noteid].title, notes[noteid].content);
    }
    
    //只有管理员可操作,关闭某一个便签
    function closeOnedNote(uint256 noteid) public onlyOwner returns(bool) {
        require(notes.length >= noteid && closedNotes[noteid] == false, "this note is invisible");
        closedNotes[noteid] = true;
        return true;
    }
    
}

此合约有几个知识点,需要注意一下:
1、 string类型是一种特殊的动态数组,是没有length属性的,因此要计算string的长度需要先使用bytes显性转成动态数组。
2、mapping类型的closedNotes变量,在key不存在的情况下返回0x0000000000000000000000000000000000000000000000000000000000000000

上一篇下一篇

猜你喜欢

热点阅读