Skip to content

Commit

Permalink
More strict range checks in Merkle proofs, croupier modifier on bet s…
Browse files Browse the repository at this point in the history
…ettlement.
  • Loading branch information
dice2-win committed Sep 7, 2018
1 parent 86217b3 commit b0a0412
Showing 1 changed file with 24 additions and 10 deletions.
34 changes: 24 additions & 10 deletions Dice2Win.sol
@@ -1,8 +1,8 @@
pragma solidity ^0.4.24;

// * dice2.win - fair games that pay Ether. Version 4.
// * dice2.win - fair games that pay Ether. Version 5.
//
// * Ethereum smart contract, deployed at 0xD1CEeeeee8aF2791fC928beFfB0FFaC3387850DE.
// * Ethereum smart contract, deployed at 0xD1CEeeeee83F8bCF3BEDad437202b6154E9F5405.
//
// * Uses hybrid commit-reveal + block hash random number generation that is immune
// to tampering by players, house and miners. Apart from being fully transparent,
Expand Down Expand Up @@ -106,6 +106,9 @@ contract Dice2Win {
// Mapping from commits to all currently active & processed bets.
mapping (uint => Bet) bets;

// Croupier account.
address public croupier;

// Events that are issued to make statistic recovery easier.
event FailedPayment(address indexed beneficiary, uint amount);
event Payment(address indexed beneficiary, uint amount);
Expand All @@ -118,6 +121,7 @@ contract Dice2Win {
constructor () public {
owner = msg.sender;
secretSigner = DUMMY_ADDRESS;
croupier = DUMMY_ADDRESS;
}

// Standard modifier on methods invokable only by contract owner.
Expand All @@ -126,6 +130,12 @@ contract Dice2Win {
_;
}

// Standard modifier on methods invokable only by contract owner.
modifier onlyCroupier {
require (msg.sender == croupier, "OnlyCroupier methods called by non-croupier.");
_;
}

// Standard contract ownership transfer implementation,
function approveNextOwner(address _nextOwner) external onlyOwner {
require (_nextOwner != owner, "Cannot approve current owner.");
Expand All @@ -147,6 +157,11 @@ contract Dice2Win {
secretSigner = newSecretSigner;
}

// Change the croupier address.
function setCroupier(address newCroupier) external onlyOwner {
croupier = newCroupier;
}

// Change max bet reward. Setting this to zero effectively disables betting.
function setMaxProfit(uint _maxProfit) public onlyOwner {
require (_maxProfit < MAX_AMOUNT, "maxProfit should be a sane number.");
Expand Down Expand Up @@ -265,12 +280,11 @@ contract Dice2Win {
bet.gambler = msg.sender;
}

// Settlement transaction - can in theory be issued by anyone, but is designed to be
// handled by the dice2.win croupier bot. To settle a bet with a specific "commit",
// settleBet should supply a "reveal" number that would Keccak256-hash to
// This is the method used to settle 99% of bets. To process a bet with a specific
// "commit", settleBet should supply a "reveal" number that would Keccak256-hash to
// "commit". "blockHash" is the block hash of placeBet block as seen by croupier; it
// is additionally asserted to prevent changing the bet outcomes on Ethereum reorgs.
function settleBet(uint reveal, bytes32 blockHash) external {
function settleBet(uint reveal, bytes32 blockHash) external onlyCroupier {
uint commit = uint(keccak256(abi.encodePacked(reveal)));

Bet storage bet = bets[commit];
Expand All @@ -290,7 +304,7 @@ contract Dice2Win {
// is different because of Ethereum chain reorg. We supply a full merkle proof of the
// placeBet transaction receipt to provide untamperable evidence that uncle block hash
// indeed was present on-chain at some point.
function settleBetUncleMerkleProof(uint reveal, uint40 canonicalBlockNumber) external {
function settleBetUncleMerkleProof(uint reveal, uint40 canonicalBlockNumber) external onlyCroupier {
// "commit" for bet settlement can only be obtained by hashing a "reveal".
uint commit = uint(keccak256(abi.encodePacked(reveal)));
Expand Down Expand Up @@ -476,7 +490,7 @@ contract Dice2Win {
}

assembly { shift := and(calldataload(sub(offset, 28)), 0xffff) }
require (shift < blobLength, "Shift bounds check.");
require (shift + 32 <= blobLength, "Shift bounds check.");

offset += 4;
assembly { hashSlot := calldataload(add(offset, shift)) }
Expand All @@ -497,7 +511,7 @@ contract Dice2Win {
uint scratchBuf2 = scratchBuf1 + uncleHeaderLength;
uint unclesLength; assembly { unclesLength := and(calldataload(sub(offset, 28)), 0xffff) }
uint unclesShift; assembly { unclesShift := and(calldataload(sub(offset, 26)), 0xffff) }
require (unclesShift < unclesLength, "Shift bounds check.");
require (unclesShift + uncleHeaderLength <= unclesLength, "Shift bounds check.");

offset += 6;
assembly { calldatacopy(scratchBuf2, offset, unclesLength) }
Expand All @@ -512,7 +526,7 @@ contract Dice2Win {
blobLength := and(calldataload(sub(offset, 30)), 0xffff)
shift := and(calldataload(sub(offset, 28)), 0xffff)
}
require (shift < blobLength, "Shift bounds check.");
require (shift + 32 <= blobLength, "Shift bounds check.");

offset += 4;
assembly { hashSlot := calldataload(add(offset, shift)) }
Expand Down

1 comment on commit b0a0412

@twbjx
Copy link

@twbjx twbjx commented on b0a0412 May 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wanna to know that how the jackpot number was calculated,please

Please sign in to comment.