整体思路:
代码在最下面
- one、two、three:用于存储猜大小结果的三个随机数;
- four:用于存储三个随机数的和,即猜大小结果;
- win、lose:用于存储赢家和输家的地址;
- owner:合约拥有者的地址;
- outcome:用于存储猜大小结果的字符串,值为"big"或"small";
- values:存储猜大小参与者所下注的字符串;
- or:用于判断合约是否开启的布尔变量;
- possess:用于存储每个字符串对应的下注者的地址。
合约中包含以下函数:
- open():开启猜大小合约,需要发送10ETH作为合约保证金;
- _QP():参与猜大小,需要发送10ETH作为下注金额。下注时需要传入一个字符串参数,值为"big"或"small",代表参与者的下注;
- re():进行猜大小。该函数会生成三个随机数,并将它们相加得到猜大小结果。如果结果大于5,则outcome为"big",否则为"small"。然后会遍历values数组,将猜大小结果与参与者的下注做比较,将胜者的地址放入win数组,将失败者的地址放入lose数组。最后,将奖池平均分配给胜者,并将剩余的保证金归还给合约拥有者。
pragma solidity ^0.8.7;
contract Gts{
uint256 one;
uint256 two;
uint256 three;
uint256 public four;
address[] win;
address[] lose;
address owner;
string public outcome;
string[] public values;
bool or;
mapping (string => address) private possess;
modifier cat{
require(or == true,"not open");
require(msg.value == 10 ether,"not");
_;
}
function open() public payable {
require(msg.value == 10,"not money");
owner = msg.sender;
or = true;
}
function _QP(string memory value)public payable cat{
bytes32 Big = keccak256(abi.encodePacked("big"));
bytes32 Small = keccak256(abi.encodePacked("small"));
bytes32 Value = keccak256(abi.encodePacked(value));
require(Value == Big ||Value == Small,"errorB");
possess[value] = msg.sender;
values.push(value);
}
function re() public payable{
uint256 _kec = uint256((keccak256(abi.encodePacked(block.timestamp,msg.sender,values[1],values[3],values[4]))))%100000;
uint256 kec = uint256((keccak256(abi.encodePacked(block.timestamp,msg.sender,values[1],values[3],values[4],_kec))))%10;
one = uint256(keccak256(abi.encodePacked(values[kec],block.timestamp)))%10;
two = uint256(keccak256(abi.encodePacked(block.prevrandao,block.timestamp,one,values[kec],_kec)))%10;
three = uint256(keccak256(abi.encodePacked(block.prevrandao,block.timestamp,one,two,values[kec])))%10;
four = (one + two + three)%10;
if(four > 5){
outcome = 'big';
}else{
outcome = 'small';
}
for(uint256 i; i < values.length; i++){
if(keccak256(abi.encodePacked(values[i])) == keccak256(abi.encodePacked(outcome))){
win.push(possess[values[i]]);
}else{
lose.push(possess[values[i]]);
}
}
uint256 pel = win.length;
uint256 random = address(this).balance/pel;
for(uint256 i; i < win.length; i++){
payable(win[i]).transfer(random/10);
payable(owner).transfer(address(this).balance);
}
}
}
.注:这个合约的随机数虽然经过几层套,但还是可预测的,安全性还是比较低,此外这个合约至少需要五位账户参与,想要更改可以去随机数处将数组索引改小一点。