区块链夺宝合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | 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 ]); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构