Advertisement
Guest User

Untitled

a guest
May 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.74 KB | None | 0 0
  1. pragma solidity 0.4.25; /*
  2.  
  3.  
  4. _______ _____ ____ _ _ _ _ _____ _
  5. |__ __| __ \ / __ \| \ | | | (_) | __ \ | |
  6. | | | |__) | | | | \| | |_ ___ _ __ _ __ _ | |__) | __ ___ ___ ___ _ __ | |_ ___
  7. | | | _ /| | | | . ` | __/ _ \| '_ \| |/ _` | | ___/ '__/ _ \/ __|/ _ \ '_ \| __/ __|
  8. | | | | \ \| |__| | |\ | || (_) | |_) | | (_| | | | | | | __/\__ \ __/ | | | |_\__ \
  9. |_| |_| \_\\____/|_| \_|\__\___/| .__/|_|\__,_| |_| |_| \___||___/\___|_| |_|\__|___/
  10. | |
  11. |_|
  12.  
  13.  
  14. ██╗ ██╗██╗ ████████╗██╗███╗ ███╗ █████╗ ████████╗███████╗ ██████╗ ██╗ ██████╗███████╗
  15. ██║ ██║██║ ╚══██╔══╝██║████╗ ████║██╔══██╗╚══██╔══╝██╔════╝ ██╔══██╗██║██╔════╝██╔════╝
  16. ██║ ██║██║ ██║ ██║██╔████╔██║███████║ ██║ █████╗ ██║ ██║██║██║ █████╗
  17. ██║ ██║██║ ██║ ██║██║╚██╔╝██║██╔══██║ ██║ ██╔══╝ ██║ ██║██║██║ ██╔══╝
  18. ╚██████╔╝███████╗██║ ██║██║ ╚═╝ ██║██║ ██║ ██║ ███████╗ ██████╔╝██║╚██████╗███████╗
  19. ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝
  20.  
  21.  
  22.  
  23. ----------------------------------------------------------------------------------------------------
  24.  
  25. === MAIN FEATURES ===
  26. => Higher degree of control by owner - safeguard functionality
  27. => SafeMath implementation
  28. => Random Number generation using: block hash, block number, user address, bet amount, bet type and user-provided seed
  29. => Dividend payout
  30. => Sidebet Jackpot
  31. => Topia Freeze Tiers
  32. => Referral Tiers
  33. => Community Audit by Bug Bounty program
  34.  
  35.  
  36. ------------------------------------------------------------------------------------------------------
  37. Copyright (c) 2019 onwards TRONtopia Inc. ( https://trontopia.co )
  38. Contract designed by Jesse Busman ( jesse@jesbus.com )
  39. and by EtherAuthority ( https://EtherAuthority.io )
  40. ------------------------------------------------------------------------------------------------------
  41. */
  42.  
  43.  
  44. //*******************************************************************//
  45. //------------------------ SafeMath Library -------------------------//
  46. //*******************************************************************//
  47. library SafeMath
  48. {
  49. function mul(uint256 a, uint256 b) internal pure returns (uint256 c)
  50. {
  51. if (a == 0) { return 0; }
  52. c = a * b;
  53. require(c / a == b);
  54. }
  55.  
  56. function div(uint256 a, uint256 b) internal pure returns (uint256)
  57. {
  58. return a / b;
  59. }
  60.  
  61. function sub(uint256 a, uint256 b) internal pure returns (uint256)
  62. {
  63. require(b <= a);
  64. return a - b;
  65. }
  66.  
  67. function add(uint256 a, uint256 b) internal pure returns (uint256 c)
  68. {
  69. c = a + b;
  70. require(c >= a);
  71. }
  72. }
  73.  
  74.  
  75.  
  76. //*******************************************************************//
  77. //------------------ Contract to Manage Ownership -------------------//
  78. //*******************************************************************//
  79. contract owned
  80. {
  81. address internal owner;
  82. address internal newOwner;
  83.  
  84. event OwnershipTransferred(address indexed _from, address indexed _to);
  85.  
  86. constructor() public {
  87. owner = msg.sender;
  88. }
  89.  
  90. modifier onlyOwner {
  91. require(msg.sender == owner);
  92. _;
  93. }
  94.  
  95. function transferOwnership(address _newOwner) public onlyOwner {
  96. newOwner = _newOwner;
  97. }
  98.  
  99. //the reason for this flow is to protect owners from sending ownership to unintended address due to human error
  100. function acceptOwnership() public {
  101. require(msg.sender == newOwner);
  102. emit OwnershipTransferred(owner, newOwner);
  103. owner = newOwner;
  104. newOwner = address(0);
  105. }
  106. }
  107.  
  108.  
  109.  
  110. //**************************************************************************//
  111. //--------------------- TRONTOPIA CONTRACT INTERFACE ---------------------//
  112. //**************************************************************************//
  113.  
  114. interface TRONtopiaInterface
  115. {
  116. function transfer(address recipient, uint amount) external returns(bool);
  117. function mintToken(address _user, uint256 _tronAmount) external returns(bool);
  118. }
  119.  
  120.  
  121. //**************************************************************************//
  122. //------------------- DIVIDEND CONTRACT INTERFACE --------------------//
  123. //**************************************************************************//
  124.  
  125. interface InterfaceDIVIDEND {
  126. function referrers(address user) external returns(address);
  127. function updateReferrer(address _user, address _referrer) external returns(bool);
  128. function payReferrerBonusOnly(address _user, uint256 _refBonus, uint256 _trxAmount ) external returns(bool);
  129. function payReferrerBonusAndAddReferrer(address _user, address _referrer, uint256 _trxAmount, uint256 _refBonus) external returns(bool);
  130. }
  131.  
  132.  
  133.  
  134. //**************************************************************************//
  135. //--------------------- DICE GAME MAIN CODE STARTS HERE -------------------//
  136. //**************************************************************************//
  137.  
  138. contract TRONtopia_ultimate_dice is owned
  139. {
  140. using SafeMath for uint256;
  141. uint256[] private multipliersData;
  142. address public topiaTokenContractAddress;
  143. address public dividendContractAddress;
  144. uint256 public totalDepositedTRX;
  145. uint256 public totalDepositedIntoJackpot;
  146.  
  147.  
  148. uint256 private constant _yin = 1;
  149. uint256 private constant _yang = 2;
  150. uint256 private constant _bang = 3;
  151. uint256 private constant _zero = 4;
  152. uint256 private constant _odd = 5;
  153. uint256 private constant _even = 6;
  154.  
  155. uint256 private yinMultiplier = 21111;
  156. uint256 private yangMultiplier = 21111;
  157. uint256 private bangMultiplier = 95000;
  158. uint256 private zeroMultiplier = 950000;
  159. uint256 private oddMultiplier = 19000;
  160. uint256 private evenMultiplier = 19000;
  161.  
  162. uint256 public maxBetAmount = 500000;
  163. uint256 public minimumSideBetAmountTRX = 25;
  164. uint256 public minimumMainBetAmountTRX = 10;
  165. uint256 private maxWinDivisibleAmount = 50;
  166.  
  167. // Side bet jackpot
  168. uint256 public sideBetAmountTRXtoQualifyForMaximumJackpot = 1000;
  169. uint256 public sideBetLossPercentageForProgressiveJackpot = 10;
  170. uint256 public maximumPercentageOfJackpotSizeWon = 75;
  171. uint256 public jackpotSizePercentageToDividendPool = 10;
  172. uint256 private sideBetJackpotMaxOdd = 1000000; // 1 Million is highest odd of sidebet jackpot
  173. uint256 private sideBetJackpotFixNumber = 1000; // so the odd to get this number would be 1:1000000
  174.  
  175. bool public systemHalted = false;
  176.  
  177. uint256 private betExpiredBehaviour = 0;
  178. // 0: bet is ignored
  179. // 1: user gets their bet back
  180. // 2: bet is ignored, system is halted
  181. // 3: user gets their bet back, system is halted
  182.  
  183. event BetStarted(bytes32 indexed _betHash, address indexed _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 indexed _blockNumber, uint256[5] _rollIntegerVariables);
  184. event BetFinished(bytes32 indexed _betHash);
  185. event BetExpired(bytes32 betHash, address user, uint256 betAmount);
  186. event BetRefunded(bytes32 indexed _betHash, address indexed _gambler, uint256 _amountRefunded);
  187. event Roll(address indexed user, uint256 _startNumber, uint256 _endNumber, uint256 _winningNumber, uint256 indexed _value, bool indexed result, uint256 timestamp);
  188. event KingTopian(address indexed user, uint256 _prize, uint256 _trxplayed, uint256 timestamp);
  189. event UnluckyBunch(address indexed user, uint256 _loose, uint256 _trxplayed, uint256 timestamp);
  190. event HighRollers(address indexed user, uint256 _startNumber, uint256 _endNumber, uint256 _winningNumber, uint256 _value, uint256 _winamount, bool result, uint256 timestamp);
  191. event RareWins(address indexed user, uint256 _startNumber, uint256 _endNumber, uint256 _winningNumber, uint256 _value, uint256 _winamount, bool result, uint256 timestamp);
  192. event SideBetRolls(address indexed user, uint256 _winningNumber, uint256 _betValue, uint256 winAmount, uint256 sideBet, bool result, uint256 timestamp);
  193. event SideBetJackpot(address indexed winner, uint256 lukyNumber, uint256 jackpotAmount);
  194.  
  195. // Fallback function. It just accepts incoming TRX
  196. function () payable external
  197. {
  198. }
  199.  
  200. constructor() public
  201. {
  202. blockHashes.length = ~uint256(0);
  203. }
  204.  
  205. // setMultiplierData stores multiplier array data in the contract
  206. // [985000,492500,328333,246250,197000,164166,140714,123125,109444,98500,89545,82083,75769,70357,65666,61562,57941,54722,51842,49250,46904,44772,42826,41041,39400,37884,36481,35178,33965,32833,31774,30781,29848,28970,28142,27361,26621,25921,25256,24625,24024,23452,22906,22386,21888,21413,20957,20520,20102,19700,19313,18942,18584,18240,17909,17589,17280,16982,16694,16416,16147,15887,15634,15390,15153,14924,14701,14485,14275,14071,13873,13680,13493,13310,13133,12960,12792,12628,12468,12312,12160,12012,11867,11726,11588,11453,11321,11193,11067,10944,10824,10706,10591,10478,10368,10260,10155]
  207. function setMultiplierData(uint256[] memory data) public onlyOwner returns (string)
  208. {
  209. multipliersData = data;
  210. return "Multiplier Added";
  211. }
  212.  
  213. function setBetExpiredBehaviour(uint256 _betExpiredBehaviour) external onlyOwner
  214. {
  215. betExpiredBehaviour = _betExpiredBehaviour;
  216. }
  217.  
  218. function setSystemHalted(bool _systemHalted) external onlyOwner
  219. {
  220. systemHalted = _systemHalted;
  221. }
  222.  
  223.  
  224.  
  225. struct Bet
  226. {
  227. address gambler;
  228. bytes32 uniqueBetId;
  229. bytes32 userSeed;
  230. uint256 blockNumber;
  231. uint256 startNumber;
  232. uint256 endNumber;
  233. uint256 mainBetTRX;
  234. uint256 sideBetTRX;
  235. uint256 sideBetType;
  236. }
  237.  
  238. mapping(bytes32 => uint256) public unfinishedBetHash_to_timestamp;
  239. mapping(address => bytes32) public user_to_lastBetHash;
  240.  
  241. bytes32[] public blockHashes;
  242.  
  243. uint256 public currentSideBetJackpotSize = 0;
  244.  
  245. uint256 public ownerRakePool;
  246.  
  247. uint256 public ownerRakePerMillion;
  248.  
  249. function storeCertainBlockHashes(uint256[] _blockNumbers) external
  250. {
  251. for (uint256 i=0; i<_blockNumbers.length; i++)
  252. {
  253. uint256 blockNumber = _blockNumbers[i];
  254. bytes32 blockHash = blockhash(blockNumber);
  255. if (blockHash != 0x0 && blockHashes[blockNumber] == 0x0)
  256. {
  257. blockHashes[blockNumber] = blockHash;
  258. }
  259. }
  260. }
  261.  
  262. function storeBlockHashesRange(uint256 _firstBlockNumber, uint256 _lastBlockNumber) public
  263. {
  264. for (uint256 b=_firstBlockNumber; b<=_lastBlockNumber; b++)
  265. {
  266. bytes32 blockHash = blockhash(b);
  267. if (blockHash != 0x0 && blockHashes[b] == 0x0)
  268. {
  269. blockHashes[b] = blockHash;
  270. }
  271. }
  272. }
  273.  
  274. function storeAllRecentBlockHashes() external
  275. {
  276. storeBlockHashesRange(block.number-256, block.number-1);
  277. }
  278.  
  279.  
  280. // Function to finish multiple bets in one transaction
  281. function finishManyBets(address[] _gambler, bytes32[] _uniqueBetId, bytes32[] _userSeed, uint256[] _blockNumber, uint256[5][] _rollIntegerVariables, uint256 _lowLevelGas) external
  282. {
  283. for (uint256 i=0; i<_gambler.length; i++)
  284. {
  285. finishBet(
  286. _gambler[i],
  287. _uniqueBetId[i],
  288. _userSeed[i],
  289. _blockNumber[i],
  290. _rollIntegerVariables[i]
  291. );
  292.  
  293. if (gasleft() < _lowLevelGas)
  294. {
  295. break;
  296. }
  297. }
  298. }
  299.  
  300. // Function to allow a user to finish their previous bet and start a new one in one transaction.
  301. function finishBet_and_startBet(
  302. address _finishBet_gambler,
  303. bytes32 _finishBet_uniqueBetId,
  304. bytes32 _finishBet_userSeed,
  305. uint256 _finishBet_blockNumber,
  306. uint256[5] _finishBet_rollIntegerVariables,
  307.  
  308.  
  309. uint256[5] _startBet_rollIntegerVariables,
  310. address _startBet_referrer,
  311. bytes32 _startBet_userSeed,
  312. bytes32 _startBet_uniqueBetId
  313. ) external payable
  314. {
  315. finishBet(
  316. _finishBet_gambler,
  317. _finishBet_uniqueBetId,
  318. _finishBet_userSeed,
  319. _finishBet_blockNumber,
  320. _finishBet_rollIntegerVariables
  321. );
  322.  
  323. startBet(
  324. _startBet_rollIntegerVariables,
  325. _startBet_referrer,
  326. _startBet_userSeed,
  327. _startBet_uniqueBetId
  328. );
  329. }
  330.  
  331.  
  332.  
  333.  
  334. /**
  335. * uint256[] _rollIntegerVariables array contains:
  336. * _rollIntegerVariables[0] = _startNumber;
  337. * _rollIntegerVariables[1] = _endNumber;
  338. * _rollIntegerVariables[2] = _amount;
  339. * _rollIntegerVariables[3] = _sideBetValue;
  340. * _rollIntegerVariables[4] = _sideBetType;
  341. *
  342. * Side bet types:
  343. * yin = 1
  344. * yang = 2
  345. * bang = 3
  346. * zero = 4
  347. * odd = 5
  348. * even = 6
  349. **/
  350.  
  351. function startBet(uint256[5] _rollIntegerVariables, address _referrer, bytes32 _userSeed, bytes32 _uniqueBetId) payable public returns (bytes32 _newUnfinishedBetHash)
  352. {
  353. require(!systemHalted, "System is halted");
  354.  
  355. // User must have sent the same amount of TRX as his main bet + his sidebet
  356. require(msg.value == (_rollIntegerVariables[2].add(_rollIntegerVariables[3])).mul(1e6), "Invalid msg.value");
  357.  
  358. // The main bet must be at least the minimum main bet
  359. require(_rollIntegerVariables[2] >= minimumMainBetAmountTRX, 'Main bet amount too low');
  360.  
  361. // Prevent bets greater than the maximum bet
  362. require((_rollIntegerVariables[2] + _rollIntegerVariables[3]) <= maxBetAmount, 'Bet amount too large');
  363.  
  364. // Ensure that:
  365. // _rollIntegerVariables[0] >= 0 && _rollIntegerVariables[0] < 100
  366. // _rollIntegerVariables[1] >= 0 && _rollIntegerVariables[1] < 100
  367. // _rollIntegerVariables[0] <= _rollIntegerVariables[1]
  368. // _rollIntegerVariables[1] - _rollIntegerVariables[0] < multipliersData.length
  369. require(_rollIntegerVariables[1] >= _rollIntegerVariables[0] && _rollIntegerVariables[1] < 100, 'End number must be greater than or equal to start number');
  370. require(_rollIntegerVariables[1] - _rollIntegerVariables[0] < multipliersData.length, 'Number range too large');
  371.  
  372. // Validate side bet
  373. if (_rollIntegerVariables[3] > 0)
  374. {
  375. require(_rollIntegerVariables[4] >= 1 && _rollIntegerVariables[4] <= 6, 'Invalid side bet type');
  376. require(_rollIntegerVariables[3] >= minimumSideBetAmountTRX, 'Side bet amount is below the minimum');
  377. }
  378. else
  379. {
  380. require(_rollIntegerVariables[4] == 0, 'Side bet type selected, but no side bet value provided');
  381. }
  382.  
  383. // startBet may not be called by another smart contract
  384. require(msg.sender == tx.origin, 'Caller must not be Contract Address');
  385.  
  386. require(_referrer != msg.sender, 'User cannot refer himself');
  387.  
  388. // If this is the user's first bet...
  389. if (user_to_lastBetHash[msg.sender] == 0x0)
  390. {
  391. // Set their referral address
  392. InterfaceDIVIDEND(dividendContractAddress).updateReferrer(msg.sender, _referrer);
  393. }
  394.  
  395. // Mint tokens depending on how much TRX is received
  396. TRONtopiaInterface(topiaTokenContractAddress).mintToken(msg.sender, msg.value);
  397.  
  398. // Compute the bet hash
  399. _newUnfinishedBetHash = calculateBetHash(
  400. msg.sender,
  401. _uniqueBetId,
  402. _userSeed,
  403. block.number,
  404. _rollIntegerVariables
  405. );
  406.  
  407. // This bet must not already exist
  408. require(unfinishedBetHash_to_timestamp[_newUnfinishedBetHash] == 0, "That bet already exists");
  409.  
  410. // Store the bet hash
  411. unfinishedBetHash_to_timestamp[_newUnfinishedBetHash] = block.timestamp;
  412. user_to_lastBetHash[msg.sender] = _newUnfinishedBetHash;
  413.  
  414. // Store the bet in event
  415. emit BetStarted(_newUnfinishedBetHash, msg.sender, _uniqueBetId, _userSeed, block.number, _rollIntegerVariables);
  416.  
  417. ownerRakePool += (_rollIntegerVariables[2] + _rollIntegerVariables[3]) * ownerRakePerMillion;
  418. }
  419.  
  420. function getBlockHash(uint256 _blockNumber) external view returns (bytes32)
  421. {
  422. return blockhash(_blockNumber);
  423. }
  424. function getBlockNumber() external view returns (uint256)
  425. {
  426. return block.number;
  427. }
  428.  
  429. function createBetObject(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables) private pure returns (Bet memory bet)
  430. {
  431. return Bet({
  432. gambler: _gambler,
  433. uniqueBetId: _uniqueBetId,
  434. userSeed: _userSeed,
  435. blockNumber: _blockNumber,
  436. startNumber: _rollIntegerVariables[0],
  437. endNumber: _rollIntegerVariables[1],
  438. mainBetTRX: _rollIntegerVariables[2],
  439. sideBetTRX: _rollIntegerVariables[3],
  440. sideBetType: _rollIntegerVariables[4]
  441. });
  442. }
  443.  
  444. function calculateBetHash(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables) public pure returns (bytes32)
  445. {
  446. return keccak256(abi.encode(
  447. _gambler,
  448. _uniqueBetId,
  449. _userSeed,
  450. _blockNumber,
  451. _rollIntegerVariables[0],
  452. _rollIntegerVariables[1],
  453. _rollIntegerVariables[2],
  454. _rollIntegerVariables[3],
  455. _rollIntegerVariables[4]
  456. ));
  457. }
  458.  
  459. function calculateBetResult(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables) external view returns (uint256 winningNumber, uint256 mainBetWin, uint256 mainBetProfit, uint256 sideBetWin, uint256 sideBetProfit, uint256 sideBetJackpotWinAmount, uint256 winningNumberForSidebetJackpot)
  460. {
  461. Bet memory bet = createBetObject(
  462. _gambler,
  463. _uniqueBetId,
  464. _userSeed,
  465. _blockNumber,
  466. _rollIntegerVariables
  467. );
  468.  
  469. bytes32 betHash = calculateBetHash(
  470. _gambler,
  471. _uniqueBetId,
  472. _userSeed,
  473. _blockNumber,
  474. _rollIntegerVariables
  475. );
  476.  
  477. return _calculateBetResult(bet, betHash);
  478. }
  479.  
  480.  
  481. function calculateBetResultWithBlockHash(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables, bytes32 _blockHash) external view returns (uint256 winningNumber, uint256 mainBetWin, uint256 mainBetProfit, uint256 sideBetWin, uint256 sideBetProfit, uint256 sideBetJackpotWinAmount, uint256 winningNumberForSidebetJackpot)
  482. {
  483. Bet memory bet = createBetObject(
  484. _gambler,
  485. _uniqueBetId,
  486. _userSeed,
  487. _blockNumber,
  488. _rollIntegerVariables
  489. );
  490.  
  491. bytes32 betHash = calculateBetHash(
  492. _gambler,
  493. _uniqueBetId,
  494. _userSeed,
  495. _blockNumber,
  496. _rollIntegerVariables
  497. );
  498.  
  499. return _calculateBetResultWithBlockHash(bet, betHash, _blockHash);
  500. }
  501.  
  502.  
  503. function _calculateBetResult(Bet memory bet, bytes32 betHash) private view returns (uint256 winningNumber, uint256 mainBetWin, uint256 mainBetProfit, uint256 sideBetWin, uint256 sideBetProfit, uint256 sideBetJackpotWinAmount, uint256 winningNumberForSidebetJackpot)
  504. {
  505. // Fetch the block hash of the block in which the startBet was confirmed
  506. bytes32 blockHash;
  507. if (bet.blockNumber < block.number-256) blockHash = blockHashes[bet.blockNumber];
  508. else blockHash = blockhash(bet.blockNumber);
  509.  
  510. return _calculateBetResultWithBlockHash(bet, betHash, blockHash);
  511. }
  512.  
  513. function _calculateBetResultWithBlockHash(Bet memory bet, bytes32 betHash, bytes32 blockHash) private view returns (uint256 winningNumber, uint256 mainBetWin, uint256 mainBetProfit, uint256 sideBetWin, uint256 sideBetProfit, uint256 sideBetJackpotWinAmount, uint256 winningNumberForSidebetJackpot)
  514. {
  515. // Block hash must be non-zero
  516. require(blockHash != 0x0, "Too late or too early to calculate bet result.");
  517.  
  518. // Generate random number for main bet & side bet
  519. bytes32 _randomSeed = keccak256(abi.encode(blockHash, betHash));
  520. winningNumber = uint256(_randomSeed) % 100;
  521.  
  522. // If there was a sidebet...
  523. if (bet.sideBetTRX > 0)
  524. {
  525. // Generate random number for side bet jackpot
  526. winningNumberForSidebetJackpot = uint256(keccak256(abi.encode(_randomSeed, uint256(1)))) % sideBetJackpotMaxOdd;
  527.  
  528. // If they won the sidebet jackpot...
  529. if (winningNumberForSidebetJackpot == sideBetJackpotFixNumber)
  530. {
  531. // Calculate the jackpot amount won
  532.  
  533. // If the sidebet does not qualify for the full jackpot...
  534. if (bet.sideBetTRX < sideBetAmountTRXtoQualifyForMaximumJackpot)
  535. {
  536. sideBetJackpotWinAmount =
  537. currentSideBetJackpotSize
  538. * maximumPercentageOfJackpotSizeWon / 100
  539. * bet.sideBetTRX / sideBetAmountTRXtoQualifyForMaximumJackpot;
  540. }
  541.  
  542. // If the sidebet does qualify for the full jackpot...
  543. else
  544. {
  545. sideBetJackpotWinAmount =
  546. currentSideBetJackpotSize
  547. * maximumPercentageOfJackpotSizeWon / 100;
  548. }
  549. }
  550.  
  551. // If they did not win the sidebet jackpot...
  552. else
  553. {
  554. sideBetJackpotWinAmount = 0;
  555. }
  556. }
  557.  
  558. // Calculate the amount won from the main bet
  559. if (winningNumber >= bet.startNumber && winningNumber <= bet.endNumber)
  560. {
  561. // rollIntegerVariables[1] - rollIntegerVariables[0] == the amount of winning numbers - 1
  562. mainBetWin = bet.mainBetTRX * multipliersData[bet.endNumber - bet.startNumber] * 100;
  563. mainBetProfit = mainBetWin - (bet.mainBetTRX * 1e6);
  564. }
  565. else
  566. {
  567. mainBetWin = 0;
  568. mainBetProfit = 0;
  569. }
  570.  
  571. // Calculate the amount won from the sidebet
  572. sideBetWin = _calculateSideBetWin(winningNumber, bet.sideBetType, bet.sideBetTRX);
  573. if (sideBetWin > 0)
  574. {
  575. sideBetProfit = sideBetWin - (bet.sideBetTRX * 1e6);
  576. }
  577.  
  578. // Winnings must be limited to the configured fraction of the contract's balance
  579. uint256 maximumProfit = (address(this).balance - currentSideBetJackpotSize - ownerRakePool) / maxWinDivisibleAmount;
  580. if (mainBetProfit + sideBetProfit > maximumProfit)
  581. {
  582. mainBetWin = bet.mainBetTRX * 1e6;
  583. sideBetWin = bet.sideBetTRX * 1e6;
  584. mainBetProfit = 0;
  585. sideBetProfit = 0;
  586. }
  587. }
  588.  
  589.  
  590.  
  591. function finishBet(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables) public
  592. {
  593. require(!systemHalted, "System is halted");
  594.  
  595. Bet memory bet = createBetObject(
  596. _gambler,
  597. _uniqueBetId,
  598. _userSeed,
  599. _blockNumber,
  600. _rollIntegerVariables
  601. );
  602.  
  603. bytes32 betHash = calculateBetHash(
  604. _gambler,
  605. _uniqueBetId,
  606. _userSeed,
  607. _blockNumber,
  608. _rollIntegerVariables
  609. );
  610.  
  611. finishBet(bet, betHash);
  612. }
  613.  
  614. function finishBet(Bet memory bet, bytes32 betHash) private
  615. {
  616. uint256 betTimestamp = unfinishedBetHash_to_timestamp[betHash];
  617.  
  618. // If the bet has already been finished, do nothing
  619. if (betTimestamp == 0) { return; }
  620.  
  621. // If we can't finish this bet yet, do nothing
  622. if (bet.blockNumber >= block.number) { return; }
  623.  
  624. // If the bet has expired...
  625. if (bet.blockNumber < block.number-256 && blockHashes[bet.blockNumber] == 0x0)
  626. {
  627. // Mark bet as finished
  628. unfinishedBetHash_to_timestamp[betHash] = 0;
  629. emit BetExpired(betHash, bet.gambler, (bet.mainBetTRX + bet.sideBetTRX) * 1e6);
  630.  
  631. // User gets their bet back
  632. if (betExpiredBehaviour == 1 || betExpiredBehaviour == 3)
  633. {
  634. bet.gambler.transfer((bet.mainBetTRX + bet.sideBetTRX) * 1e6);
  635. }
  636.  
  637. // System is halted
  638. if (betExpiredBehaviour == 2 || betExpiredBehaviour == 3)
  639. {
  640. systemHalted = true;
  641. }
  642.  
  643. return;
  644. }
  645.  
  646.  
  647.  
  648.  
  649. (uint256 _winningNumber, uint256 mainBetWin, , uint256 sideBetWin, , uint256 sideBetJackpotWinAmount, uint256 sideBetJackpotRandomNumber) = _calculateBetResult(
  650. bet, betHash
  651. );
  652.  
  653.  
  654.  
  655.  
  656.  
  657. // Emit main bet events
  658. emit Roll(bet.gambler, bet.startNumber, bet.endNumber, _winningNumber, bet.mainBetTRX, mainBetWin > 0, betTimestamp);
  659. if (mainBetWin > 0)
  660. {
  661. emit KingTopian(bet.gambler, mainBetWin, bet.mainBetTRX, betTimestamp);
  662.  
  663. // If the main bet was greater than 10000 TRX
  664. if (bet.mainBetTRX > 10000)
  665. {
  666. emit HighRollers(bet.gambler, bet.startNumber, bet.endNumber, _winningNumber, bet.mainBetTRX, mainBetWin, true, betTimestamp);
  667. }
  668.  
  669. // If the amount of winning numbers was <= 5 (5% or less chance to win)
  670. if ((bet.endNumber - bet.startNumber) < 5)
  671. {
  672. emit RareWins(bet.gambler, bet.startNumber, bet.endNumber, _winningNumber, bet.mainBetTRX, mainBetWin, true, betTimestamp);
  673. }
  674. }
  675.  
  676. else
  677. {
  678. emit UnluckyBunch(bet.gambler, bet.mainBetTRX, bet.mainBetTRX, betTimestamp);
  679. }
  680.  
  681.  
  682.  
  683. // Emit side bet events
  684. if (bet.sideBetTRX > 0)
  685. {
  686. emit SideBetRolls(bet.gambler, _winningNumber, bet.sideBetTRX, sideBetWin, bet.sideBetType, sideBetWin > 0, betTimestamp);
  687. }
  688.  
  689.  
  690. // Emit side bet jackpot events
  691. if (sideBetJackpotWinAmount > 0)
  692. {
  693. emit SideBetJackpot(bet.gambler, sideBetJackpotRandomNumber, sideBetJackpotWinAmount);
  694. }
  695.  
  696.  
  697.  
  698.  
  699. // Mark bet as finished
  700. unfinishedBetHash_to_timestamp[betHash] = 0;
  701. emit BetFinished(betHash);
  702.  
  703.  
  704.  
  705.  
  706. // If there was a jackpot win...
  707. if (sideBetJackpotWinAmount > 0)
  708. {
  709. // Add the configured percentage of the jackpot pool to the dividend pool
  710. currentSideBetJackpotSize = currentSideBetJackpotSize.sub(currentSideBetJackpotSize * jackpotSizePercentageToDividendPool / 100);
  711.  
  712. // Decrease the current size of the jackpot by the part they won
  713. currentSideBetJackpotSize = currentSideBetJackpotSize.sub(sideBetJackpotWinAmount);
  714. }
  715.  
  716.  
  717. // If there was a sidebet loss...
  718. if (bet.sideBetTRX > 0 && sideBetWin == 0)
  719. {
  720. currentSideBetJackpotSize = currentSideBetJackpotSize.add(bet.sideBetTRX * 1e6 * sideBetLossPercentageForProgressiveJackpot / 100);
  721. }
  722.  
  723.  
  724.  
  725. // If the user won their main bet, their sidebet or both, their referrer gets payed
  726. if ((mainBetWin > 0 || sideBetWin > 0) && InterfaceDIVIDEND(dividendContractAddress).referrers(bet.gambler) != address(0x0))
  727. {
  728. uint256 referralAmount = 0;
  729. if (mainBetWin > 0) referralAmount += mainBetWin.sub(bet.mainBetTRX * 1e6);
  730. if (sideBetWin > 0) referralAmount += sideBetWin.sub(bet.sideBetTRX * 1e6);
  731.  
  732. // Processing referral system fund distribution
  733. // [✓] 0.2% trx to referral if any.
  734. InterfaceDIVIDEND(dividendContractAddress).payReferrerBonusOnly(bet.gambler, referralAmount, (bet.mainBetTRX + bet.sideBetTRX) * 1e6);
  735. }
  736.  
  737.  
  738.  
  739.  
  740. // Transfer the amount won
  741. uint256 totalWin = mainBetWin + sideBetWin + sideBetJackpotWinAmount;
  742. if (totalWin > 0)
  743. {
  744. bet.gambler.transfer(totalWin);
  745. }
  746. }
  747.  
  748.  
  749. function adminRefundBet(address _gambler, bytes32 _uniqueBetId, bytes32 _userSeed, uint256 _blockNumber, uint256[5] _rollIntegerVariables) external onlyOwner returns (bool _success)
  750. {
  751. require(!systemHalted, "System is halted");
  752.  
  753. require(_blockNumber < block.number - 100, "Too early to refund bet. Please wait 100 blocks.");
  754.  
  755. bytes32 betHash = calculateBetHash(
  756. _gambler,
  757. _uniqueBetId,
  758. _userSeed,
  759. _blockNumber,
  760. _rollIntegerVariables
  761. );
  762.  
  763. if (unfinishedBetHash_to_timestamp[betHash] == 0)
  764. {
  765. return false;
  766. }
  767. else
  768. {
  769. unfinishedBetHash_to_timestamp[betHash] = 0;
  770. _gambler.transfer((_rollIntegerVariables[2] + _rollIntegerVariables[3]) * 1e6);
  771. emit BetRefunded(betHash, _gambler, (_rollIntegerVariables[2] + _rollIntegerVariables[3]) * 1e6);
  772. return true;
  773. }
  774. }
  775.  
  776. function _calculateSideBetWin(uint256 _winningNumber, uint256 _sideBetType, uint256 _sideBetValue) private view returns (uint256)
  777. {
  778. if (_sideBetType != 0)
  779. {
  780. uint256 firstNumber = _winningNumber / 10;
  781. uint256 lastNumber = _winningNumber % 10;
  782.  
  783. if (_sideBetType == _yin)
  784. {
  785. if (firstNumber > lastNumber)
  786. {
  787. return _sideBetValue * yinMultiplier * 100;
  788. }
  789. }
  790. else if (_sideBetType == _yang)
  791. {
  792. if (firstNumber < lastNumber)
  793. {
  794. return _sideBetValue * yangMultiplier * 100;
  795. }
  796. }
  797. else if (_sideBetType == _bang)
  798. {
  799. if (_winningNumber == 0 || _winningNumber == 11 || _winningNumber == 22 || _winningNumber == 33 || _winningNumber == 44 || _winningNumber == 55 || _winningNumber == 66 || _winningNumber == 77 || _winningNumber == 88 || _winningNumber == 99)
  800. {
  801. return _sideBetValue * bangMultiplier * 100;
  802. }
  803. }
  804. else if (_sideBetType == _zero)
  805. {
  806. if (_winningNumber == 0)
  807. {
  808. return _sideBetValue * zeroMultiplier * 100;
  809. }
  810. }
  811. else if (_sideBetType == _odd)
  812. {
  813. if (_winningNumber % 2 != 0)
  814. {
  815. return _sideBetValue * oddMultiplier * 100;
  816. }
  817. }
  818. else if (_sideBetType == _even)
  819. {
  820. if (_winningNumber % 2 == 0)
  821. {
  822. return _sideBetValue * evenMultiplier * 100;
  823. }
  824. }
  825. }
  826.  
  827. return 0;
  828. }
  829.  
  830.  
  831. /**
  832. This functions allows the owner to update the sidebet jackpot variables
  833. */
  834. function updateSideBetJackpot(
  835. uint256 _sideBetJackpotMaxOdd,
  836. uint256 _sideBetJackpotFixNumber,
  837. uint256 _sideBetAmountTRXtoQualifyForMaximumJackpot,
  838. uint256 _maximumPercentageOfJackpotSizeWon,
  839. uint256 _sideBetLossPercentageForProgressiveJackpot,
  840. uint256 _jackpotSizePercentageToDividendPool
  841. ) public onlyOwner returns(string)
  842. {
  843. require(_maximumPercentageOfJackpotSizeWon <= 100);
  844. require(_jackpotSizePercentageToDividendPool <= 100);
  845. require(_maximumPercentageOfJackpotSizeWon + _jackpotSizePercentageToDividendPool <= 100);
  846. require(_sideBetLossPercentageForProgressiveJackpot <= 100);
  847.  
  848. sideBetJackpotMaxOdd = _sideBetJackpotMaxOdd;
  849. sideBetJackpotFixNumber = _sideBetJackpotFixNumber;
  850. sideBetAmountTRXtoQualifyForMaximumJackpot = _sideBetAmountTRXtoQualifyForMaximumJackpot;
  851. maximumPercentageOfJackpotSizeWon = _maximumPercentageOfJackpotSizeWon;
  852. sideBetLossPercentageForProgressiveJackpot = _sideBetLossPercentageForProgressiveJackpot;
  853. jackpotSizePercentageToDividendPool = _jackpotSizePercentageToDividendPool;
  854.  
  855. return "Sidebet Jackpot variables updated successfully";
  856. }
  857.  
  858.  
  859. function depositIntoSideBetJackpot() public payable returns (string)
  860. {
  861. totalDepositedIntoJackpot += msg.value;
  862. currentSideBetJackpotSize += msg.value;
  863. return "Successfully deposited into jackpot";
  864. }
  865.  
  866. function withdrawDepositedJackpot(uint256 _amountSun) public onlyOwner returns (string)
  867. {
  868. totalDepositedIntoJackpot = totalDepositedIntoJackpot.sub(_amountSun);
  869. currentSideBetJackpotSize = currentSideBetJackpotSize.sub(_amountSun);
  870.  
  871. msg.sender.transfer(_amountSun);
  872.  
  873. return "Successful withdrawal from jackpot";
  874. }
  875.  
  876.  
  877. /**
  878. This function just gives total balance of contract
  879. */
  880. function totalTRXbalanceContract() public view returns(uint256)
  881. {
  882. return address(this).balance;
  883. }
  884.  
  885.  
  886. /**
  887. function to deposit TRX into smart contract. It will update dividend threshold and totalDepositedTRX tracker
  888. If you dont want these things to update, then just send TRX to contract address
  889. */
  890. function depositTRX() payable public onlyOwner returns(string)
  891. {
  892. //updating totalDepositedTRX tracker
  893. totalDepositedTRX += msg.value;
  894.  
  895. //changing dividend threshold according to how much TRX deposited by owner
  896. dividendThreshold = dividendThreshold.add(msg.value);
  897.  
  898. return "Transaction successful";
  899. }
  900.  
  901. /**
  902. This function lets owner to withdraw TRX as much he deposited.
  903. Thus there is NO "exit scam" possibility, as there is no other way to take TRX out of this contract
  904. */
  905. function manualWithdrawTRX(uint256 amount) public onlyOwner returns(string)
  906. {
  907. //checking conditions
  908. require(totalDepositedTRX >= amount, 'Invalid amount');
  909.  
  910. //changing dividend threshold according to how much TRX deposited by owner
  911. dividendThreshold = dividendThreshold.sub(amount);
  912.  
  913. //updating tracker
  914. totalDepositedTRX -= amount;
  915.  
  916. //transferring the TRX to owner
  917. owner.transfer(amount);
  918.  
  919. return "Transaction successful";
  920. }
  921.  
  922.  
  923. /**
  924. Just in rare case, owner wants to transfer Tokens from contract to owner address
  925. */
  926. function manualWithdrawTokens(uint256 tokenAmount) public onlyOwner returns(string)
  927. {
  928. // no need for overflow checking as that will be done in transfer function
  929. TRONtopiaInterface(topiaTokenContractAddress).transfer(msg.sender, tokenAmount);
  930.  
  931. return "Transaction successful";
  932. }
  933.  
  934.  
  935. function withdrawPartOfRakePool(uint256 amount) external onlyOwner returns (string)
  936. {
  937. ownerRakePool = ownerRakePool.sub(amount);
  938. msg.sender.transfer(amount);
  939. return "Done";
  940. }
  941.  
  942. function withdrawFullRakePool() external onlyOwner returns (string)
  943. {
  944. msg.sender.transfer(ownerRakePool);
  945. ownerRakePool = 0;
  946. return "Done";
  947. }
  948.  
  949.  
  950.  
  951. /**
  952. Function allows owner to update the Topia contract address
  953. */
  954. function updateTopiaTokenContractAddress(address _newAddress) public onlyOwner returns(string)
  955. {
  956. require(_newAddress != address(0), 'Invalid Address');
  957. topiaTokenContractAddress = _newAddress;
  958.  
  959. return "Topia Token Contract Address Updated";
  960. }
  961.  
  962. /**
  963. Function allows owner to update the DIVIDEND contract address
  964. */
  965. function updateDividendContractAddress(address _newAddress) public onlyOwner returns(string)
  966. {
  967. require(_newAddress != address(0), 'Invalid Address');
  968. dividendContractAddress = _newAddress;
  969.  
  970. return "Dividend Contract Address Updated";
  971. }
  972.  
  973.  
  974.  
  975. /**
  976. Function allows owner to update the sidebet multiplier variables
  977. */
  978. function updateSidebetMultipliers(uint256 yinMultiplier_, uint256 yangMultiplier_, uint256 bangMultiplier_, uint256 zeroMultiplier_, uint256 oddMultiplier_, uint256 evenMultiplier_) public onlyOwner returns(string)
  979. {
  980. yinMultiplier = yinMultiplier_;
  981. yangMultiplier = yangMultiplier_;
  982. bangMultiplier = bangMultiplier_;
  983. zeroMultiplier = zeroMultiplier_;
  984. oddMultiplier = oddMultiplier_;
  985. evenMultiplier = evenMultiplier_;
  986.  
  987. return("side bet multipliers updated successfully");
  988. }
  989.  
  990.  
  991. /**
  992. Function to change max bet amount and max bet divisible amount.
  993. */
  994. function updateMaxBetMaxWin(uint256 maxBetAmount_, uint256 maxWinDivisibleAmount_ ) public onlyOwner returns(string)
  995. {
  996. maxBetAmount = maxBetAmount_;
  997. maxWinDivisibleAmount = maxWinDivisibleAmount_;
  998.  
  999. return("Max bet and max win updated successfully");
  1000. }
  1001.  
  1002. /**
  1003. Function to change minimum side bet amount
  1004. */
  1005. function updateMinimumSideBetAmount(uint256 minimumSideBetAmountTRX_) public onlyOwner returns(string)
  1006. {
  1007. minimumSideBetAmountTRX = minimumSideBetAmountTRX_;
  1008.  
  1009. return("Minimum sidebet amount updated successfully");
  1010. }
  1011.  
  1012. /**
  1013. Function to change minimum main bet amount
  1014. */
  1015. function updateMinimumMainBetAmount(uint256 minimumMainBetAmountTRX_) public onlyOwner returns(string)
  1016. {
  1017. minimumMainBetAmountTRX = minimumMainBetAmountTRX_;
  1018.  
  1019. return("Minimum sidebet amount updated successfully");
  1020. }
  1021.  
  1022. function updateRakePerMillion(uint256 _newRakePerMillion) external onlyOwner returns (string)
  1023. {
  1024. require(_newRakePerMillion < 1000000);
  1025. ownerRakePerMillion = _newRakePerMillion;
  1026. return "Done";
  1027. }
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035. //-------------------------------------------------//
  1036. //---------------- DIVIDEND SECTION ---------------//
  1037. //-------------------------------------------------//
  1038.  
  1039. uint256 public dividendThreshold; //dividend threshold
  1040. //uint256 public dividendPaidAllTime;
  1041.  
  1042. /**
  1043. * Function to view available dividend amount
  1044. */
  1045. function displayAvailableDividend() public view returns (bool, uint256)
  1046. {
  1047. if (address(this).balance >= dividendThreshold + currentSideBetJackpotSize)
  1048. {
  1049. return (true, address(this).balance - dividendThreshold - currentSideBetJackpotSize);
  1050. }
  1051. else
  1052. {
  1053. return (false, dividendThreshold + currentSideBetJackpotSize - address(this).balance);
  1054. }
  1055. }
  1056.  
  1057.  
  1058. /**
  1059. This function called by token contract, while actual dividend distribution
  1060. This also will be called by Dividend contract, to take some excessive fund to reduce the risk of loss in case of attack!!
  1061. */
  1062. function requestDividendPayment(uint256 dividendAmount) public returns(bool)
  1063. {
  1064. require(msg.sender == topiaTokenContractAddress || msg.sender == dividendContractAddress, 'Unauthorised caller');
  1065. msg.sender.transfer(dividendAmount);
  1066. return true;
  1067. }
  1068.  
  1069.  
  1070. /**
  1071. Function to update dividend threshold
  1072. */
  1073. function updateDividendThreshold(uint256 _dividendThreshold) public onlyOwner returns(string)
  1074. {
  1075. require(_dividendThreshold > 0, 'Invalid Amount');
  1076. dividendThreshold = _dividendThreshold;
  1077.  
  1078. return "Dividend threshold updated";
  1079. }
  1080.  
  1081. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement