{"content":{"title":"基于solidity的抢红包代码","body":"# 基于[solidity](https:\/\/learnblockchain.cn\/article\/567)的抢红包代码\r\n\r\n## 1.实现功能\r\n1. 发红包人可以设置红包的口令，类型，最多抢红包人数和红包有效时间。\r\n1. 可以查看某个人的某个红包当前剩余的钱。\r\n1. 可以查看当前所有红包剩余的钱。\r\n1. 可以查看当前红包中还有钱的对应的所有发钱包人的地址。\r\n1. 可以查看某个红包的抢红包结果。\r\n1. 可以查看某个人（地址）在某个发红包人发的某个红包中抢到了多少钱。\r\n1. 一个人可以发送多个红包，每个人对同一个红包只能够抢一次。\r\n1. 好友功能，只有红包拥有者的好友能够抢红包。\r\n1. 红包需要设置有效期，有效期内好友能够抢红包，有效期过后红包的拥有者能够撤回红包(仅仅在红包的超过有效期后，红包拥有者能够撤回红包)。\r\n1. 红包合约同时支持存在多个红包，并且任意的人能够调用红包合约不断新添加红包，每个红包对应自己的口令，抢红包的人需要输入该口令才能抢红包。\r\n1. 支持平分和随机分红包。\r\n## 2.原文链接\r\n题目参考：https:\/\/blog.csdn.net\/weixin_44858076\/article\/details\/109603051\r\n\r\n## 3.solidity代码\r\n\r\n```js\r\n\/\/ SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.4;\r\n\r\n\r\ncontract red_envelope {\r\n\r\n    struct redbag {\r\n        \r\n        uint256 amount;\r\n        uint256 leixing;\r\n        uint256 maxnum;\r\n        uint256 time;\r\n        uint256 left_money;\r\n        bytes32 kouling;\r\n        address sender;\r\n        address[] qiang;\r\n    }\r\n    \r\n    mapping (address => uint256) countNum;\r\n    mapping (address => mapping(uint256 => redbag)) public whosredbag;\r\n    \r\n    event Fahongbao(address indexed _sender,uint256 _amount,uint256 _maxnum);\r\n    event BeFriend(address _mine,address _friend);\r\n    event GetRed(address indexed _mine,address _sender,uint256 _whichRB,uint256 _amount);\r\n    event GetRealse(address _sender,uint256 _leftRed,uint256 _nowTime);\r\n    \r\n    \r\n    mapping (address => address[]) friend;\r\n\r\n    function beFriend(address _friend) public{\r\n        require(!isFriend(_friend,msg.sender),\"already friend\");\r\n        friend[msg.sender].push(_friend);\r\n        emit BeFriend(msg.sender,_friend);\r\n    }\r\n    \r\n    function  _countNum(address _Addr) internal returns(uint256 _whichRB){\r\n        countNum[_Addr] += 1;\r\n        _whichRB = countNum[_Addr];\r\n        return _whichRB;\r\n    }\r\n\r\n    function getRealse(address _leftRed,uint256 _whichRB) public returns(bool) {\r\n        redbag storage _newSender = whosredbag[_leftRed][_whichRB];\r\n        require(msg.sender == _newSender.sender,\"you are not the owner\");\r\n        require(_newSender.time < block.timestamp,\"time isn't out\");\r\n        uint256 _amount = _newSender.left_money;\r\n        _newSender.left_money -= _amount;\r\n        (bool success,) = payable(msg.sender).call{value:_amount}(\"\");\r\n        emit GetRealse(_newSender.sender,_amount,block.timestamp);\r\n        return success;\r\n    }\r\n\r\n    function fahongbao(\r\n        uint256 _maxnum,\r\n        uint256 _time,\r\n        bytes32 _kouling,\r\n        uint256 _leixing\r\n\r\n    ) public payable\r\n    {\r\n        redbag storage _newSender = whosredbag[msg.sender][_countNum(msg.sender)];\r\n        uint256 _nowTime = block.timestamp;\r\n        _newSender.time = _time + _nowTime;\r\n        _newSender.kouling = _kouling;\r\n        _newSender.amount = msg.value;\r\n        _newSender.sender = msg.sender;\r\n        _newSender.maxnum = _maxnum;\r\n        _newSender.leixing = _leixing;\r\n        _newSender.left_money = msg.value;\r\n        emit Fahongbao(_newSender.sender,_newSender.amount,_newSender.maxnum);\r\n    }\r\n\r\n    \/\/ 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4\r\n    \/\/ 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2\r\n    \/\/ 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db\r\n    \/\/ 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB\r\n    function kouling(string memory _kouling) public pure returns(bytes32 result){\r\n        assembly{\r\n            result := mload(add(_kouling,32))\r\n         }\r\n    }\r\n\r\n    function getRed(address _who,bytes32 _kouling,uint256 _whichRB) public returns(bool)  {\r\n        require(isFriend(msg.sender,_who),\"not friend\");\r\n        redbag storage _newSender = whosredbag[_who][_whichRB];\r\n        require(_kouling == _newSender.kouling);\r\n        require(_newSender.time > block.timestamp,\"time is out\");\r\n        require(_isqiang(_who,_whichRB));\r\n        if(_newSender.qiang.length == _newSender.maxnum - 1){\r\n            uint256 _amount = _newSender.left_money;\r\n            _newSender.qiang.push(msg.sender);\r\n            _newSender.left_money -= _amount;\r\n            (bool success,) = payable(msg.sender).call{value:_amount}(\"\");\r\n            emit GetRed(msg.sender,_newSender.sender,_whichRB,_amount);\r\n            return success;\r\n        }\r\n        else{uint256 _amount = _perValue(_who,_newSender.leixing,_whichRB);\r\n            _newSender.qiang.push(msg.sender);\r\n            _newSender.left_money -= _amount;\r\n            (bool success,) = payable(msg.sender).call{value:_amount}(\"\");\r\n            emit GetRed(msg.sender,_newSender.sender,_whichRB,_amount);\r\n            return success;\r\n        }\r\n\r\n\r\n    }\r\n\r\n    function _isqiang(address _who,uint256 _whichRB) internal view returns(bool restult) {\r\n        redbag memory _newSender = whosredbag[_who][_whichRB];\r\n        for(uint256 i = 0; i < _newSender.qiang.length;i ++){\r\n            require(msg.sender != _newSender.qiang[i],\"you have already done this\");\r\n            }\r\n        return true;\r\n    }\r\n\r\n    function isFriend(address _mine,address _owner) internal view returns(bool result) {\r\n        for(uint256 i = 0; i < friend[_owner].length;i ++){\r\n            if(_mine == friend[_owner][i]){\r\n                result = true;\r\n            }\r\n        }\r\n        return result;\r\n           \r\n    }\r\n\r\n    function _perValue(address _owner,uint256 _type,uint256 _whichRB) internal view returns(uint256 restult) {\r\n        require(_type < 2,\"_type should be 1 or 0\");\r\n        redbag memory _newSender = whosredbag[_owner][_whichRB];\r\n        uint256 _amount = _newSender.amount \/ _newSender.maxnum;\r\n        if(_type == 1){\r\n            return restult = _amount;\r\n        }\r\n        else if(_type == 0){\r\n            return restult = (_random() * _amount) \/ 50 ;\r\n        }\r\n    }\r\n\r\n    function _random() internal view returns(uint256 restult){\r\n        bytes32 randomBytes = keccak256(abi.encodePacked(block.number, msg.sender, blockhash(block.timestamp-1)));\r\n        return restult = (uint(randomBytes) % 100);\r\n    }\r\n}\r\n```\r\n\r\n\r\n## 4.总结\r\n本人为代码小白（刚开始学solidity，求交流和学习途径）+蹩脚英语，目前随机数采用很简单粗暴的途径，也没有对uint256溢出问题进行保护，代码也没有完全参考题目，欢迎各位对代码进行测试，反应存在问题，一起学习交流，谢谢！"},"author":{"user":"https:\/\/learnblockchain.cn\/people\/3498","address":null},"history":"QmeuHdNNMEwFV8ezXnWEJ3TbGdjCqg1oLbVpzVGLKhWcQi","timestamp":1665216574,"version":1}