《百灵界》悬赏合约是如何实现的

bounty.jpg

https://etherlark.github.io

悬赏合约在《百灵界》的设计中也算是个亮点啰!它可以实现悬赏的功能,有些类似于国内的威客,国外的freelancer这样的功能。不同的是,《百灵界》使用智能合约来完成这一功能。

如上图所示,悬赏主要分成三步,七个状态,由金主(发布悬赏的人)和猎人(应聘的人)来共同完成合约。智能合约没有第三方来监督这个过程,所以,悬赏的完成只能由金主和猎人之间的互信和博弈。设计了七个状态也是考虑到检视任务完成的复杂性,有一定的约束性,又让人有利益的驱动主动完成合约。

悬赏的功能不也正好对应当前的零工经济吗?! 撮合有需求的双方完成一定的任力,大家各取所需,不是皆大欢喜嘛!目前《百灵界》已上测试网,也想听听大家的意见,后期会不断改进。

pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2;


contract Bounty {    
     /*
    金主发布悬赏   Created 
    金主取消任务   Cancelled
    金主确认猎人   Confirmed
    猎人A提交任务  HunterFinished
    猎人A超时未提交任务 HunterOutOfTime 
    金主确认任务完成  Promoterfinished
    金主超时未确认任务  PromoterOutOfTime
    */
    enum State { Created, Cancelled, Confirmed,  HunterFinished, HunterOutOfTime, Promoterfinished, PromoterOutOfTime}
   
    uint public id = 0;
    struct TaskMessage 
    {
        string hash;
        address promoter;
        address hunterA;
        address[] hunters;
        string[] reasonHashs;
        uint bonus;
        uint taskStart;
        uint taskDeadLine;
        State state;
    }

    mapping(uint => TaskMessage) public tasks;
    
    // receive() external payable { }
    
    // fallback () external payable { }
    
    
    modifier onlyPromoter(uint _uid) {
        require(msg.sender == tasks[_uid].promoter);
        _;
    }
    
    modifier onlyhunterA(uint _uid) {
        require(msg.sender == tasks[_uid].hunterA);
        _;
    }
    
    modifier inState(uint _uid, State _state) {
        require(tasks[_uid].state == _state );
        _;
    }
    
    modifier inTime(uint _uid) {
        require(now <= tasks[_uid].taskStart + tasks[_uid].taskDeadLine);
        _;
    }
    
    modifier outOfTime(uint _uid) {
        require(now > tasks[_uid].taskStart + tasks[_uid].taskDeadLine);
        _;
    }
    
    event SetTask(uint _uid, TaskMessage _task);
    
    //金主发布悬赏。
    function setTask(string memory _hash, uint _bonus, uint _hour, uint _minunt) 
        public 
    {       
        id += 1;
        tasks[id].hash = _hash;
        tasks[id].promoter = msg.sender;
        tasks[id].bonus = _bonus;
        tasks[id].taskDeadLine = _hour * 1 hours + _minunt * 1 minutes;
        token.transferFromOrigin(address(this), _bonus+_bonus/2);
        
        emit SetTask(id, tasks[id]);
    }

    //猎人申请任务
    function applyTask(uint _uid, string memory _reasonHashs) 
        public
        inState(_uid, State.Created)
    {   
        require(tasks[_uid].promoter != msg.sender);
        tasks[_uid].hunters.push(msg.sender);
        tasks[_uid].reasonHashs.push(_reasonHashs);
    }
    
    //金主取消任务
    function cancelTask(uint _uid)
        public
        inState(_uid, State.Created)
        onlyPromoter(_uid)
    {
        token.transfer(msg.sender, tasks[_uid].bonus+tasks[_uid].bonus/2);
        tasks[_uid].state = State.Cancelled;
    }
    
    //金主确认猎人A
    function confirmHunter(uint _uid, address a)
        public
        inState(_uid, State.Created)
        onlyPromoter(_uid)
    {
        tasks[_uid].hunterA = a;
        tasks[_uid].taskStart = now;
        tasks[_uid].state = State.Confirmed;
    }
    
    //猎人A提交任务
    function hunterAFinished(uint _uid)
        public
        inTime(_uid)
        inState(_uid, State.Confirmed)
        onlyhunterA(_uid)
    {
        tasks[_uid].taskStart = now;
        tasks[_uid].state = State.HunterFinished;
    }
    
    //猎人A超时未提交任务
    function hunterAOutOfTime(uint _uid)
        public
        outOfTime(_uid)
        onlyPromoter(_uid)
    {
        token.transfer(msg.sender, tasks[_uid].bonus+tasks[_uid].bonus/2);
        tasks[_uid].state = State.HunterOutOfTime;
    }
    
    //金主确认任务完成
    function promoterFinished(uint _uid)
        public
        inTime(_uid)
        inState(_uid, State.HunterFinished)
        onlyPromoter(_uid)
    {
        token.transfer(msg.sender, tasks[_uid].bonus/2);
        token.transfer(tasks[_uid].hunterA, tasks[_uid].bonus);
        tasks[_uid].state = State.Promoterfinished;
    }
    
    //金主退回任务
    function taskFallback(uint _uid)
        public
        inTime(_uid)
        inState(_uid, State.HunterFinished)
        onlyPromoter(_uid)
    {
        tasks[_uid].taskStart = now;
        tasks[_uid].state = State.Confirmed;
    }
    
    //金主超时未确认任务
    function promoterOutOfTime(uint _uid)
        public
        outOfTime(_uid)
        inState(_uid, State.HunterFinished)
        onlyhunterA(_uid)
    {
        token.transfer(msg.sender, tasks[_uid].bonus);
        tasks[_uid].state = State.PromoterOutOfTime;
    }
    
    //获取任务信息
    function getTask(uint _uid) 
        public 
        view
        returns (TaskMessage memory) 
    {
        return (tasks[_uid]);
    }
}

合约代码细节在这,有兴趣的可以参考。