zoukankan      html  css  js  c++  java
  • 区块链夺宝合约

    pragma solidity ^0.4.23;
    
    /**
     * Math operations with safety checks
     */
    library SafeMath {
      function mul(uint a, uint b) internal returns (uint) {
        uint c = a * b;
        assert(a == 0 || c / a == b);
        return c;
      }
    
      function div(uint a, uint b) internal returns (uint) {
        // assert(b > 0); // Solidity automatically throws when dividing by 0
        uint c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return c;
      }
    
      function sub(uint a, uint b) internal returns (uint) {
        assert(b <= a);
        return a - b;
      }
    
      function add(uint a, uint b) internal returns (uint) {
        uint c = a + b;
        assert(c >= a);
        return c;
      }
    
      function max64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a >= b ? a : b;
      }
    
      function min64(uint64 a, uint64 b) internal constant returns (uint64) {
        return a < b ? a : b;
      }
    
      function max256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a >= b ? a : b;
      }
    
      function min256(uint256 a, uint256 b) internal constant returns (uint256) {
        return a < b ? a : b;
      }
    
      function assert(bool assertion) internal {
        if (!assertion) {
          throw;
        }
      }
    }
    
    interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }
    
    contract TokenERC20 {
    
        using SafeMath for uint256;
        // Public variables of the token
        string public name;
        string public symbol;
        uint8 public decimals = 18;
        // 18 decimals is the strongly suggested default, avoid changing it
        uint256 public totalSupply;
    
        // This creates an array with all balances
        mapping (address => uint256) public balanceOf;
        mapping (address => mapping (address => uint256)) public allowance;
    
        // This generates a public event on the blockchain that will notify clients
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        // This notifies clients about the amount burnt
        event Burn(address indexed from, uint256 value);
    
        /**
         * Constructor function
         *
         * Initializes contract with initial supply tokens to the creator of the contract
         */
        function TokenERC20(
            uint256 initialSupply,
            string tokenName,
            string tokenSymbol
        ) public {
            totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
            balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
            name = tokenName;                                   // Set the name for display purposes
            symbol = tokenSymbol;                               // Set the symbol for display purposes
        }
    
        /**
         * Internal transfer, only can be called by this contract
         */
        function _transfer(address _from, address _to, uint _value) internal {
            // Prevent transfer to 0x0 address. Use burn() instead
            require(_to != 0x0);
            // Check if the sender has enough
            require(balanceOf[_from] >= _value);
            // Check for overflows
            require(balanceOf[_to] + _value >= balanceOf[_to]);
            // Save this for an assertion in the future
            uint previousBalances = balanceOf[_from] + balanceOf[_to];
            // Subtract from the sender
            balanceOf[_from] -= _value;
            // Add the same to the recipient
            balanceOf[_to] += _value;
            emit Transfer(_from, _to, _value);
            // Asserts are used to use static analysis to find bugs in your code. They should never fail
            assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
        }
        
        function onechance_transfer(address _to, uint _value) public {
             _transfer(tx.origin,_to, _value);
        }
    
        /**
         * Transfer tokens
         *
         * Send `_value` tokens to `_to` from your account
         *
         * @param _to The address of the recipient
         * @param _value the amount to send
         */
        function transfer(address _to, uint256 _value) public {
            _transfer(msg.sender, _to, _value);
        }
    
        /**
         * Transfer tokens from other address
         *
         * Send `_value` tokens to `_to` on behalf of `_from`
         *
         * @param _from The address of the sender
         * @param _to The address of the recipient
         * @param _value the amount to send
         */
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
            require(_value <= allowance[_from][msg.sender]);     // Check allowance
            allowance[_from][msg.sender] -= _value;
            _transfer(_from, _to, _value);
            return true;
        }
    
        /**
         * Set allowance for other address
         *
         * Allows `_spender` to spend no more than `_value` tokens on your behalf
         *
         * @param _spender The address authorized to spend
         * @param _value the max amount they can spend
         */
        function approve(address _spender, uint256 _value) public
            returns (bool success) {
            allowance[msg.sender][_spender] = _value;
            return true;
        }
    
        /**
         * Set allowance for other address and notify
         *
         * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it
         *
         * @param _spender The address authorized to spend
         * @param _value the max amount they can spend
         * @param _extraData some extra information to send to the approved contract
         */
        function approveAndCall(address _spender, uint256 _value, bytes _extraData)
            public
            returns (bool success) {
            tokenRecipient spender = tokenRecipient(_spender);
            if (approve(_spender, _value)) {
                spender.receiveApproval(msg.sender, _value, this, _extraData);
                return true;
            }
        }
    
        /**
         * Destroy tokens
         *
         * Remove `_value` tokens from the system irreversibly
         *
         * @param _value the amount of money to burn
         */
        function burn(uint256 _value) public returns (bool success) {
            require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
            balanceOf[msg.sender] -= _value;            // Subtract from the sender
            totalSupply -= _value;                      // Updates totalSupply
            emit Burn(msg.sender, _value);
            return true;
        }
    
        /**
         * Destroy tokens from other account
         *
         * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
         *
         * @param _from the address of the sender
         * @param _value the amount of money to burn
         */
        function burnFrom(address _from, uint256 _value) public returns (bool success) {
            require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
            require(_value <= allowance[_from][msg.sender]);    // Check allowance
            balanceOf[_from] -= _value;                         // Subtract from the targeted balance
            allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
            totalSupply -= _value;                              // Update totalSupply
            emit Burn(_from, _value);
            return true;
        }
    }
    
    contract OneChance {
       
        using SafeMath for uint;
        address public sponsor;
        
        modifier onlySponsor() {
            if (msg.sender != sponsor) throw;
            _;
        }
        
        event PostGoods(uint goodsId, string goodsUuid); // 商品发布成功通知:已发布多少件商品(商品编号),商品uuid编号
        event DelGoods(uint goodsId,bool isActive);//删除商品事件:商品编号,商品状态(true代表正常,false代表删除)
        event BuyChance(address consumer,uint goodsId, uint chanceStartId, uint chanceEndId); // 购买Chance成功通知:购买者地址;商品Id,购买chance获得的起始编号;购买chance获得的终止编号
        event NotifySubmitPlaintext(uint goodsId); // 售磬通知:商品编号
        event NotifyWinnerResult(uint goodsId, uint winnerId, address winnerAddr);//中奖通知:商品编号;获奖者编号;获奖者地址
       
        // 稳定币合约地址
        TokenERC20 public stableCoin;
        
        // 商品
        struct Goods {
            string name; // 奖品名称
            uint256 amt; // 奖品价格
            string description; // 奖品描述
            bool isActive; //商品状态,true代表商品可以购买查看,false代表商品已删除
            uint256 winnerId; // 中奖用户Id=获奖算法结果%(amt/stableCoinPrice)/+1 ,用户id从1开始,winnerId=0说明还没有开奖
            address[] consumers; // 购买用户列表,index+1=用户Id,存储内容为压缩地址uid
     		TokenERC20 otherCoin; // 其他币合约地址
            uint256 stableCoinPrice; // 购买一个chance需要的稳定币
            uint256 stableAndOtherCoinPrice; //稳定币与其它币组合购买,不使用值为0 (需要稳定币)
            uint256 otherCoinPrice; //稳定币与其它币组合购买,不使用值为0 (需要其他币,因为是方案2,所以如果otherCoinPrice的值不为0)
        }
        
        // 商品列表
        Goods[] public goodses;
       
        // 初始化,将合约创建者设置为主办方,设置稳定币地址
        function OneChance(address _stableCoin){
            sponsor = msg.sender;
            stableCoin = TokenERC20(_stableCoin);
        }
        
        // 发布奖品,只有主办方可以调用,主办方用 uuid确定多笔发布奖品操作具体哪一个奖品发布成功
        function postGoods(string _name, uint256 _amt, string _description,uint256 _stableCoinPrice,address _otherCoin,uint256 _stableAndOtherCoinPrice, uint256 _otherCoinPrice,string uuid) public onlySponsor {
            Goods memory goods;
            goods.name = _name;
            goods.amt = _amt;
            goods.description = _description;
            goods.isActive = true;
            goods.stableCoinPrice = _stableCoinPrice;
            if(_otherCoinPrice != 0){
             	goods.otherCoin = TokenERC20(_otherCoin);
            	goods.stableAndOtherCoinPrice = _stableAndOtherCoinPrice;
            	goods.otherCoinPrice = _otherCoinPrice;
            }
            goodses.push(goods);
            // 通知主办方发布成功(事件)
            emit PostGoods(goodses.length, uuid);
        }
        
        //已发布商品数目
        function topGoodsId() public view returns (uint) {
            return goodses.length;
        }
        
        //删除商品
         function delGoodsById(uint _goodsId) public onlySponsor {
             Goods goods = goodses[_goodsId-1];
             goods.isActive = false;
             emit DelGoods(_goodsId,false);
        }
        
        // 查询奖品信息
        function goods(uint256 _goodsId) public view returns (string name, uint256 amt, string description, bool isActive,uint consumersLength,  uint256 winnerId, address winnerAddr, uint256 stableCoinPrice, uint256 stableAndOtherCoinPrice, uint256 otherCoinPrice) {
            Goods goods = goodses[_goodsId-1];
            name = goods.name;
            amt = goods.amt;
            description = goods.description;
            isActive = goods.isActive;
            consumersLength = goods.consumers.length;
            winnerId = goods.winnerId;
            if (winnerId!=0) {
                // 用户Id-1得到数组下标,然后用地址压缩合约查询uid得到用户实际地址
                winnerAddr = goods.consumers[winnerId-1];
            }
            stableCoinPrice = goods.stableCoinPrice;
            stableAndOtherCoinPrice = goods.stableAndOtherCoinPrice;
            otherCoinPrice = goods.otherCoinPrice;
        }
        
        // 查询用户地址
        function user(uint256 _goodsId, uint256 _userId) public view returns (address userAddr) {
            Goods goods = goodses[_goodsId-1];
            userAddr = goods.consumers[_userId-1];
        }
       
        // 购买chance
        function buyChance(uint256 _goodsId, uint256 _quantity1, uint256 _quantity2) public {
            if (_quantity1+_quantity2 <= 0) throw;
            Goods goods = goodses[_goodsId-1];
            if (goods.isActive == false ) throw;
            if ((goods.consumers.length + _quantity1 + _quantity2) * goods.stableCoinPrice > goods.amt) throw; 
            stableCoin.onechance_transfer(sponsor,_quantity1*goods.stableCoinPrice+_quantity2*goods.stableAndOtherCoinPrice);
            if (_quantity2 != 0){
                goods.otherCoin.onechance_transfer(sponsor,_quantity2*goods.otherCoinPrice);
            }
            // 通知用户购买成功,用户需要记录自己的 goodsId+beginUserId
            emit BuyChance(tx.origin, _goodsId, goods.consumers.length+1,goods.consumers.length+_quantity1+_quantity2);
            // 记录商品的购买用户
            for (uint256 i=0; i<_quantity1 +_quantity2; i++) {
                goods.consumers.push(tx.origin);
            }
            // 如果商品 Chance 已售罄,通知购买用户提交原始随机数以生成中奖用户
            if (goods.consumers.length == goods.amt/goods.stableCoinPrice) {
                emit NotifySubmitPlaintext(_goodsId);
            }
        }
        
        // 计算获奖用户,取幸运区块号签名(哈希值)的最后8位,转成10进制数字
        function submitPlaintext(uint256 hashNum,uint256 _goodsId) public {
            Goods goods = goodses[_goodsId-1];
            goods.winnerId = hashNum % (goods.amt/goods.stableCoinPrice) +1;
            //通知用户中奖结果
           	emit NotifyWinnerResult(_goodsId, goods.winnerId,goods.consumers[goods.winnerId-1]);
        }
    
    }
    

      

  • 相关阅读:
    微信视频号里的视频如何保存下来呢?
    jQuery实现平面图区域标记
    npm安装教程 yarn 基本安装和使用
    VitePress :VuePress 下一代建站工具
    基于CentOS的ECS实例实现OSS反向代理
    备份MySQL数据库到七牛云的shell脚本
    ShedLock 解决分布式结构下定时任务重复执行问题
    linux清除日志和文件缓存
    Communications link failure:The last packet successfully received from the server was 0 millisecond ago
    CentOS7安装nodeJs
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/9856581.html
Copyright © 2011-2022 走看看